Loo*_*eft 40 scope r function plyr
这确实挑战了我调试R代码的能力.
我想ddply()用于将相同的函数应用于按顺序命名的不同列; 例如.a,b,c.为此,我打算重复将列名称作为字符串传递,并使用eval(parse(text=ColName))该函数来引用它.我从另一个答案中抓住了这个技术.
这很有效,直到我放入ddply()另一个功能.以下是示例代码:
# Required packages:
library(plyr)
myFunction <- function(x, y){
NewColName = "a"
z = ddply(x, y, summarize,
Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE)
)
return(z)
}
a = c(1,2,3,4)
b = c(0,0,1,1)
c = c(5,6,7,8)
df = data.frame(a,b,c)
sv = c("b")
#This works.
ColName = "a"
ddply(df, sv, summarize,
Ave = mean(eval(parse(text=ColName)), na.rm=TRUE)
)
#This doesn't work
#Produces error: "Error in parse(text = NewColName) : object 'NewColName' not found"
myFunction(df,sv)
#Output in both cases should be
# b Ave
#1 0 1.5
#2 1 3.5
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?NewColName甚至在函数内部定义!
我认为这个问题的答案,循环 - 创造 - 新变量 - 在ddply,可能会帮助我,但我今天已经做了足够的头撞,现在是时候举手并寻求帮助了.
Pet*_*r O 22
今天解决这个问题的方法是summarize进入here(summarize).例如
myFunction <- function(x, y){
NewColName = "a"
z = ddply(x, y, here(summarize),
Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE)
)
return(z)
}
Run Code Online (Sandbox Code Playgroud)
here(f),在2012年12月添加到plyr,捕获了当前的背景.
Jam*_*mes 14
您可以通过组合使用do.call和call在NewColName仍然可见的环境中构建调用来执行此操作:
myFunction <- function(x,y){
NewColName <- "a"
z <- do.call("ddply",list(x, y, summarize, Ave = call("mean",as.symbol(NewColName),na.rm=TRUE)))
return(z)
}
myFunction(d.f,sv)
b Ave
1 0 1.5
2 1 3.5
Run Code Online (Sandbox Code Playgroud)
我偶尔遇到这样的问题,当ddply与summarize或者transform什么东西组合时,并没有足够聪明地判断导航各种环境的细节我倾向于通过简单地不使用summarize而不是使用我自己的匿名函数来解决问题:
myFunction <- function(x, y){
NewColName <- "a"
z <- ddply(x, y, .fun = function(xx,col){
c(Ave = mean(xx[,col],na.rm=TRUE))},
NewColName)
return(z)
}
myFunction(df,sv)
Run Code Online (Sandbox Code Playgroud)
显然,"手动"执行此操作需要付出代价,但它通常可以避免处理组合ddply和评估问题时的头痛问题summarize.当然,这并不是说哈德利不会出现解决方案......
问题出在plyr包本身的代码上。在summary函数中,有一行eval(substitute(...),.data,parent.frame()). 众所周知,parent.frame() 可以做一些非常时髦和意想不到的事情。时间
@James 的解决方案是一个非常好的解决方法,但如果我没记错的话,@Hadley 本人之前说过,plyr 包不适合在函数中使用。
抱歉,我这里错了。但目前已知 plyr 包在这些情况下会出现问题。
因此,我为您提供了该问题的基本解决方案:
myFunction <- function(x, y){
NewColName = "a"
z = aggregate(x[NewColName],x[y],mean,na.rm=TRUE)
return(z)
}
> myFunction(df,sv)
b a
1 0 1.5
2 1 3.5
Run Code Online (Sandbox Code Playgroud)