6  R的数据结构

6.1 本章学习目标(🐈)

  • 理解数据类型与数据结构的区别,建立“数据是什么 vs 如何组织”的认知
  • 掌握 R 中常见数据结构(vector、matrix、array、list、data frame)的基本特点
  • 理解向量及其向量化运算在 R 计算中的核心作用
  • 能根据数据分析需求选择合适的数据结构进行数据组织与处理

6.2 数据类型与数据结构的区别

在学习 R 编程时,很多初学者容易混淆 数据类型(data type)数据结构(data structure)
实际上,它们解决的是两个不同层次的问题。

简单理解:

数据类型决定“数据是什么”,数据结构决定“数据如何组织”。

例如:

  • 5 是一个 数值型(numeric)
  • "R" 是一个 字符型(character)

这些都是 数据类型

但是在实际分析中,我们往往需要存储 很多数据,例如:

  • 多个数值
  • 多个变量
  • 一整张数据表

这时就需要 数据结构 来组织数据。

可以用一个简单的类比理解:

概念 作用 类比
数据类型 描述单个数据的性质 砖头的材料
数据结构 描述数据如何组织在一起 房子的结构

例如:

  • 数值型数据可以组成 向量
  • 多个向量可以组成 数据框

因此:

数据类型是基础,数据结构是数据的组织形式。


6.3 R 中常见的数据结构

R 中最重要的五种数据结构包括:

  • 向量(vector)
  • 矩阵(matrix)
  • 数组(array)
  • 列表(list)
  • 数据框(data frame)

其中:

  • 向量是最基础的数据结构
  • 其他结构通常都是向量的扩展

6.4 向量(Vector)

向量是 R 中最基本的数据结构。

向量的特点:

  • 相同数据类型 的元素组成
  • 元素按 顺序排列

可以使用 c()函数创建向量

Code
x <- c(1, 2, 3, 4, 5)
x
[1] 1 2 3 4 5

查看向量信息:

Code
typeof(x)
[1] "double"
Code
length(x)
[1] 5

向量也可以是其他类型:

Code
y <- c("A", "B", "C")
z <- c(TRUE, FALSE, TRUE)

注意:

向量中的元素必须是同一种数据类型。

6.4.1 向量化运算:R语言的核心思想

在 R 语言中,向量化运算(Vectorized Operations) 是一个非常重要的概念。

很多人认为:

向量化运算是 R 语言的灵魂。

这是因为 R 的设计初衷就是 用于统计计算和数据分析,而这些任务通常需要对 一整组数据同时进行计算


向量化运算指的是:

一次运算同时作用于整个向量,而不是逐个元素计算。

例如:

Code
x <- c(1,2,3,4)

x + 1
[1] 2 3 4 5

输出结果:

2 3 4 5

在这里:

  • 1 自动作用于向量中的每一个元素
  • 不需要使用循环

向量化运算具有三个重要优点:

优点 解释
代码更简洁 不需要循环
计算更快 R 内部使用 C 语言优化
更符合数学表达 表达方式更直观

例如使用循环:

Code
x <- c(1,2,3,4)
y <- numeric(length(x))
for(i in 1:length(x)){
  y[i] <- x[i] + 1
}
y
[1] 2 3 4 5

使用向量化

Code
x <- c(1,2,3,4)

x + 1
[1] 2 3 4 5

可以看到:

向量化代码更加简单。


6.4.2 向量之间的运算

R 可以直接对 两个向量进行运算

Code
x <- c(1,2,3)
y <- c(4,5,6)
x + y
[1] 5 7 9

结果:

5 7 9

这相当于:

(1+4, 2+5, 3+6)

同样可以进行:

x - y
x * y
x / y

6.4.3 向量与标量运算

R 还支持 向量与单个数字运算

Code
x <- c(10,20,30)
x * 2
[1] 20 40 60

结果:

20 40 60

这里的 2 会自动作用到向量的每个元素。


6.4.4 逻辑向量运算

向量化运算不仅适用于数值,还适用于 逻辑判断

Code
x <- c(3,7,2,9)
x > 5
[1] FALSE  TRUE FALSE  TRUE

结果:

FALSE TRUE FALSE TRUE

这在数据筛选中非常重要。

例如:

