目录


数据结构是为了便于存储不同类型的数据而设计的。R中常用的数据结构包括:

  • 同质数据类型(homogeneous data types),即所存储的一定是相同类型的 元素,包括向量、矩阵、多维数组;

  • 异质数据类型(heterogeneous data types),即可以存储不同类型的元素, 这大大提高了存储的灵活性,但同时也降低了存储效率和运行效率,包括列 表、数据框。

  • 另外,还有字符串、日期时间数据、时间序列数据。

1.向量(一维数据)

  • 向量是由一组相同类型的原始值构成的序列,可以是一组数值、一组逻辑值、一 组字符串等;
  • 常用的向量有:数值向量、逻辑向量、字符向量

1.1数值向量

(1) 数值向量就是由数值组成的向量,单个数值是长度为 1 的数值向量

1
2
x <- 1.5
x
## [1] 1.5
  • 可以用 numeric() 来创建全为 0 的指定长度的数值向量:
1
numeric(10)
##  [1] 0 0 0 0 0 0 0 0 0 0
  • 经常用函数 c()实现将多个对象合并到一起:
1
c(1, 2, 3, 4, 5)
## [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:5 # 同seq(5)或seq(1,5)
## [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
2
x = 1:3
rep(x, 2)
## [1] 1 2 3 1 2 3
1
rep(x, each=2)
## [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 中,两个不同长度的向量做运算,短的会自动循环补齐以配合长的:

1
2:3+1:5
## 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")
## [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
v1[2:4] # 第2-4个元素
## [1] 2 3 4
1
v1[-3] # 除了第 3 个之外的元素
## [1] 1 2 4

-也可以放任意位置的数值向量,但是注意不能既放正数又放负数:

1
v1[c(1,3)]
## [1] 1 3
1
#v1[c(1, 2, -3)] # 报错
  • 访问不存在的位置也是可以的,返回 NA:
1
v1[3:6]
## [1]  3  4 NA NA

(2) 使用逻辑向量来访问

  • 输入与向量相同长度的逻辑向量,以此决定每一个元素是否要被获取:
1
v1[c(TRUE, FALSE, TRUE, FALSE)]
## [1] 1 3

(3) 对向量子集进行赋值,替换相应元素

1
2
v1[2] <- 0
v1
## [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
2
v1[v1 <= 2] <- 0
v1
## [1] 3 0 0 3
1
which.max(v1) # 返回向量v1中最大值所在的位置
## [1] 1
1
which.min(v1) # 返回向量v1中最小值所在的位置
## [1] 2

注意: 若对不存在的位置赋值,前面将用 NA 补齐:

1
2
v1[10] <- 8
v1
##  [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
  • 命名后,就可以通过名字来访问向量元素:
1
x[c("a", "c")]
## a c 
## 1 3
1
x[c("a", "a", "c")] # 重复访问也是可以的
## a a c 
## 1 1 3
1
x["d"] # 访问不存在的名字
## <NA> 
##   NA
  • 获取向量元素的名字:
1
names(x)
## [1] "a" "b" "c"
  • 更改向量元素的名字:
1
2
names(x) <- c("x", "y", "z")
x["z"]
## z 
## 3
  • 移除向量元素的名字:
1
2
names(x) <- NULL
x
## [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(),基本格式:
sort(x, decreasing=FALSE, na.last=FALSE, ...)
其中,
x:为排序对象(数值型或字符型);
decreasing:默认为 FALSE 即升序,TURE 为降序;
na.last:默认为 FALSE,若为 TRUE,则将向量中的 NA 值放到序列末尾。
函数rank(),返回值是该向量中对应元素的“排名”。
函数order(),返回值是对应“排名”的元素所在向量中的位置。
1
x<-c(1,5,8,2,9,7,4); x
## [1] 1 5 8 2 9 7 4
1
sort(x)
## [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
  • 若一个维度空缺,则选出该维度的所有元素:
1
m1[1,] # 提取第1行,所有列元素
## 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
m1[3:7]
## [1] 3 4 5 6 7

由于向量只包含相同类型的元素,矩阵也是如此。所以它们的操作方式也相似。若输 入一个不等式,则返回同样大小的逻辑矩阵:

1
m1 > 3
##       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构建多维数组子集

  • 第3个维度姑且称为“页”
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
1
a1[,,2] # 提取第2页的所有元素
##    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