R中意外的应用函数行为

R中意外的应用函数行为,r,apply,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,]

我通过
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()
向量反转函数。但当我们尝试按行应用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]}
提供相同的结果,因此它肯定不是rev的错


对此有何解释?

将行向量传递给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

这是因为
apply
返回一个按列定义的矩阵,并且您正在对行进行迭代

apply
的第一个应用程序显示每一行,然后是结果中的一列

显示函数
print
显示每次迭代时传递给
rev
的内容:

 x <- apply(m, 1, print)
[1] 1 3 5 7
[1] 2 4 6 8

x文件规定

如果对FUN的每次调用都返回长度为n的向量,则apply返回 如果n>1,则维数为c(n,dim(X)[边距])的数组

从这个角度来看,这种行为根本不是一个bug,这就是它的工作原理

人们可能会想,为什么会选择默认设置,而不是保留原始矩阵的结构。考虑下面的例子:

> 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

一致的?事实上,我们为什么会期望其他东西呢?

我知道
t
强制矩阵方向,但是
vec
本身可以说是返回垂直或水平方向吗<代码>完全相同(1:10,rev(t(10:1)))
是正确的。谢谢Matthew,我认为你说得对,但我认为答案应该属于tonytonov,因为他在文档中阐明了基本原理。顺便说一句,打印的东西很有启发性:
apply(m,1,FUN=function(v){print(“done”)}
(令人困惑地)生成打印和对象报告,这是需要记住的:)@geotheory这就是为什么我将结果分配给一个变量。这将阻止打印返回的对象。在试验
print
时,我们只关心参数,而不关心返回值。将表达式包装在
invisible()
中也会阻止打印最终结果,但分配给变量的击键次数会更少。感谢您解释机制和原因。除非马修(似乎同样正确)的答案得到一致的支持,否则我认为你已经做到了。谢谢你的评论,谢谢。