Code
x[x > 5]
[1] 7 9

结果:

7 9

6.4.5 常见的向量化函数

R 中大量函数都是向量化函数,例如:

函数 作用
sum() 求和
mean() 求平均
sqrt() 开平方
log() 对数
abs() 绝对值

示例:

Code
x <- c(1,4,9,16)
sqrt(x)
[1] 1 2 3 4

输出:

1 2 3 4

6.4.6 向量长度不一致的情况

当两个向量长度不一致时,R 会进行 循环回收(recycling)

Code
x <- c(1,2,3,4)
y <- c(10,20)
x + y
[1] 11 22 13 24

R 会自动扩展 y

10 20 10 20

结果:

11 22 13 24

如果长度不能整除,R 会给出警告。


6.4.7 向量是 R最重要的数据结构

在 R 中:

  • 矩阵是 向量的二维形式
  • 数组是 多维向量
  • 数据框的每一列也是 向量

因此可以说:

向量是 R 所有数据结构的基础。

理解向量化运算,就等于理解了 R 语言的计算方式。


假设我们有一组实验数据:

Code
yield <- c(5.2, 6.1, 5.8, 6.5, 5.9)

计算平均值:

Code
mean(yield)
[1] 5.9

计算标准化值:

Code
yield - mean(yield)
[1] -0.7  0.2 -0.1  0.6  0.0

整个过程不需要循环。


6.5 矩阵(Matrix)

矩阵是 二维数据结构, 可以理解为具有行和列的向量

创建矩阵最常用matrix()函数(把一个数值向量折叠成矩阵)

Code
m <- matrix(1:6, nrow = 2, ncol = 3)
m
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

矩阵结构:

Code
dim(m)
[1] 2 3

矩阵特点:

  • 所有元素 必须是同一种数据类型
  • 具有 行和列

访问元素:

Code
m[1,2]
[1] 3

6.6 数组(Array)

数组是 多维矩阵

例如:

  • 三维数据
  • 多个矩阵组合

创建数组常用array()函数

Code
a <- array(1:12, dim = c(2,3,2))
a
, , 1

     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

, , 2

     [,1] [,2] [,3]
[1,]    7    9   11
[2,]    8   10   12

数组特点:

  • 可以有 多个维度
  • 元素类型必须一致

查看维度:

Code
dim(a)
[1] 2 3 2

6.7 列表(List)

列表是一种 非常灵活的数据结构

列表的特点:

可以包含不同类型的数据。

创建列表最常用list()函数

Code
my_list <- list(
  name = "Alice",
  age = 25,
  score = c(80, 90, 85)
)

my_list
$name
[1] "Alice"

$age
[1] 25

$score
[1] 80 90 85

查看结构:

Code
str(my_list)
List of 3
 $ name : chr "Alice"
 $ age  : num 25
 $ score: num [1:3] 80 90 85

列表常用于:

  • 存储复杂对象
  • 存储模型结果
  • 存储多种类型数据

6.8 数据框(Data Frame)

数据框是 R 中最常用的数据结构之一。

可以理解为:

类似 Excel 表格的数据结构

创建数据框最常用data.frame()函数

Code
df <- data.frame(
  id = 1:3,
  name = c("A", "B", "C"),
  score = c(85, 90, 88)
)
df
  id name score
1  1    A    85
2  2    B    90
3  3    C    88

查看结构:

Code
str(df)
'data.frame':   3 obs. of  3 variables:
 $ id   : int  1 2 3
 $ name : chr  "A" "B" "C"
 $ score: num  85 90 88

数据框特点:

  • 列长度必须一致
  • 不同列可以有不同数据类型

6.9 R 数据结构之间的关系

可以用下面的关系理解:

数据结构 维度 数据类型要求
vector 一维 相同类型
matrix 二维 相同类型
array 多维 相同类型
list 一维 可不同类型
data frame 二维 每列相同,但列之间可不同

6.10 R 的原子类型与列表类型

在 R 语言中,数据对象大体可以分为两类:

  • 原子类型(atomic types)
  • 列表类型(list)

理解这两种类型,有助于理解 R 的数据结构。


6.10.1 原子类型(Atomic Types)

原子类型是 R 中最基本的数据类型

它们的特点是:

