【问题标题】:Why doesn't outer work the way I think it should (in R)?为什么外部不按我认为应该的方式工作(在 R 中)?
【发布时间】:2013-08-09 05:50:33
【问题描述】:

在@hadley 的article on functionals referenced in an answer today 的提示下,我决定重新审视一个关于outer 函数如何工作(或不工作)的难题。为什么会失败:

outer(0:5, 0:6, sum) # while outer(0:5, 0:6, "+") succeeds

这表明我认为outer应该处理像sum这样的函数:

 Outer <- function(x,y,fun) {
   mat <- matrix(NA, length(x), length(y))
   for (i in seq_along(x)) {
            for (j in seq_along(y)) {mat[i,j] <- fun(x[i],y[j])} }
   mat}

>  Outer(0:5, 0:6, `+`)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    0    1    2    3    4    5    6
[2,]    1    2    3    4    5    6    7
[3,]    2    3    4    5    6    7    8
[4,]    3    4    5    6    7    8    9
[5,]    4    5    6    7    8    9   10
[6,]    5    6    7    8    9   10   11

好的,对于该示例,我的索引没有完全对齐,但修复起来并不难。问题是为什么像sum 这样应该能够接受两个参数并返回适合矩阵元素的(原子)值的函数在传递给base::outer 函数时却不能这样做?

所以@agstudy 为Outer 的更紧凑版本提供了灵感,而他的版本更加紧凑​​:

 Outer <- function(x,y,fun) {
       mat <- matrix(mapply(fun, rep(x, length(y)), 
                                 rep(y, each=length(x))),
                     length(x), length(y))

但是,问题仍然存在。术语“矢量化”在这里有些含糊,我认为“二元”更正确,因为sincos 在该术语的通常意义上是“矢量化”的。期望outer 以可以使用非二元函数的方式扩展其参数是否存在基本的逻辑障碍。

这是另一个outer-error,可能与我对这个问题缺乏了解类似:

> Vectorize(sum)
function (..., na.rm = FALSE)  .Primitive("sum")
>  outer(0:5, 0:6, function(x,y) Vectorize(sum)(x,y) )
Error in outer(0:5, 0:6, function(x, y) Vectorize(sum)(x, y)) : 
  dims [product 42] do not match the length of object [1]

【问题讨论】:

  • 你的函数没问题,但我猜要慢得多,所以对于outer 的 R 实现来说不是很好;已经用 C++ 实现了 outer,那么 sum 版本可能会起作用
  • 你在最后一个例子中寻找这个:outer(0:5, 0:6, Vectorize(function(x,y)sum(x,y)))
  • @eddi:如果提供答案,我会赞成。
  • 您的报告函数可能会有所帮助,但仅将“矢量化”包裹在函数周围并不足以确保成功。 @eddi 的版本更好。

标签: r functional-programming vectorization


【解决方案1】:

outer(0:5, 0:6, sum) 不起作用,因为sum 没有“矢量化”(在返回与其两个参数长度相同的矢量的意义上)。这个例子应该能说明区别:

 sum(1:2,2:3)
  8
 1:2 + 2:3
 [1] 3 5

您可以使用mapplysum 进行矢量化处理,例如:

identical(outer(0:5, 0:6, function(x,y)mapply(sum,x,y)),
          outer(0:5, 0:6,'+'))
TRUE

PS:一般在使用outer之前我在调试模式下使用browser来创建我的函数:

outer(0:2, 1:3, function(x,y)browser())
Called from: FUN(X, Y, ...)
Browse[1]> x
[1] 0 1 2 0 1 2 0 1 2
Browse[1]> y
[1] 1 1 1 2 2 2 3 3 3
Browse[1]> sum(x,y)
[1] 27          ## this give an error 
Browse[1]> x+y  
[1] 1 2 3 2 3 4 3 4 5 ## this is vectorized

【讨论】:

  • 来自?sum 的微妙之处:... numeric or complex or logical vectors。所以sum(c(1,2,3)) = sum(1,2,3) = sum(c(1,2),3)
  • 我喜欢浏览器的例子。我会用我的 Vectorize(sum) 后续 Q 来尝试。(但我不认为仅仅说“它是矢量化的”就足够具体了。)
  • @DWin 我同意这里的术语。 “矢量化”在这里不是一个好词。 dyadic 也许?随时编辑我的答案。
  • 只需在outer 问题上添加一个新的解释性问答的链接:“dims [product xx] do not match the length of object [xx]” error in using R function outer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 2015-05-04
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
相关资源
最近更新 更多