我正在尝试从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中的所有强制转换函数来解决问题,但我确信必须有一个更清晰的方法。)
答案 0 :(得分:0)
cast
已过时。您应该使用reshape2
而不是reshape
,其中您有两个功能:dcast
和acast
。实现所需内容的一个想法是使用.
中的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())
,您应该没问题。