使用reshape包中的强制转换正确引用公式

时间:2014-02-04 22:32:00

标签: r casting reshape

我正在尝试从reshape包中围绕'cast'函数包装一个函数,该函数在投射之前对我的数据运行一些检查。

cast2 <- function(data, formula = ... ~ variable, fun.aggregate = NULL, 
        ..., margins = FALSE, subset = TRUE, df = FALSE, fill = NULL, 
        add.missing = FALSE, value = guess_value(data)) {

    #RunChecksOnData()

    return(cast(data, formula = formula, fun.aggregate = fun.aggregate, ..., margins = margins, subset = subset, df = df, fill = fill, add.missing = add.missing, value = value))
}

如果没有检查,我希望这个函数'cast2'会返回与cast相同的结果。 但是,当我选择其中一个特色示例时

names(airquality) <- tolower(names(airquality))
aqm <- melt(airquality, id=c("month", "day"), na.rm=TRUE)

并运行:

cast2(aqm, day ~ month, mean, subset=variable=="ozone")

这导致错误“eval中的错误(expr,envir,enclos):找不到对象'变量'”

我怀疑这与公式传递函数的方式有关,但我无法弄明白。 (我意识到我可以在技术上通过复制cast2中的所有强制转换函数来解决问题,但我确信必须有一个更清晰的方法。)

2 个答案:

答案 0 :(得分:0)

cast已过时。您应该使用reshape2而不是reshape,其中您有两个功能:dcastacast。实现所需内容的一个想法是使用.中的plyr这是一个示例:

library(plyr)
library(reshape2)
dcast2 <- function(){
  names(airquality) <- tolower(names(airquality))
  aqm <- melt(airquality, id=c("month", "day"), na.rm=TRUE)
  dcast(aqm, variable ~ month, mean, subset = subset)
}

然后你这样称呼它:

dcast2(.(variable=="ozone"))
  variable        5        6        7        8        9
1    ozone 23.61538 29.44444 59.11538 59.96154 31.44828

答案 1 :(得分:0)

您现在的问题是,您无法评估subset参数,因为cast不使用标准评估来捕获它。使用match.call()即可避免对subset进行评估。错误中引用的variable来自表达式subset=variable=="ozone"

这是一个解决方案。如果你真的只是要检查数据而不是试图修改它,那么这是微不足道的。您需要做的就是检查您的变量,如果没问题,请将调用更改为cast并进行评估。如果你需要修改变量,那么它有点棘手,但不是那么多。您需要确保调用引用函数环境中的已修改变量。我在下面这样做:

cast2 <- function(data, formula = ... ~ variable, fun.aggregate = NULL, 
                  margins = FALSE, subset = TRUE, df = FALSE, fill = NULL, 
                  add.missing = FALSE, value = guess_value(data)) {

  #RunChecksOnData()
  cast.call <- match.call()
  cast.call[[1]] <- quote(cast)       # update call
  data$value <- data$value * 100      # modify data
  cast.call[["data"]] <- quote(data)  # update call for modified data (otherwise this refers to aqm)
  eval(cast.call)
}

编辑:如果您使用此功能,则需要注意避免功能环境与生成呼叫的环境之间的冲突。只要您的函数不包含任何与调用中引用的名称相同的变量,此处就可以使用。如果您无法保证是这种情况,那么您需要注意如何进行评估。我将创建一个新的环境,该父环境具有该函数的parent.frame,在那里分配修改后的对象(例如data),然后在该环境中评估cast.call。此复杂性仅适用于需要修改参数的情况。如果您只需要检查参数,可以将最后一行修改为eval(cast.call, parent.frame()),您应该没问题。