使用R函数“外部”时出现“尺寸[产品xx]与对象[xx]的长度不匹配”错误

时间:2018-09-13 15:34:03

标签: 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

第一季度:为什么outer(x, y, "funError")不起作用?

  

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

第二季度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

2 个答案:

答案 0 :(得分:3)

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

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))

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%` and 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

?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).

“矢量化”一词是 the most discussed one in R on performance。意思是“向量化函数的作用”:

## 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) )

有些函数说"+""*"paste的行为是这样的,但是许多其他函数则没有,例如classsum,{{1 }}。 R中的prod系列函数可以帮助您向量化函数操作,也可以编写自己的循环来达到相同的效果。


另一个值得阅读的优质问答:Why doesn't outer work the way I think it should (in R)?

答案 1 :(得分:1)

我认为这是因为从外部得到的矩阵期望与您的输入具有相同的尺寸,但是class(a)的长度仅为1,因此矩阵尺寸不匹配。试试

funError2 <- function(a,b){paste(rep(class(a), length(a)),rep(class(b), length(b)), sep = "**")}
outer(x,y, "funError2")
#>    y2                 y3                 y4                
#> x1 "integer**integer" "integer**integer" "integer**integer"
#> x2 "integer**integer" "integer**integer" "integer**integer"
#> x3 "integer**integer" "integer**integer" "integer**integer"
#> x4 "integer**integer" "integer**integer" "integer**integer"
#> x5 "integer**integer" "integer**integer" "integer**integer"
#> x6 "integer**integer" "integer**integer" "integer**integer"
#> x7 "integer**integer" "integer**integer" "integer**integer"
#> x8 "integer**integer" "integer**integer" "integer**integer"
#> x9 "integer**integer" "integer**integer" "integer**integer"
#>    y5                
#> x1 "integer**integer"
#> x2 "integer**integer"
#> x3 "integer**integer"
#> x4 "integer**integer"
#> x5 "integer**integer"
#> x6 "integer**integer"
#> x7 "integer**integer"
#> x8 "integer**integer"
#> x9 "integer**integer"

reprex package(v0.2.0)于2018-09-13创建。