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()
中也会阻止打印最终结果,但分配给变量的击键次数会更少。感谢您解释机制和原因。除非马修(似乎同样正确)的答案得到一致的支持,否则我认为你已经做到了。谢谢你的评论,谢谢。