对比以下两个代码段:
1
> a <- cbind(1,2)
> a
[,1] [,2]
[1,] 1 2
> str(a)
num [1, 1:2] 1 2
2
> b <- Reduce(cbind, list(1,2))
> b
init
[1,] 1 2
> str(b)
num [1, 1:2] 1 2
- attr(*, "dimnames")=List of 2
..$ : NULL
..$ : chr [1:2] "init" ""
根据Reduce
帮助页面,我希望a
和b
相同,但它们显然不完全相同。为什么?
答案 0 :(得分:5)
这是因为Reduce
调用f
的方式以及cbind
如何创建列名。 Reduce
根据init
和right
args的值确定初始值,并将该值存储在名为init
的对象中,它也会反复更新。< / p>
在您的示例中,Reduce
中的以下代码是发生差异的地方:
init <- x[[1L]]
ind <- ind[-1L]
for (i in ind) init <- f(init, x[[i]])
默认的cbind
参数deparse.level = 1
表示它尝试通过删除传递给它的对象名称来创建dimnames
(如果它们生成合理的名称)。如果您希望Reduce
输出与在单个号码上调用cbind
相同,请设置deparse.level=0
。
> str(Reduce(function(x,y) cbind(x,y,deparse.level=0), list(1,2)))
num [1, 1:2] 1 2
顺便说一下,在for循环中调用cbind
是一个坏主意,因为它必须在每次迭代时重新分配内存,导致代码非常慢。分配您期望的完整输出对象(如果可以)然后填写元素会好得多。
答案 1 :(得分:3)
约书亚的答案解释了为什么你有所不同。我只是展示如何获得相同的输出。实际上,您应该将init参数初始化为NULL:
identical(Reduce(cbind, list(1,2),init=NULL),
cbind(1,2))
TRUE
除此之外,调用更有效:
do.call(cbind,list(1,2))