关于范围,环境和功能的讨论已经很多。参见例如here或here。但是,我不确定我是否找到了解决以下问题的好方法:
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)
您可以轻松验证是否使用了全局定义的d=-1
,而不是参数中提供的d=1
。 (如果不存在全局定义的d
,则返回object not found
消息。现在最大的问题是:如何为所使用的函数创建d
参数而不是全局定义的{ {1}}?
我的印象是以下情况应该有效:
d
据我了解, myfun2 <- function(df, d){
here <- environment()
new.dat <- ddply(df, .(id), transform, x=x*with(here,d))
return(new.dat)}
myfun2(df, 1)
从环境with(here, d)
检索对象d
。因此,结果应为here
。但是,返回错误,说
1
我不确定我理解为什么这不起作用,如果有人能够对此有所了解,或者如果你能提供替代解决方案,我会很高兴。请注意,将整个 Error in eval(substitute(expr), data, enclos = parent.frame()) :
invalid 'envir' argument of type 'closure'
语句包装到ddply
中似乎也没有帮助。
一个有效的解决方案是with(...)
函数内的当前环境:
attach
但是我不喜欢这个解决方案,因为它通过使用本地 myfun3 <- function(df, d){
here <- environment()
attach(here)
new.dat <- ddply(df, .(id), transform, x=x*d)
detach(here)
return(new.dat)
}
屏蔽全局定义的d
来工作,我认为这不是很优雅。
赞赏任何评论/指示。
答案 0 :(得分:4)
要唤醒延迟评估并确保使用本地d
参数,请使用force
。添加以下行:
d <- force(d)
到myfun
的开头。
ddply
具有非标准评估,并且仅在应用转换时在df
内查找变量,因此即使您{d
也看不到本地force
{1}}它。正如哈德利指出的那样,你需要用transform
来打电话给here
。
myfun <- function(df, d){
require(plyr)
new.dat <- ddply(df, .(id), here(transform), x=x*d)
return(new.dat)}
轻微不相关的代码改进:
由于require
返回FALSE
时您没有做任何事情,因此您应该将其与library
交换。
mutate
是替代transform
的的改进替代品
您不需要明确的return
。
myfun <- function(df, d){
library(plyr)
ddply(df, .(id), here(mutate), x=x*d)}