数据结构是为了便于存储不同类型的数据而设计的。R中常用的数据结构包括:
1.向量(一维数据)
- 向量是由一组相同类型的原始值构成的序列,可以是一组数值、一组逻辑值、一
组字符串等;
- 常用的向量有:数值向量、逻辑向量、字符向量
1.1数值向量
(1) 数值向量就是由数值组成的向量,单个数值是长度为 1 的数值向量
## [1] 1.5
- 可以用
numeric()
来创建全为 0 的指定长度的数值向量:
## [1] 0 0 0 0 0 0 0 0 0 0
## [1] 1 2 3 4 5
1
|
c(1, 2, c(3, 4, 5)) # 将多个数值向量合并成一个数值向量
|
## [1] 1 2 3 4 5
(2)创建等差的数值向量
用 : 或函数 seq() 可以创建等差的数值向量。seq() 的基本格式为:
seq(from, to, by, length.out, along.with, ...)
其中,
from:设置首项(默认为 1);
to:设置尾项;
by:设置等差值(默认为 1 或 -1);
length.out:设置序列长度;
along.with:以该参数的长度作为序列长度。
## [1] 1 2 3 4 5
1
|
seq(1, 10, 2) # 从1开始, 到10结束, 步长为2
|
## [1] 1 3 5 7 9
(3) 创建重复的数值向量
函数 rep(),基本格式为:
rep(x, times,length.out, each, ...)
其中,
x:为要重复的序列;
times:设置序列重复次数;
length.out:设置产生的序列的长度;
each:设置每个元素分别重复的次数(默认为 1)。
## [1] 1 2 3 1 2 3
## [1] 1 1 2 2 3 3
1
|
rep(x, c(2,1,2)) # 按照规则重复序列中的各元素
|
## [1] 1 1 2 3 3
1
|
rep(x, each=2, length.out=4)
|
## [1] 1 1 2 2
1
|
rep(x, each=2, times=3)
|
## [1] 1 1 2 2 3 3 1 1 2 2 3 3 1 1 2 2 3 3
注意: 在 R
中,两个不同长度的向量做运算,短的会自动循环补齐以配合长的:
## Warning in 2:3 + 1:5: 长的对象长度不是短的对象长度的整倍数
## [1] 3 5 5 7 7
1.2逻辑向量
- 逻辑向量,是一组逻辑值(TRUE 或 FALSE, 简写为 T 或 F
也可以)的向量。
1
|
c(1, 2) > c(2, 1) # 等价于c(1 > 2, 2 > 1)
|
## [1] FALSE TRUE
1
|
c(2, 3) > c(1, 2, -1, 3) # 等价于c(2 > 1, 3 > 2, 2 > -1, 3 > 3)
|
## [1] TRUE TRUE TRUE FALSE
- 除了比较运算符外,还可以用 %in% 判断元素是否属于集合:
1
|
c(1, 4) %in% c(1, 2, 3) # 左边向量每一个元素是否属于右边集合
|
## [1] TRUE FALSE
注: match(v1, v2) 逐个检查向量 v1 中元素是否在向量 v2
中,若是则返回该元素, 否则返回 NA
1.3字符向量
- 字符(串)向量,是一组字符串组成的向量,R
中单引号和双引号都可以用来生 成字符向量。
## [1] "hello, world!"
## [1] "Hello" "World"
1
|
c("Hello", "World") == "Hello, World"
|
## [1] FALSE FALSE
- 要想字符串中出现单引号或双引号,需要用转义符
\
来做转义,或者单双引号错 开,用函数 cat()
生成字符串:
1
|
cat("Is \"You\" a Chinese name?")
|
## Is "You" a Chinese name?
1
|
cat('Is "You" a Chinese name?')
|
## Is "You" a Chinese name?
1
|
'Is "You" a Chinese name?'
|
## [1] "Is \"You\" a Chinese name?"
注: R 中还有不常用的复数向量、原(raw)向量。
1.4构建向量子集
(1) 使用元素的位置来访问(R 中索引是从 1 开始的)
1
2
|
v1 <- c(1, 2, 3, 4)
v1[2] # 第2个元素
|
## [1] 2
## [1] 2 3 4
## [1] 1 2 4
-也可以放任意位置的数值向量,但是注意不能既放正数又放负数:
## [1] 1 3
## [1] 3 4 NA NA
(2) 使用逻辑向量来访问
- 输入与向量相同长度的逻辑向量,以此决定每一个元素是否要被获取:
1
|
v1[c(TRUE, FALSE, TRUE, FALSE)]
|
## [1] 1 3
(3) 对向量子集进行赋值,替换相应元素
## [1] 1 0 3 4
1
2
|
v1[2:4] <- c(0, 1, 3)
v1
|
## [1] 1 0 1 3
1
2
|
v1[c(TRUE, FALSE, TRUE, FALSE)] <- c(3, 2)
v1
|
## [1] 3 0 2 3
(4) 用逻辑条件来选择元素或赋值
1
|
v1[v1 <= 2] # 同v1[which(v1 <= 2)]或subset(v1, v1<=2)
|
## [1] 0 2
1
|
v1[v1 ^ 2 - v1 + 1 >= 2]
|
## [1] 3 2 3
## [1] 3 0 0 3
1
|
which.max(v1) # 返回向量v1中最大值所在的位置
|
## [1] 1
1
|
which.min(v1) # 返回向量v1中最小值所在的位置
|
## [1] 2
注意: 若对不存在的位置赋值,前面将用 NA 补齐:
## [1] 3 0 0 3 NA NA NA NA NA 8
(5) 对向量元素命名
1
2
|
x <- c(a = 1, b = 2, c = 3)
x
|
## a b c
## 1 2 3
## a c
## 1 3
1
|
x[c("a", "a", "c")] # 重复访问也是可以的
|
## a a c
## 1 1 3
## <NA>
## NA
## [1] "a" "b" "c"
1
2
|
names(x) <- c("x", "y", "z")
x["z"]
|
## z
## 3
## [1] 1 2 3
(6)[ ] 与 [[ ]] 的区别
[ ]
可以提取对象的子集,[[ ]]
`可以提取对象中的元素。
- 二者的区别:以向量为例,可以将一个向量比作 10
盒糖果,你可以使用
[ ]
获取其中的3盒糖果,使用[[ ]]
打开盒子并从中取出一颗糖果。
- 对于未对元素命名的向量,使用
[ ]
和[[ ]]
取出一个元素会产生相同的结果。但已对元素命名的向量,二者会产生不同的结果:
1
2
|
x <- c(a = 1, b = 2, c = 3,d=4)
x["a"] # 取出标签为"a"的糖果盒
|
## a
## 1
1
|
x[["a"]] # 取出标签为"a"的糖果盒里的糖果
|
## [1] 1
注意: 由于
[[ ]]
只能用于提取出一个元素,因此不适用于提取多个元素的情况,所以[[ ]]
不能用于负整数,因为负整数意味着提取除特定位置之外的所有元素。
使用含有不存在的位置或名称来创建向量子集时将会产生缺失值。但当使用 [[
]]
提取一个位置超出范围或者对应名称不存在的元素时,该命令将会无法运行并产生错误信息。
以下三个语句会报错:
1
2
3
|
#x[[c(1, 2)]]
#x[[-1]]
#x[["d"]]
|
(7) 对向量排序
sort(x, decreasing=FALSE, na.last=FALSE, ...)
其中,
x:为排序对象(数值型或字符型);
decreasing:默认为 FALSE 即升序,TURE 为降序;
na.last:默认为 FALSE,若为 TRUE,则将向量中的 NA 值放到序列末尾。
函数rank(),返回值是该向量中对应元素的“排名”。
函数order(),返回值是对应“排名”的元素所在向量中的位置。
## [1] 1 5 8 2 9 7 4
## [1] 1 2 4 5 7 8 9
1
|
order(x) # 默认升序,排名第2的元素在原向量的第4个位置
|
## [1] 1 4 7 2 6 3 5
1
|
rank(x) # 默认升序,第2个元素排名第4位
|
## [1] 1 4 6 2 7 5 3
注: 函数 rev(), 可将序列进行反转,即 1,2,3 变成 3,2,1
2.矩阵(二维数据)
矩阵是一个用两个维度表示和访问的向量。因此,适用于向量的性质和方法大多
也适用于矩阵:矩阵也要求元素是同一类型,数值矩阵、逻辑矩阵等。
2.1用 matrix() 函数将一个向量变成矩阵,其基本格式为:
matrix(x, nrow, ncol, byrow=FALSE, dimnames, ...)
其中,
x:为数据向量作为矩阵的元素;
nrow:设定行数;
ncol:设定列数;
byrow:设置是否按行填充,默认为 FALSE(按列填充);
dimnames:用字符型向量表示矩阵的行名和列名。
1
2
3
|
matrix(c(1, 2, 3,
4, 5, 6,
7, 8, 9), nrow=3, byrow=FALSE)
|
## [,1] [,2] [,3]
## [1,] 1 4 7
## [2,] 2 5 8
## [3,] 3 6 9
1
2
3
|
matrix(c(1, 2, 3,
4, 5, 6,
7, 8, 9), nrow=3, byrow=TRUE)
|
## [,1] [,2] [,3]
## [1,] 1 2 3
## [2,] 4 5 6
## [3,] 7 8 9
1
2
|
matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9), nrow=3, byrow=TRUE,
dimnames=list(c("r1", "r2", "r3"), c("c1", "c2", "c3")))
|
## c1 c2 c3
## r1 1 2 3
## r2 4 5 6
## r3 7 8 9
1
2
3
4
|
m1 <- matrix(c(1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12), ncol = 4)
rownames(m1) <- c("r1", "r2", "r3")
colnames(m1) <- c("c1", "c2", "c3", "c4")
m1
|
## c1 c2 c3 c4
## r1 1 4 7 10
## r2 2 5 8 11
## r3 3 6 9 12
-特殊矩阵
1
|
diag(1:4, nrow=4) # 对角矩阵
|
## [,1] [,2] [,3] [,4]
## [1,] 1 0 0 0
## [2,] 0 2 0 0
## [3,] 0 0 3 0
## [4,] 0 0 0 4
注: 函数 as.vector(), 可将矩阵转化为向量,元素按列读取。
2.2构建矩阵子集
- 矩阵是用两个维度表示和访问的向量,可以用一个二维存取器
[ , ]
来访问,这类似于构建向量子集时用的一维存取器[]
。
- 可以为每个维度提供一个向量来确定一个矩阵的子集。方括号中的第 1
个参数是 行选择器,第 2
个参数是列选择器。与构建向量子集一样,可以在两个维度中使
用数值向量、逻辑向量和字符向量。
1
|
m1[1,2] # 提取第1行,第2列的单个元素
|
## [1] 4
1
|
m1[1:2, 2:4] # 提取第1至2行,第2至4列的元素
|
## c2 c3 c4
## r1 4 7 10
## r2 5 8 11
1
|
m1[c("r1","r3"), c("c1","c3")] # 提取行名为r1和r3,列名为c1和c3的元素
|
## c1 c3
## r1 1 7
## r3 3 9
## c1 c2 c3 c4
## 1 4 7 10
1
|
m1[, 2:4] # 提取所有行,第2至4列的元素
|
## c2 c3 c4
## r1 4 7 10
## r2 5 8 11
## r3 6 9 12
- 负数表示在构建矩阵子集时可排除该位置,这和向量中的用法一致:
1
|
m1[-1,] # 提取除了第1行之外的所有元素
|
## c1 c2 c3 c4
## r2 2 5 8 11
## r3 3 6 9 12
1
|
m1[,-c(2,4)] # 提取除了第2和4列之外的所有元素
|
## c1 c3
## r1 1 7
## r2 2 8
## r3 3 9
注意,矩阵是一个用两个维度表示和访问的向量,但它本质上仍然是一个向量。因
此,向量的一维存取器也可以用来构建矩阵子集:
## [1] 3 4 5 6 7
由于向量只包含相同类型的元素,矩阵也是如此。所以它们的操作方式也相似。若输
入一个不等式,则返回同样大小的逻辑矩阵:
## c1 c2 c3 c4
## r1 FALSE TRUE TRUE TRUE
## r2 FALSE TRUE TRUE TRUE
## r3 FALSE TRUE TRUE TRUE
根据它就可以选择矩阵元素或赋值:
1
|
m1[m1 > 3] # 注意选出来的结果是向量
|
## [1] 4 5 6 7 8 9 10 11 12
- 矩阵运算
A+B
, A-B
, A*B
, A/B
:矩阵四则运算,要求矩阵同型,类似
Matlab 中 的点运算,分别将对应位置的元素做四则运行;
A %*% B
:矩阵乘法,要求 A 的列数 = B 的行数。
3.多维数组(高维数据)
- 向量/矩阵向更高维度的自然推广。具体来说,多维数组就是一个维度更高(通常
大于 2)、可访问的向量。数组也要求元素是同一类型。
3.1创建多维数组
- 用函数
array()
将一个向量变成多维数组,基本格式为:
array(x,dim=...,dimnames=...)
其中,
x:为数据向量作为多维数组的元素;
dim:设置多维数组各维度的维数;
dimnames:设置多维数组各维度的名称。
1
2
|
a1 <- array(1:24, dim = c(3, 4, 2))
a1
|
## , , 1
##
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
##
## , , 2
##
## [,1] [,2] [,3] [,4]
## [1,] 13 16 19 22
## [2,] 14 17 20 23
## [3,] 15 18 21 24
1
2
3
|
a1 <- array(1:24, dim=c(3, 4, 2),
dimnames=list(c("r1","r2","r3"),
c("c1","c2","c3","c4"), c("k1","k2")));a1
|
## , , k1
##
## c1 c2 c3 c4
## r1 1 4 7 10
## r2 2 5 8 11
## r3 3 6 9 12
##
## , , k2
##
## c1 c2 c3 c4
## r1 13 16 19 22
## r2 14 17 20 23
## r3 15 18 21 24
1
2
3
4
|
a1 <- array(1:24, dim=c(3, 4, 2))
dimnames(a1) <- list(c("r1","r2","r3"),
c("c1","c2","c3","c4"), c("k1","k2"))
a1
|
## , , k1
##
## c1 c2 c3 c4
## r1 1 4 7 10
## r2 2 5 8 11
## r3 3 6 9 12
##
## , , k2
##
## c1 c2 c3 c4
## r1 13 16 19 22
## r2 14 17 20 23
## r3 15 18 21 24
注: list 是生成列表(见后文)
3.2构建多维数组子集
1
|
a1[2,4,2] # 提取第2行,第4列,第2页的元素
|
## [1] 23
1
|
a1["r2","c4","k2"] # 提取第r2行,第c4列,第k2页的元素
|
## [1] 23
1
|
a1[1,2:4,1:2] # 提取第1行,第2至4列,第1至2页的元素
|
## k1 k2
## c2 4 16
## c3 7 19
## c4 10 22
## c1 c2 c3 c4
## r1 13 16 19 22
## r2 14 17 20 23
## r3 15 18 21 24
1
|
dim(a1) # 返回多维数组a1的各维度的维数
|
## [1] 3 4 2