2.5 数组 (array)和矩阵 (matrix)简介

向量是一维的数据。数组是多维的数据。矩阵是二维的数据,因此矩阵是数组的一种特殊情况。

Dataframe不是矩阵(虽然都是方的,且取子集方法和矩阵有近似之处。 矩阵是二维的,仅包含一种数据类型数组。 Dataframe是一个二维的列表,不同列(即列表的分量)可以存储不同的数据类型

本质上,矩阵和数组都是以向量的形式存储的。它们只是额外地拥有dim(即“dimensions”,维度)属性。我们可以用dim()函数从向量创建数组/矩阵:

A <- 1:48 
dim(A) <- c(6,8) 
A
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,]    1    7   13   19   25   31   37   43
#> [2,]    2    8   14   20   26   32   38   44
#> [3,]    3    9   15   21   27   33   39   45
#> [4,]    4   10   16   22   28   34   40   46
#> [5,]    5   11   17   23   29   35   41   47
#> [6,]    6   12   18   24   30   36   42   48

可以看到我们创建了一个二维的数组, 即一个4行6列的矩阵。

is.array(A)
#> [1] TRUE
is.matrix(A)
#> [1] TRUE

它多出来的dim属性可以用attr()(即“attributes”,属性)函数来查看:

attributes(A)
#> $dim
#> [1] 6 8

注意24个数字排列的方式。第一个维度是行,所以先把4行排满,随后再使用下一个维度(列),使用第2列继续排4行,就像数字一样,(十进制中)先把个位从零数到9,再使用第二个位数(十位),以此类推。下面三维和四维的例子可能会更清晰。

同时注意最左边和最上边的[1,], [,3]之类的标记。你应该猜出来了,这些是索引. 假设你要抓取第五行第三列的数值:

A[5,3]
#> [1] 17

或者第三行的全部数值:

A[3,]
#> [1]  3  9 15 21 27 33 39 45

或者第四列的全部数值:

A[,4]
#> [1] 19 20 21 22 23 24

接下来我们再看一个三维的例子(还是用1-48):

dim(A) <- c(2,8,3)
A
#> , , 1
#> 
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,]    1    3    5    7    9   11   13   15
#> [2,]    2    4    6    8   10   12   14   16
#> 
#> , , 2
#> 
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,]   17   19   21   23   25   27   29   31
#> [2,]   18   20   22   24   26   28   30   32
#> 
#> , , 3
#> 
#>      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
#> [1,]   33   35   37   39   41   43   45   47
#> [2,]   34   36   38   40   42   44   46   48

它生成了三个二维的矩阵。在每个2*8的矩阵存储满16个元素后,第三个维度就要加一了。每个矩阵开头的, , x正是第三个维度的值。同理,我们可以生成四维的数组(这是另外一种改变维度的方法。dim作为一个属性 (attribute), 可以通过attr()函数赋值。attr()还可以赋值其他的属性。):

attr(A, "dim") <- c(3,4,2,2)
A
#> , , 1, 1
#> 
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    4    7   10
#> [2,]    2    5    8   11
#> [3,]    3    6    9   12
#> 
#> , , 2, 1
#> 
#>      [,1] [,2] [,3] [,4]
#> [1,]   13   16   19   22
#> [2,]   14   17   20   23
#> [3,]   15   18   21   24
#> 
#> , , 1, 2
#> 
#>      [,1] [,2] [,3] [,4]
#> [1,]   25   28   31   34
#> [2,]   26   29   32   35
#> [3,]   27   30   33   36
#> 
#> , , 2, 2
#> 
#>      [,1] [,2] [,3] [,4]
#> [1,]   37   40   43   46
#> [2,]   38   41   44   47
#> [3,]   39   42   45   48

观察每个矩阵开头的, , x, y. x是第三个维度,y是第四个维度。每个二位矩阵存满后,第三个维度(x)加一。x达到上限后,第四个维度(y)再加1。

类似二维矩阵,你可以通过索引任意抓取数据,比如:

A[ ,3 , , ] #每个矩阵第3列的数据,即所有第二个维度为3的数值
#> , , 1
#> 
#>      [,1] [,2]
#> [1,]    7   19
#> [2,]    8   20
#> [3,]    9   21
#> 
#> , , 2
#> 
#>      [,1] [,2]
#> [1,]   31   43
#> [2,]   32   44
#> [3,]   33   45

