在函数中ddply找不到对象的对象
这真的对我调试R代码的能力提出了挑战。在函数中ddply找不到对象的对象
我想用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
任何想法? NewColName甚至在函数内定义!
我认为这个问题的答案loops-to-create-new-variables-in-ddply可能对我有帮助,但是我今天做了足够的头撞,现在是时候举手并寻求帮助。
您可以用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
看起来像你有环境问题。全球分配解决了这个问题,但在一个人的灵魂的费用:
library(plyr)
a = c(1,2,3,4)
b = c(0,0,1,1)
c = c(5,6,7,8)
d.f = data.frame(a,b,c)
sv = c("b")
ColName = "a"
ddply(d.f, 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=d.f,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=d.f,y=sv)
通过使用get
拔出从早期环境my.parse,我们可以得出非常接近,但还是要过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=d.f,y=sv)
expression(a)
<environment: 0x0275a9b4>
b Ave
1 0 1.5
2 1 3.5
我怀疑ddply
在.GlobalEnv评估已,这就是为什么所有的parent.frame()
和sys.frame()
战略的我试过失败。
我summarize
或transform
或东西结合时ddply
,并且不是足够聪明可以洞察到浏览各种环境的来龙去脉我倾向于通过简单地不使用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)
显然,是“手动”做这个东西成本,但它往往避免处理那些来自结合ddply
和summarize
评价问题的头痛。这并不是说,当然,哈德利将无法与解决方案展示了......
问题在于plyr软件包本身的代码。在汇总功能中,有一行eval(substitute(...),.data,parent.frame())
。众所周知,parent.frame()可以做出非常时髦和意想不到的事情。 T
他对@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
今天的解决这个问题,使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,捕获当前上下文。
辉煌!当一起使用lubridate和plyr时,请确保您特别提到plyr :: here()(因为lubridate不幸在这里重新定义()) –
更多信息:https://github.com/hadley/plyr/问题/ 3 – Lennert
我怀疑该解决方案可能需要@Hadley函数:-) –
尝试所有这些努力。群头猛击永远是我的赞赏......我会保持灵魂 –