我发现了apply
令人惊讶的行为,我想知道是否有人可以解释。让我们采用一个简单的矩阵:
> (m = matrix(1:8,ncol=4))
[,1] [,2] [,3] [,4]
[1,] 1 3 5 7
[2,] 2 4 6 8
我们可以垂直翻转它:
> apply(m, MARGIN=2, rev)
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 1 3 5 7
这会将rev()
向量反转函数迭代地应用于每列。但是当我们尝试逐行应用时,我们得到:
> apply(m, MARGIN=1, rev)
[,1] [,2]
[1,] 7 8
[2,] 5 6
[3,] 3 4
[4,] 1 2
..逆时针旋转90度! Apply使用FUN=function(v) {v[length(v):1]}
提供相同的结果,因此绝对不是转换的错误。
对此有何解释?
答案 0 :(得分:4)
这是因为apply
返回一个按列定义的矩阵,并且您正在迭代这些行。
apply
的第一个应用程序显示每一行,然后是结果中的一列。
显示函数print
显示每次迭代时传递给rev
的内容:
x <- apply(m, 1, print)
[1] 1 3 5 7
[1] 2 4 6 8
也就是说,每次打印调用都会传递一个向量。两个调用,c(1,3,5,7)
和c(2,4,6,8)
正在传递给函数。
反转这些会产生c(7,5,3,1)
和c(8,6,4,2)
,然后将它们用作返回矩阵的列,给出您看到的结果。
答案 1 :(得分:2)
将行向量传递给rev时,它会返回一个列向量。
t(c(1,2,3,4))
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
rev(t(c(1,2,3,4)))
[1] 4 3 2 1
这不是你的预期
[,1] [,2] [,3] [,4]
[1,] 4 3 2 1
所以,你必须将调用转换为申请以获得你想要的东西
t(apply(m, MARGIN=1, rev))
[,1] [,2] [,3] [,4]
[1,] 7 5 3 1
[2,] 8 6 4 2
答案 2 :(得分:2)
文档说明了
如果每次调用FUN都返回一个长度为n的向量,则apply返回 如果n> 1,则为维数c(n,dim(X)[MARGIN])的数组。 1。
从这个角度来看,这种行为并不是一个错误,这就是它的工作方式。
有人可能想知道为什么选择这是默认设置,而不是保留原始矩阵的结构。请考虑以下示例:
> apply(m, 1, quantile)
[,1] [,2]
0% 1.0 2.0
25% 2.5 3.5
50% 4.0 5.0
75% 5.5 6.5
100% 7.0 8.0
> apply(m, 2, quantile)
[,1] [,2] [,3] [,4]
0% 1.00 3.00 5.00 7.00
25% 1.25 3.25 5.25 7.25
50% 1.50 3.50 5.50 7.50
75% 1.75 3.75 5.75 7.75
100% 2.00 4.00 6.00 8.00
> all(rownames(apply(m, 2, quantile)) == rownames(apply(m, 1, quantile)))
[1] TRUE
一致?确实,为什么我们还期待别的什么?