在聪明的lapply
之后,我留下了一个二维矩阵列表。
例如:
set.seed(1)
test <- replicate( 5, matrix(runif(25),ncol=5), simplify=FALSE )
> test
[[1]]
[,1] [,2] [,3] [,4] [,5]
[1,] 0.8357088 0.29589546 0.9994045 0.2862853 0.6973738
[2,] 0.2377494 0.14704832 0.0348748 0.7377974 0.6414624
[3,] 0.3539861 0.70399206 0.3383913 0.8340543 0.6439229
[4,] 0.8568854 0.10380669 0.9150638 0.3142708 0.9778534
[5,] 0.8537634 0.03372777 0.6172353 0.4925665 0.4147353
[[2]]
[,1] [,2] [,3] [,4] [,5]
[1,] 0.1194048 0.9833502 0.9674695 0.6687715 0.1928159
[2,] 0.5260297 0.3883191 0.5150718 0.4189159 0.8967387
[3,] 0.2250734 0.2292448 0.1630703 0.3233450 0.3081196
[4,] 0.4864118 0.6232975 0.6219023 0.8352553 0.3633005
[5,] 0.3702148 0.1365402 0.9859542 0.1438170 0.7839465
[[3]]
...
我想把它变成一个三维数组:
set.seed(1)
replicate( 5, matrix(runif(25),ncol=5) )
显然,如果我正在使用复制,我可以打开simplify
,但sapply
不能正确简化结果,stack
完全失败。 do.call(rbind,mylist)
将其转换为2d矩阵而不是3d数组。
我可以通过循环执行此操作,但我正在寻找一种简洁实用的方法来处理它。
我最接近的方式是:
array( do.call( c, test ), dim=c(dim(test[[1]]),length(test)) )
但我觉得这样做不够优雅(因为它反汇编然后重新组合了矢量的数组属性,并且需要进行大量测试以确保安全(例如每个元素的尺寸相同)。
答案 0 :(得分:13)
试试这个:
simplify2array(test)
答案 1 :(得分:8)
您可以使用abind
包,然后使用abind(test, along = 3)
library(abind)
testArray <- abind(test, along = 3)
或者您可以在调用simplify = 'array'
时使用sapply
,而不是lapply
。 simplify = 'array'
与simplify = TRUE
不同,因为它会更改higher
simplify2array
例如
foo <- function(x) matrix(1:10, ncol = 5)
# the default is simplify = TRUE
sapply(1:5, foo)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 2 2 2 2
[3,] 3 3 3 3 3
[4,] 4 4 4 4 4
[5,] 5 5 5 5 5
[6,] 6 6 6 6 6
[7,] 7 7 7 7 7
[8,] 8 8 8 8 8
[9,] 9 9 9 9 9
[10,] 10 10 10 10 10
# which is *not* what you want
# so set `simplify = 'array'
sapply(1:5, foo, simplify = 'array')
, , 1
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 2
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 3
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 4
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
, , 5
[,1] [,2] [,3] [,4] [,5]
[1,] 1 3 5 7 9
[2,] 2 4 6 8 10
答案 2 :(得分:2)
test2 <- unlist(test)
dim(test2) <- c(dim(test[[1]]),5)
或者如果您事先不知道预期的尺寸:
dim3 <- c(dim(test[[1]]), length(test2)/prod(dim(test[[1]])))
dim(test2) <- dim3
答案 3 :(得分:2)
数组只是具有维度的原子向量。 test
的每个矩阵分量实际上只是具有维度的向量。因此,我能想到的最简单的解决方案是将列表test
展开到一个向量中,并使用array
和适当提供的维度将其转换为数组。
set.seed(1)
foo <- replicate( 5, matrix(runif(25),ncol=5) )
tmp <- array(unlist(test), dim = c(5,5,5))
> all.equal(foo, tmp)
[1] TRUE
> is.array(tmp)
[1] TRUE
> dim(tmp)
[1] 5 5 5
如果您不想对尺寸进行硬编码,我们必须做出一些假设,但可以轻松填写test
的尺寸,例如
tmp2 <- array(unlist(test), dim = c(dim(test[[1]]), length(test)))
> all.equal(foo, tmp2)
[1] TRUE
这假设每个组件的尺寸都是相同的,但是如果那个条件不成立,我看不出如何将子矩阵放入三维数组中。
这可能看起来很糟糕,要展开列表,但这只是利用R如何处理矩阵和数组作为具有维度的向量。