【问题标题】:Once again: Setting the environment within a function再次:在函数中设置环境
【发布时间】:2014-07-05 14:21:31
【问题描述】:

已经有很多关于范围、环境和功能的讨论。参见例如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 用于函数的参数而不是全局定义的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) 从环境here 中检索对象d。所以,结果应该是1。但是,返回一个错误,说

  Error in eval(substitute(expr), data, enclos = parent.frame()) : 
   invalid 'envir' argument of type 'closure' 

我不确定我是否理解为什么这不起作用,如果有人能对此有所了解,或者如果你能提供替代解决方案,我会很高兴。请注意,将整个 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)
 }

但我不喜欢这个解决方案,因为它通过用本地 d 屏蔽全局定义的 d 来工作,我认为这不是很优雅。

感谢任何 cmets / 指针。

【问题讨论】:

  • new.dat &lt;- ddply(df, .(id), function(x,d){x&lt;-x*d}, d) 有点作品,但不完全

标签: r function plyr environment


【解决方案1】:

要唤醒惰性求值并确保您使用的是本地 d 参数,请使用 force。添加这一行:

d <- force(d)

myfun的开头。


好的,看来我误解了这个问题。在这种情况下,问题在于ddply 具有非标准评估,并且在应用转换时仅在df 内部查找变量,因此即使您force 它也看不到本地d。正如 Hadley 指出的那样,您需要将 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 是一个改进的 drop-in 替代 替代方案到transform.
您不需要明确的return

myfun <- function(df, d){
      library(plyr)
      ddply(df, .(id), here(mutate), x=x*d)}

【讨论】:

  • mutate 不是替代transform;比较 transform(d, x=x*d, y=x)mutate(d, x=x*d, y=x)
  • 谢谢!那很有启发性。我仍然不明白为什么with(here, d)-solution 不起作用。提供一个数字而不是 d 有效(显然)。为什么写with(here, d) 不是一回事?我的理解是,从ddply 的角度来看,两者应该是等价的。
  • @coffeinjunky 在ddply 内,环境here 不可访问;错误消息令人困惑,因为“here”也是 plyr 函数的名称。
  • 好点!将其更改为here2 会导致object here2 not found 消息。所以,ddply 评估全局环境中的所有内容,即with(here2, d) 在全局环境中进行评估,但是在那里,尽管有明确的地址,但本地环境 here2 不可见?这是导致问题的原因吗?
  • 是的——这就像给火星或塔图因上的人寄明信片;尽可能具体,邮局不会到达。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
  • 2019-04-25
  • 1970-01-01
相关资源
最近更新 更多