代码之家  ›  专栏  ›  技术社区  ›  Andre Elrico

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

r
  •  1
  • Andre Elrico  · 技术社区  · 6 年前
    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") 不工作?

    尺寸误差(robj)<-c(dX,dY):

    第2季度 :为什么 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 回复  |  直到 6 年前
        1
  •  5
  •   Zheyuan Li    6 年前

    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)

    这是说明性的,因为你会看到为什么 outer(1:5, 1:5, "+") 工作但是 outer(1:5, 1:5, sum) 失败。基本上, FUN 必须能够处理 xx yy . 否则,请包装 一个叫做 Vectorize . 更多细节将在后面给出。

    注意,“list”也是向量的有效模式。所以呢 outer How to perform pairwise operation like `%in%` and set operations for a list of vectors .


    可以将矩阵/数组传递给 外面的 外面的

    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 他说,你要表现得像这样,但其他很多人不这样 class sum , prod *apply R中的族函数有助于将函数动作矢量化,也可以编写自己的循环来实现同样的效果。


    Why doesn't outer work the way I think it should (in R)?

        2
  •  2
  •   AndS.    6 年前

    我认为这是因为outer得到的矩阵期望与输入的维数相同,但是类(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"
    

    创建日期:2018-09-13 reprex package