以下列表列表:
> lll = list(list(5,3,4), list(5,3,7), list(6,2,1), list(6,1,3), list(5,2,1))
Run Code Online (Sandbox Code Playgroud)
我期望输出与rbind和cbind转换为sapply,但它们是相同的:
> sapply(lll, rbind)
[,1] [,2] [,3] [,4] [,5]
[1,] 5 5 6 6 5
[2,] 3 3 2 1 2
[3,] 4 7 1 3 1
> sapply(lll, cbind)
[,1] [,2] [,3] [,4] [,5]
[1,] 5 5 6 6 5
[2,] 3 3 2 1 2
[3,] 4 7 1 3 1
>
> identical(sapply(lll, cbind), sapply(lll, rbind))
[1] TRUE
Run Code Online (Sandbox Code Playgroud)
为什么会这样,什么代码会产生cbind vs rbind的转置输出?
您编写它的方式rbind
是单独应用于每个子列表,因此它实际上并没有将它们与任何内容组合.在这种情况下,所有它真正做的是将维度属性添加到子列表,将其从列表更改length=3
为矩阵dim=c(1,3)
. cbind
除了你会得到同样的事情dim=c(3,1)
.关键是,正如你所写,它既不是rbind
也不cbind
是实际用于将子列表组合在一起.这完全由sapply
并且sapply
不关心它们作为矩阵的尺寸.它将它们视为向量并将它们组合为列.
考虑这个稍微简单的例子:
> sapply(list(list(1,2,3),list(4,5,6)),rbind)
[,1] [,2]
[1,] 1 4
[2,] 2 5
[3,] 3 6
Run Code Online (Sandbox Code Playgroud)
它相当于:
> sapply(list(rbind(list(1,2,3)),rbind(list(4,5,6))),identity)
Run Code Online (Sandbox Code Playgroud)
这相当于:
> sapply(list(matrix(list(1,2,3),c(1,3)),matrix(list(4,5,6),c(1,3))),identity)
Run Code Online (Sandbox Code Playgroud)
这相当于这个,因为sapply
关心它们的长度,而不是它们的尺寸:
> sapply(list(c(1,2,3),c(4,5,6)),identity)
Run Code Online (Sandbox Code Playgroud)
这基本上就是这个(因为sapply
它们组合成列):
> cbind(c(1,2,3),c(4,5,6))
Run Code Online (Sandbox Code Playgroud)
你真正想要的是调用rbind
一次,每个子列表作为参数,而不是在每个子列表上单独调用它.换句话说,你希望它像这样工作:
> rbind(list(1,2,3),list(4,5,6))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
Run Code Online (Sandbox Code Playgroud)
但是,由于您已将子列表存储在单个列表中,因此可以通过使用来实现此目的do.call
,这使您可以将所有参数rbind
作为单个参数提供list
:
> list_of_lists <- list(list(1,2,3),list(4,5,6))
> do.call(rbind, list_of_lists)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
Run Code Online (Sandbox Code Playgroud)