代码之家  ›  专栏  ›  技术社区  ›  Henrik

如何在R中的函数中使用acast(reformae2)?

  •  7
  • Henrik  · 技术社区  · 15 年前

    我试着用 acast reshape2 在一个自写函数中,但有一个问题,acast没有找到我发送给它的数据。

    以下是我的数据:

    library("reshape2")
    x <- data.frame(1:3, rnorm(3), rnorm(3), rnorm(3))    
    colnames(x) <- c("id", "var1", "var2", "var3")
    y <-melt(x, id = "id", measure = c("var1", "var2", "var3"))
    

    y 然后看起来像这样:

      id variable      value
    1  1     var1  0.1560812
    2  2     var1  1.0343844
    3  3     var1 -1.4157728
    4  1     var2  0.8808935
    5  2     var2  0.1719239
    6  3     var2  0.6723758
    7  1     var3 -0.7589631
    8  2     var3  1.1325995
    9  3     var3 -1.5744876
    

    现在我可以通过 阿卡斯特

    > acast(y,y[,1] ~ y[,2])
            var1      var2       var3
    1  0.1560812 0.8808935 -0.7589631
    2  1.0343844 0.1719239  1.1325995
    3 -1.4157728 0.6723758 -1.5744876
    

    但是,在为 阿卡斯特

    wrap.acast <- function(dat, v1 = 1, v2 = 2) {
        out <- acast(dat, dat[,v1] ~ dat[,v2])
        return(out)
    }
    
    wrap.acast(y)
    
    Error in eval(expr, envir, enclos) : object 'dat' not found
    

    这个问题显然与环境和全局/局部变量有关。因为它在声明 dat 在全球环境中(即。, v1 v2

    谢谢。

    4 回复  |  直到 15 年前
        1
  •  7
  •   Collin    15 年前

    不要使用公式说明,而要使用字符说明:

    acast(y, list(names(y)[1], names(y)[2]))
    
        2
  •  4
  •   Gavin Simpson    15 年前

    > acast(y, y[,1] ~ y[,2])
            var1       var2         var3
    1  2.1726117  0.6107264  0.291446236
    2  0.4755095 -0.9340976 -0.443291873
    3 -0.7099464 -1.2536334  0.001105352
    

    因为如果提供了数据对象,“y”位是冗余的。如果在公式中直接用名称引用y的变量,事情会很顺利

    > acast(y, id ~ variable)
            var1       var2         var3
    1  2.1726117  0.6107264  0.291446236
    2  0.4755095 -0.9340976 -0.443291873
    3 -0.7099464 -1.2536334  0.001105352
    

    在第二个版本中,代码的可读性更高。

    acast names ,正如Joris所指出的,Hadley的解决方案要简单得多。因此,我的观点是要注意如何在R中使用公式规范。如果正确使用公式,从长远来看,您将省去很多麻烦(尽管不是特别针对这个问题)。

        3
  •  2
  •   Joris Meys    15 年前

    更正:问题不是它没有找到dat,而是它没有在指定的公式中找到dat[,v1]和dat[,v2]。Acast接受公式类型的参数,并在围绕数据帧创建的临时环境中对该参数进行求值。在该环境中,当函数包装在另一个对象中时,它找不到“dat”对象。

    我并没有完全理解它是如何在全局中工作的,在包装时也不会,但是如果你给acast一个公式,它也会在函数中工作。

    wrap.acast <- function(dat, v1 = 1, v2 = 2) {
        x1 <- names(dat)[v1]
        x2 <- names(dat)[v2]
        form <- as.formula(paste(x1,"~",x2))
        out <- acast(dat,form)
        return(out)
    }
    

    使用您的玩具数据:

    > wrap.acast(y)
            var1      var2       var3
    1 0.04095337 0.4044572 -0.4532233
    2 1.23905358 1.2493187  0.7083557
    3 0.72798307 0.7868746  1.7144811
    
        4
  •  -2
  •   Henrik    15 年前

    我发现了一个非常不雅观的方法来解决问题使用超级作业( <<-
    将函数更改为以下值可以完成此任务。但是,这是相当丑陋的,因为它创建的全局变量仍然存在。

    wrap.acast <- function(dat, v1 = 1, v2 = 2) {
        dat <<- dat
        v1 <<- v1
        v2 <<- v2
        out <- acast(dat, dat[,v1] ~ dat[,v2])
        return(out)
    }
    

    在运行函数之前:

    > ls()
    [1] "wrap.acast" "x"          "y"     
    

    > ls()
    [1] "dat"        "v1"         "v2"         "wrap.acast" "x"         
    [6] "y"