再次:在功能内设置环境 [英] Once again: Setting the environment within a function

查看:63
本文介绍了再次:在功能内设置环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

There are many discussions about scoping, environments and functions already. See e.g. here or here. However, I am not sure I have found a good solution to the following problem:

 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 ,则返回找不到对象消息)现在最大的问题是:如何制作 d 函数的参数而不是全局定义的 d ?

You can easily verify that the globally defined d=-1 was used, instead of the d=1 as provided in the argument. (If no globally defined d exists, then a object not found message is returned) The big question is now: how do I make the d argument to the function used instead of the globally defined d?

我觉得以下方法应该有效:

I was under the impression that the following should work:

      myfun2 <- function(df, d){
          here <- environment()
          new.dat <- ddply(df, .(id), transform, x=x*with(here,d)) 
          return(new.dat)}
      myfun2(df, 1)

据我了解, with(此处为d)从环境 here 中检索对象 d .因此,结果应为 1 .但是返回错误,说

It is my understanding that with(here, d) retrieves the object d from the environment here. So, the result should be 1. An error is returned, though, saying

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

我不确定我为什么不能这样做,如果有人可以对此有所了解,或者您可以提供替代解决方案,我将非常高兴.请注意,将整个 ddply 语句包装到 with(...)中似乎也无济于事.

I am not sure I understand why this does not work, and I would be happy if anyone could shed some light on this, or if you could provide alternative solutions. Note that wrapping the entire ddply-statement into with(...) does not seem to help either.

一种可行的解决方案是在功能内附加当前环境:

A solution that does work is to attach the current environment inside the function:

 myfun3 <- function(df, d){
   here <- environment()
   attach(here)
   new.dat <- ddply(df, .(id), transform, x=x*d) 
   detach(here)
   return(new.dat)
 }

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

but I don't like this solution since it works by masking the globally defined d with the local d, which I think is not very elegant.

任何评论/指针都值得赞赏.

Any comments / pointers are appreciated.

推荐答案

要唤醒延迟评估并确保您使用的是本地 d 参数,请使用 force .添加此行:

To wake up the lazy evaluation and be sure that you are using the local d argument, use force. Add this line:

d <- force(d)

myfun 的开头.

好的,看来我误解了这个问题.在这种情况下,问题在于 ddply 具有非标准评估,并且在应用转换时仅在 df 内部查找变量,因此看不到本地d ,即使您 force .正如Hadley所指出的,您需要包装 transform 来插入对 here 的调用.

OK, it seems that I misunderstood the problem. In this case, the problem is that ddply has non-standard evaluation and only looks inside df for variables when applying transformations, so it doesn't see the local d even if you force it. As Hadley pointed out, a you need to wrap transform insdie a call to 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 .

Minor unrelated code improvements:
Since you aren't doing anything with the case when require returns FALSE, you should swap it with library.
mutate is an improved drop-in replacement for alternative to transform.
You don't need the explicit return.

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

这篇关于再次:在功能内设置环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