使用 R 函数 `outer` 时出现“dims [product xx] 与对象 [xx] 的长度不匹配”错误

And*_*ico 2 r

x <- 1:9
names(x) <- paste0("x",x)
y <- 2:5
names(y) <- paste0("y",y)

fun1      <-function(a, b) {paste(class(a),b, sep = "**")} #works
funError  <-function(a, b) {paste(class(a),class(b), sep = "**")} #does not work with outer
funNoError<-function(a, b) {paste(a,class(a),class(b),b, sep = "**")}  #works with outer  

funError(1,2) #is a valid function
outer(x, y, "funError") # fails
outer(x, y, "funNoError") # works
Run Code Online (Sandbox Code Playgroud)

Q1:为什么不起作用outer(x, y, "funError")

dim(robj) <- c(dX, dY) 中的错误:dims [产品 36] 与对象 [1] 的长度不匹配

Q2:为什么outer(x, y, "funNoError")有效?它非常相似。

  • 我能看到的唯一区别是,的每个“结果”funError都是相同的 ( "numeric**numeric")。

  • 如果始终具有相同的值是问题:为什么这里有效?

outer(rep(0,7), 1:10, "^")


好的,我明白了:

lol  <- function(a,b) {"lol"}
lol_v<- Vectorize(lol)

outer(x, y, "lol")   # fails with same Error
outer(x, y, "lol_v") # works as expected
Run Code Online (Sandbox Code Playgroud)

李哲源*_*李哲源 5

我经常解释outer(x, y, FUN)什么时候xy都是具有以下内容的向量:

xx <- rep(x, times = length(y))
yy <- rep(y, each = length(x))
zz <- FUN(xx, yy)
stopifnot(length(zz) == length(x) * length(y))  ## length = product?
z <- matrix(zz, length(x), length(y))
Run Code Online (Sandbox Code Playgroud)

funError失败是因为zz长度为 1,而funNoError不是因为在粘贴a(长度 > 1 的向量)和class(a)(长度为 1 的向量)时应用了“回收规则” 。

这是说明性的,因为您将看到为什么outer(1:5, 1:5, "+")有效但outer(1:5, 1:5, sum)失败。基本上,FUN必须能够处理xxyy element-wise。否则,FUN用一个名为 的糖函数包装Vectorize。更多细节将在后面给出。

请注意,“列表”也是向量的有效模式。所以outer可以用于一些非标准的事情,比如How to perform pairwise operation like `%in%` 和 set operations for a list of vectors


您也可以将矩阵/数组传递给outer。鉴于它们只是具有“dim”属性(可选带有“dimnames”)的向量,outer工作方式不会改变。

x <- matrix(1:4, 2, 2)  ## has "dim"
y <- matrix(1:9, 3, 3)  ## has "dim"

xx <- rep(x, times = length(y))  ## xx <- rep(c(x), times = length(y))
yy <- rep(y, each = length(x))  ## yy <- rep(c(y), each = length(x))
zz <- "*"(xx, yy)
stopifnot(length(zz) == length(x) * length(y))  ## length = product?
z <- "dim<-"( zz, c(dim(x), dim(y)) )

z0 <- outer(x, y, "*")
all.equal(z, z0)
#[1] TRUE
Run Code Online (Sandbox Code Playgroud)

?outer 用简单的语言解释上面的代码。

 ‘X’ and ‘Y’ must be suitable arguments for ‘FUN’.  Each will be
 extended by ‘rep’ to length the products of the lengths of ‘X’ and
 ‘Y’ before ‘FUN’ is called.

 ‘FUN’ is called with these two extended vectors as arguments (plus
 any arguments in ‘...’).  It must be a vectorized function (or the
 name of one) expecting at least two arguments and returning a
 value with the same length as the first (and the second).

 Where they exist, the [dim]names of ‘X’ and ‘Y’ will be copied to
 the answer, and a dimension assigned which is the concatenation of
 the dimensions of ‘X’ and ‘Y’ (or lengths if dimensions do not
 exist).
Run Code Online (Sandbox Code Playgroud)

单词“矢量”是不是 讨论最多的一个在性能[R 。它的意思是“向量化一个函数的动作”:

## for FUN with a single argument
FUN( c(x1, x2, x3, x4) ) = c( FUN(x1), FUN(x2), FUN(x3), FUN(x4) )

## for FUN with two arguments
  FUN( c(x1, x2, x3, x4), c(y1, y2, y3, y4) )
= c( FUN(x1, y1), FUN(x2, y2), FUN(x3, y3), FUN(x4, y4) )
Run Code Online (Sandbox Code Playgroud)

一些函数说"+", "*",paste表现得像这样,但许多其他函数不说class, sum, prod*applyR 中的族函数可以帮助您向量化函数动作,或者您可以编写自己的循环来实现相同的效果。


另一个值得一读的高质量问答:为什么外部工作不像我认为的那样(在 R 中)?