R中出现意外的应用函数行为

时间:2014-02-12 13:29:26

标签: r apply

我发现了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]}提供相同的结果,因此绝对不是转换的错误。

对此有何解释?

3 个答案:

答案 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

一致?确实,为什么我们还期待别的什么?