我试图结合多个2d向量来获得一个3d向量,3d向量应该是[行,列,2vectors]。到目前为止,我只使用了由一个2d矢量制作的3d矢量:
x <- matrix(1:12, 3,4)
# [,1] [,2] [,3] [,4]
#[1,] 1 4 7 10
#[2,] 2 5 8 11
#[3,] 3 6 9 12
dim(x) <- c(dim(x), 1))
dim(x)
#[1] 3 4 1
当我选择一行时显示如下:
x[1,,]
#[1] 1 4 7 10
现在将2d矢量组合成3d矢量,我做了如下操作:
x <- matrix(1:12, 3, 4)
y <- x + 100
z <- abind(x, y, along=3)
dim(z)
#[1] 3 4 2
可以看到,尺寸是正确的[行,列,向量]。因此我期望这样:
z[1,,]
# [,1] [,2] [,3] [,4]
#[1,] 1 4 7 10
#[2,] 101 104 107 110
但是我得到了这个:
z[1,,]
# [,1] [,2]
#[1,] 1 101
#[2,] 4 104
#[3,] 7 107
#[4,] 10 110
所以我想知道输出是否在控制台上正确显示,或者是否有我不理解的东西。
可能有几个令人困惑的方面导致意外的输出:
- A
matrix
在R中被限制为二维矩阵,实际上如果dim(...) <= 2
,is.matrix(...)
返回TRUE
。高维矩阵实际上被称为array
。考虑
x <- matrix(1:12, 3,4)
class(x) # x is matrix, array
# [1] "matrix" "array"
dim(x) <- c(dim(x), 1))
dim(x)
# [1] 3 4 1
class(x) # x is array
# [1] "array"
- 用括号符号(如
x[1,,]
)提取或替换对象的部分(即矩阵的切片),其中包含默认参数drop = TRUE
。
对于矩阵和数组,如果
drop = TRUE
,则结果被强制到尽可能低的维度。
当drop = FALSE
,drop(...)
函数根本不会被调用时,即x[1,,,drop=FALSE]
将其dim(...)
作为c(1,4,1)
,控制台输出变为:
x[1,,,drop=FALSE]
# , , 1
#
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
那么abind
的输出看起来更一致:
y <- x + 100
z <- abind(x, y, along=3)
dim(z)
# [1] 3 4 2
z[1,,,drop=FALSE]
# , , 1
#
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
#
# , , 2
#
# [,1] [,2] [,3] [,4]
# [1,] 101 104 107 110
drop(...)
的工作方式也可能令人困惑,因为它
删除只有一级数组的维数
即对于维度为c(1, 4, 1)
的x[1,,,drop=FALSE]
,drop(...)
将删除它的第一个维度和第三个维度,将维度降为c(4)
。但是将返回NULL
,因为dim(...)
被定义为返回向量的NULL
:
drop(x[1,,,drop=FALSE])
# [1] 1 4 7 10
class(drop(x[1,,,drop=FALSE]))
# [1] "integer"
dim(drop(x[1,,,drop=FALSE]))
# NULL
对于维度为c(1,4,2)
的z[1,,,drop=FALSE]
,drop(...)
将其维度降为c(4,2)
,如:
drop(z[1,,,drop=FALSE])
# [,1] [,2]
# [1,] 1 101
# [2,] 4 104
# [3,] 7 107
# [4,] 10 110
如何让drop(...)
更直观?
实现drop(...)
的另一种方法可能更直观——删除只有一个级别的数组的标题尺寸。也就是说,对于像c(1,1,3,1,2,1)
这样维度的数组,我们的drop2(...)
将缩减为c(3,1,2,1)
。作为一个粗略的实现,考虑
dummy = array(1:6, dim=c(1,1,3,1,2,1))
drop2 = function(x) {
x.dim = dim(x)
if (is.null(x.dim)) return(x)
array(x, dim=x.dim[cumsum(x.dim > 1) > 0])
}
dim(drop2(dummy))
# [1] 3 1 2 1
drop2(x[1,,,drop=FALSE]) # resulting dim c(4, 1)
# [,1]
# [1,] 1
# [2,] 4
# [3,] 7
# [4,] 10
drop2(z[1,,,drop=FALSE])
# [,1] [,2]
# [1,] 1 101
# [2,] 4 104
# [3,] 7 107
# [4,] 10 110