cof*_*nky 6 environment r function plyr
关于范围,环境和功能的讨论已经很多.参见此处或此处.但是,我不确定我是否找到了解决以下问题的好方法:
df <- data.frame(id=rep(LETTERS[1:2],each=2), x=1:4)
d <- -1
myfun <- function(df, d){
require(plyr)
new.dat <- ddply(df, .(id), transform, x=x*d)
return(new.dat)}
myfun(df, 1)
Run Code Online (Sandbox Code Playgroud)
您可以轻松验证是否使用了全局定义d=-1,而不是d=1参数中提供的内容.(如果不d存在全局定义,则object not found返回消息)现在最大的问题是:如何d使用所使用的函数而不是全局定义的参数d?
我的印象是以下应该有效:
myfun2 <- function(df, d){
here <- environment()
new.dat <- ddply(df, .(id), transform, x=x*with(here,d))
return(new.dat)}
myfun2(df, 1)
Run Code Online (Sandbox Code Playgroud)
我的理解是从环境中with(here, d)检索对象.所以,结果应该是.但是,返回错误,说dhere1
Error in eval(substitute(expr), data, enclos = parent.frame()) :
invalid 'envir' argument of type 'closure'
Run Code Online (Sandbox Code Playgroud)
我不确定我理解为什么这不起作用,如果有人能够对此有所了解,或者如果你能提供替代解决方案,我会很高兴.请注意,将整个ddply-statement 包装起来with(...)似乎也没有帮助.
有效的解决方案是attach函数内的当前环境:
myfun3 <- function(df, d){
here <- environment()
attach(here)
new.dat <- ddply(df, .(id), transform, x=x*d)
detach(here)
return(new.dat)
}
Run Code Online (Sandbox Code Playgroud)
但我不喜欢这个解决方案,因为它通过屏蔽全局定义d的本地工作d,我认为不是很优雅.
任何评论/指针都表示赞赏.
要唤醒惰性求值并确保您使用的是本地d参数,请使用force。添加这一行:
d <- force(d)
Run Code Online (Sandbox Code Playgroud)
到 开始myfun。
好吧,看来我误解了这个问题。在这种情况下,问题是ddply具有非标准评估,并且仅在应用转换时查找内部变量,因此即使您它df也看不到本地变量。正如 Hadley 指出的,您需要将一个调用包装到.dforcetransformhere
myfun <- function(df, d){
require(plyr)
new.dat <- ddply(df, .(id), here(transform), x=x*d)
return(new.dat)}
Run Code Online (Sandbox Code Playgroud)
不相关的小代码改进:由于您没有对returns 的
情况执行任何操作,因此您应该将其替换为. 是一个改进的requireFALSElibrary
mutate直接替代替代transform。
你不需要明确的return.
myfun <- function(df, d){
library(plyr)
ddply(df, .(id), here(mutate), x=x*d)}
Run Code Online (Sandbox Code Playgroud)