在函数内部找不到对象ddply的错误

这真的挑战了我debuggingR代码的能力。

我想使用ddply()将相同的function应用到按顺序命名的不同列; 例如。 a,b,c。 为此,我打算重复传递列名作为string,并使用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 

有任何想法吗? NewColName甚至在函数内部定义!

我认为这个问题的答案, 循环创build新variables在ddply ,可能会帮助我,但我今天做了足够的头撞,现在是时候举手,寻求帮助。

您可以使用do.callcall的组合在NewColName仍然可见的环境中构build调用:

 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(df,sv) b Ave 1 0 1.5 2 1 3.5 

今天解决这个问题的方法就是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) } 

here(f)在2012年12月添加到plyr中,捕捉当前上下文。

偶尔遇到这样的问题时,把ddplysummarizetransform或什么东西,而不是足够聪明,以神圣的导航各种环境的来龙去脉,我倾向于ddply的问题,通过简单地不使用summarize ,而是使用我自己的匿名function:

 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) 

显然,手工做这件事是有代价的,但是往往避免了处理好ddplysummarize出来的评估问题的头痛。 当然,这并不是说哈德利不会出现解决scheme。

问题在于plyr包本身的代码。 在汇总函数中,有一行eval(substitute(...),.data,parent.frame()) 。 这是众所周知的parent.frame()可以做相当时髦和意想不到的东西。 Ť

他的解决scheme@James是一个非常好的解决方法, 但是如果我记得正确@Hadley自己之前说过,plyr包不打算在函数中使用。

对不起,我错了。 目前已知的是,plyr软件包在这些情况下会出现问题。

因此,我给你一个问题的基本解决scheme:

 myFunction <- function(x, y){ NewColName = "a" z = aggregate(x[NewColName],x[y],mean,na.rm=TRUE) return(z) } > myFunction(df,sv) ba 1 0 1.5 2 1 3.5 

看起来你有一个环境问题。 全球任务可以解决这个问题,但是要以自己的灵魂为代价:

 library(plyr) 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") ColName = "a" ddply(df, sv, summarize, Ave = mean(eval(parse(text=ColName)), na.rm=TRUE) ) myFunction <- function(x, y){ NewColName <<- "a" z = ddply(x, y, summarize, Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE) ) return(z) } myFunction(x=df,y=sv) 

eval正在寻找parent.frame(1)。 所以如果你改为在MyFunction外面定义NewColName,它应该可以工作:

 rm(NewColName) NewColName <- "a" myFunction <- function(x, y){ z = ddply(x, y, summarize, Ave = mean(eval(parse(text=NewColName)), na.rm=TRUE) ) return(z) } myFunction(x=df,y=sv) 

通过使用get从早期的环境中拉出myparse,我们可以走得更近,但仍然必须通过curenv作为一个全球性的:

 myFunction <- function(x, y){ NewColName <- "a" my.parse <- parse(text=NewColName) print(my.parse) curenv <<- environment() print(curenv) z = ddply(x, y, summarize, Ave = mean( eval( get("my.parse" , envir=curenv ) ), na.rm=TRUE) ) return(z) } > myFunction(x=df,y=sv) expression(a) <environment: 0x0275a9b4> b Ave 1 0 1.5 2 1 3.5 

我怀疑ddply已经在ddply中进行了评估,这就是为什么我尝试的所有parent.frame()sys.frame()策略都失败了。