2.5.1 给矩阵和列表的维度命名

假设我们记录了3种药物(chloroquine, artemisinin, doxycycline) 对5种疟原虫(P. falciparum, P. malariae, P. ovale, P. vivax, P. knowlesi)的疗效,其中每个药物对每种疟原虫做6次实验(这里用的是随机生成的数字)。为了记录数据,我们可以做3个65的矩阵,即一个65*3的数组。

B <- runif(90, 0, 1) #从均匀分布中取90个0到1之间的数
dim(B) <- c(6, 5, 3) #注意顺序
B
#> , , 1
#> 
#>        [,1]  [,2]   [,3]  [,4]  [,5]
#> [1,] 0.6922 0.898 0.5718 0.823 0.628
#> [2,] 0.1419 0.473 0.0593 0.731 0.330
#> [3,] 0.0484 0.269 0.4750 0.257 0.922
#> [4,] 0.8174 0.699 0.6339 0.736 0.890
#> [5,] 0.8560 0.435 0.8243 0.445 0.147
#> [6,] 0.7077 0.620 0.7473 0.230 0.341
#> 
#> , , 2
#> 
#>       [,1]  [,2]   [,3]  [,4]  [,5]
#> [1,] 0.116 0.960 0.8193 0.384 0.630
#> [2,] 0.260 0.782 0.5709 0.757 0.434
#> [3,] 0.495 0.826 0.5751 0.502 0.913
#> [4,] 0.118 0.424 0.0476 0.538 0.216
#> [5,] 0.157 0.914 0.2195 0.258 0.143
#> [6,] 0.396 0.750 0.5379 0.632 0.121
#> 
#> , , 3
#> 
#>        [,1]  [,2]   [,3]  [,4]   [,5]
#> [1,] 0.0553 0.590 0.3285 0.726 0.4570
#> [2,] 0.6060 0.419 0.6630 0.391 0.3829
#> [3,] 0.3775 0.112 0.3821 0.813 0.3539
#> [4,] 0.1749 0.669 0.0608 0.669 0.0801
#> [5,] 0.2252 0.717 0.2401 0.095 0.4790
#> [6,] 0.9461 0.111 0.7775 0.974 0.8369

然后我们用dimnames()(“维度名”)来命名:

dimnames(B) <- list(paste("trial.", 1:6), # 第一个维度
                    c('P. falciparum', 'P. malariae', 'P. ovale', 'P. vivax', 'P. knowlesi'), # 第二个维度
                    c('chloroquine', 'artemisinin', 'doxycycline')) # 第三个维度
B
#> , , chloroquine
#> 
#>          P. falciparum P. malariae P. ovale P. vivax P. knowlesi
#> trial. 1        0.6922       0.898   0.5718    0.823       0.628
#> trial. 2        0.1419       0.473   0.0593    0.731       0.330
#> trial. 3        0.0484       0.269   0.4750    0.257       0.922
#> trial. 4        0.8174       0.699   0.6339    0.736       0.890
#> trial. 5        0.8560       0.435   0.8243    0.445       0.147
#> trial. 6        0.7077       0.620   0.7473    0.230       0.341
#> 
#> , , artemisinin
#> 
#>          P. falciparum P. malariae P. ovale P. vivax P. knowlesi
#> trial. 1         0.116       0.960   0.8193    0.384       0.630
#> trial. 2         0.260       0.782   0.5709    0.757       0.434
#> trial. 3         0.495       0.826   0.5751    0.502       0.913
#> trial. 4         0.118       0.424   0.0476    0.538       0.216
#> trial. 5         0.157       0.914   0.2195    0.258       0.143
#> trial. 6         0.396       0.750   0.5379    0.632       0.121
#> 
#> , , doxycycline
#> 
#>          P. falciparum P. malariae P. ovale P. vivax P. knowlesi
#> trial. 1        0.0553       0.590   0.3285    0.726      0.4570
#> trial. 2        0.6060       0.419   0.6630    0.391      0.3829
#> trial. 3        0.3775       0.112   0.3821    0.813      0.3539
#> trial. 4        0.1749       0.669   0.0608    0.669      0.0801
#> trial. 5        0.2252       0.717   0.2401    0.095      0.4790
#> trial. 6        0.9461       0.111   0.7775    0.974      0.8369