一个对象中的所有元素必须是同一种类型。

R 中常见的原子类型包括:

类型 示例
numeric 3.14
integer 3L
logical TRUE
character "R"
complex 2+3i

例如:

Code
x <- c(1,2,3,4)
typeof(x)
[1] "double"

这里 x 是一个 数值型向量,所有元素类型相同。


6.10.2 列表类型(List)

列表是一种 更灵活的数据结构

它的特点是:

列表中的元素可以是不同类型的数据。

例如:

Code
my_list <- list(
  name = "Alice",
  age = 25,
  score = c(90,85,88)
)

str(my_list)
List of 3
 $ name : chr "Alice"
 $ age  : num 25
 $ score: num [1:3] 90 85 88

可以看到:

  • name 是字符型
  • age 是数值型
  • score 是数值向量

6.10.3 原子类型与列表的区别

特征 原子类型 列表
元素类型 必须相同 可以不同
常见形式 向量、矩阵、数组 list
用途 数值计算 存储复杂对象

简单示例:

Code
x <- c(1,2,3)
y <- list(1,"A",TRUE)

typeof(x)
[1] "double"
Code
typeof(y)
[1] "list"

结果:

  • x 是原子向量
  • y 是列表

6.11 本章总结

在 R 中:

  • 数据类型 描述数据的性质
  • 数据结构 描述数据如何组织

常见数据类型包括:

  • numeric
  • integer
  • logical
  • character
  • factor
  • complex

常见数据结构包括:

  • vector
  • matrix
  • array
  • list
  • data frame

理解数据类型和数据结构,是学习 R 数据分析的重要基础。

图6.1本次课程主要讲授内容

6.12 练习

下面练习用于熟悉 R 中的矩阵运算。请完成代码并写出运行结果。


6.12.1 练习1:创建矩阵

使用 matrix() 函数创建一个 2×3 的矩阵:

1 2 3
4 5 6

提示:

matrix()

要求:

  1. 创建矩阵 A
  2. 查看矩阵内容
  3. 查看矩阵维度

6.12.2 练习2:矩阵加法

创建两个矩阵:

A =
1 2
3 4

B =
5 6
7 8

要求:

  1. 创建矩阵 A
  2. 创建矩阵 B
  3. 计算 A + B

思考:

矩阵加法需要满足什么条件?


6.12.3 练习3:矩阵乘法

给定两个矩阵:

A =
1 2
3 4

B =
5 6
7 8

要求:

  1. 使用 %*% 计算矩阵乘法 A × B
  2. 写出结果矩阵

提示:

A %*% B

思考:

矩阵乘法与普通乘法有什么不同?


6.12.4 练习4:矩阵转置

给定矩阵:

A =
1 2 3
4 5 6

要求:

  1. 创建矩阵 A
  2. 计算矩阵转置

提示:

t(A)

6.12.5 练习5:矩阵行列式

给定矩阵:

A =
2 1
3 4

要求:

  1. 创建矩阵 A
  2. 计算矩阵的行列式

提示:

det(A)

6.12.6 练习6:矩阵求逆

给定矩阵:

A =
4 7
2 6

要求:

  1. 创建矩阵 A
  2. 计算矩阵的逆矩阵

提示:

solve(A)

思考:

什么情况下矩阵不能求逆?


6.12.7 练习7:解线性方程组

求解以下方程组:

2x + y = 5
x + 3y = 6

步骤:

  1. 写出系数矩阵 A
  2. 写出常数向量 b
  3. 使用 solve() 求解

提示:

solve(A, b)

6.13 矩阵的实际应用:图像

一张图片本质上是一个矩阵。

每一个像素,对应矩阵中的一个数值。以鸢尾花为例 鸢尾花

Code
library(png)
img <- readPNG("images/iris.png")
dim(img)
[1] 859 840   4

图片的维度通常为:

  • 高度
  • 宽度
  • 颜色通道(RGB)

6.13.1 显示图片

Code
plot(1:2, type = "n", xlab = "", ylab = "", axes = FALSE)
rasterImage(img, 1, 1, 2, 2)


6.13.2 转换为矩阵

Code
p <- img[,,1]
image(p,col = gray.colors(256))

这说明:

矩阵不仅是数学结构,也是图像数据的本质表示方式。