为什么rbind和cbind与sapply产生相同的输出
以下为列表列表:为什么rbind和cbind与sapply产生相同的输出,r,apply,R,Apply,以下为列表列表: > lll = list(list(5,3,4), list(5,3,7), list(6,2,1), list(6,1,3), list(5,2,1)) 我希望输出与rbind和cbind进行转换,但它们是相同的: > sapply(lll, rbind) [,1] [,2] [,3] [,4] [,5] [1,] 5 5 6 6 5 [2,] 3 3 2 1 2 [3,] 4 7
> lll = list(list(5,3,4), list(5,3,7), list(6,2,1), list(6,1,3), list(5,2,1))
我希望输出与rbind和cbind进行转换,但它们是相同的:
> 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
为什么会这样?什么代码会产生cbind与rbind的转置输出?要获得所需的输出,您可能需要尝试使用
do。调用和lappy
:
rbind
:
do.call(rbind, lapply(lll, rbind))
do.call(cbind, lapply(lll, cbind))
do.call(cbind, lll)
do.call(rbind, lll)
cbind
:
do.call(rbind, lapply(lll, rbind))
do.call(cbind, lapply(lll, cbind))
do.call(cbind, lll)
do.call(rbind, lll)
正如@zx8754所指出的,实际上可以跳过apply
的用法,只需使用do.call
即可完成(对于列表中的列表,我没有意识到这一点。谢谢!):
cbind
和rbind
:
do.call(rbind, lapply(lll, rbind))
do.call(cbind, lapply(lll, cbind))
do.call(cbind, lll)
do.call(rbind, lll)
谢谢 通常,cbind
和rbind
适用于向量。例如,请参见以下内容:
v <- c(3,1,2)
cbind(v)
# v
#[1,] 3
#[2,] 1
#[3,] 2
rbind(v)
# [,1] [,2] [,3]
#v 3 1 2
为了让它发挥作用,我会这样做(尽管其他人已经建议):
或
x按照您编写它的方式,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
这相当于:
> sapply(list(rbind(list(1,2,3)),rbind(list(4,5,6))),identity)
> sapply(list(matrix(list(1,2,3),c(1,3)),matrix(list(4,5,6),c(1,3))),identity)
这相当于:
> sapply(list(rbind(list(1,2,3)),rbind(list(4,5,6))),identity)
> sapply(list(matrix(list(1,2,3),c(1,3)),matrix(list(4,5,6),c(1,3))),identity)
这与此相当,因为sapply
关心的是它们的长度,而不是它们的尺寸:
> sapply(list(c(1,2,3),c(4,5,6)),identity)
基本上就是这样(因为sapply
将它们组合为列):
您真正想要的是调用rbind
一次,将每个子列表作为参数,而不是在每个子列表上单独调用它。换句话说,您希望它能像这样工作:
> rbind(list(1,2,3),list(4,5,6))
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
但是,由于子列表已存储在单个列表中,因此可以通过使用do.call
实现这一点,它允许您将rbind
的所有参数作为单个列表提供:
> 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
>列表的列表do.call(rbind,列表的列表)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
do.call(rbind,lappy(lll,rbind))
和do.call(cbind,lappy(lll,cbind))
。是的,这些都可以。你可能想把它作为一个答案,并做一些解释。@Abdou为什么是Lappy<代码>do.call(cbind,lll);do.call(rbind,lll)
?人们可能会被欺骗,认为rbind
或cbind
实际上组合了列表,但这只是因为sapply
在这种情况下基本上做了cbind
。本例中实际的rbind
或cbind
只是将子列表转换为矩阵,而sapply
实际上并不关心它们是矩阵。将rbind
替换为identity
,您将在此处获得相同的输出。