问题描述
已经有很多关于范围,环境和功能的讨论.参见例如或此处.但是,我不确定是否找到了解决以下问题的好方法:
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
是 alternative to transform
.
You don't need the explicit return
.
myfun <- function(df, d){
library(plyr)
ddply(df, .(id), here(mutate), x=x*d)}
这篇关于再次:在功能内设置环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!