再次:在函数内设置环境

时间:2014-07-05 14:21:31

标签: r function plyr environment

关于范围,环境和功能的讨论已经很多。参见例如herehere。但是,我不确定我是否找到了解决以下问题的好方法:

 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来工作,我认为这不是很优雅。

赞赏任何评论/指示。

1 个答案:

答案 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)}