为什么rbind和cbind用sapply产生相同的输出

时间:2016-09-30 14:53:38

标签: 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,但它们是相同的:

> 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 vs rbind的转置输出?

3 个答案:

答案 0 :(得分:5)

您编写它的方式,rbind将单独应用于您的每个子列表,因此它实际上并没有将它们与任何内容组合。在这种情况下,它真正做的就是将维度属性添加到子列表,将其从包含length=3的列表更改为具有dim=c(1,3)的矩阵。 cbind会做同样的事情,除非你得到dim=c(3,1)。关键是,正如您所写的那样,rbindcbind实际上并不用于将子列表组合在一起。这完全由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关心它们的长度而不是它们的尺寸:

> sapply(list(c(1,2,3),c(4,5,6)),identity)

基本上就是这个(因为sapply将它们组合成列):

> cbind(c(1,2,3),c(4,5,6))

你真正想要的是调用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提供:

> 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   

答案 1 :(得分:1)

要获得所需的输出,您可以尝试使用do.calllapply

rbind

do.call(rbind, lapply(lll, rbind))

cbind

do.call(cbind, lapply(lll, cbind))

正如@ zx8754所指出的那样,实际上可以跳过apply的使用并只使用do.call来完成它(对于列表中的列表我不知道的事情)谢谢!):

cbindrbind

do.call(cbind, lll)
do.call(rbind, lll)

谢谢!

答案 2 :(得分:1)

通常,cbindrbind适用于矢量。例如,请看:

v <- c(3,1,2)
cbind(v)
#     v
#[1,] 3
#[2,] 1
#[3,] 2

rbind(v)
#  [,1] [,2] [,3]
#v    3    1    2

sapply有一个名为simplify的参数,默认情况下为TRUE,此参数会中和代码中rbindcbind的效果。参数?sapply的{​​{1}}表示:

  

逻辑或字符串;如果可能,结果是否应简化为矢量,矩阵或更高维数?

实际上你的代码所做的与这段代码相同:

simplify

为了使其有效,我做了(尽管其他人已经建议):

sapply(lll, function(x) x)

或使用x <- do.call(rbind, lll) # [,1] [,2] [,3] # [1,] 5 3 4 # [2,] 5 3 7 # [3,] 6 2 1 # [4,] 6 1 3 # [5,] 5 2 1 t(x) # [,1] [,2] [,3] [,4] [,5] # [1,] 5 5 6 6 5 # [2,] 3 3 2 1 2 # [3,] 4 7 1 3 1 库:

data.table

或者

x <- rbindlist(lll)
t(x)

一旦我们得到一个表单的输出(例如x <- matrix(unlist(lll), ncol = 3, byrow = T) t(x) ),我们将结果转置为另一个表单(为rbind情况完成)。