R:暂时覆盖函数和范围/命名空间
考虑以下 R 代码:
local({
lm <- function(x) x^2
lm(10)
})
这会暂时覆盖 lm
函数,但是一旦执行 local
,它将“恢复正常”。我想知道为什么相同的方法在下一个简单示例中似乎不起作用:
require(car)
model <- lm(len ~ dose, data=ToothGrowth)
local({
vcov <- function(x) hccm(x) #robust var-cov matrix
confint(model) # confint will call vcov, but not the above one.
})
confint 函数使用 vcov 函数来获取系数的标准误差,并且这个想法是通过暂时覆盖 vcov 来使用强大的 var-cov 矩阵,而无需“手动”执行操作或更改函数。
vcov 和 confint 都是通用函数,我不知道这是否是它无法按预期工作的原因。这不是我感兴趣的具体例子;而是概念性的课程。这是命名空间还是范围“问题”?
Consider the following R code:
local({
lm <- function(x) x^2
lm(10)
})
This temporarily overrides the lm
function, but once local
has been executed it will "be back to normal". I am wondering why the same approach does not seem to work in this next simple example:
require(car)
model <- lm(len ~ dose, data=ToothGrowth)
local({
vcov <- function(x) hccm(x) #robust var-cov matrix
confint(model) # confint will call vcov, but not the above one.
})
The confint
function uses the vcov
function to obtain standard errors for the coefficients, and the idea is to use a robust var-cov matrix by temporarily overriding vcov
, without doing things "manually" or altering functions.
Both vcov and confint are generic functions, I don't know if this is the reason it does not work as intended. It is not the specific example I am interested in as such; rather the conceptual lesson. Is this a namespace or a scope "issue"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我们展示了如何使用代理对象执行此操作(请参阅本文档的代理部分) ,首先使用proto 包,然后不使用:
1) proto。由于
confint.lm
正在调用vcov
,我们需要确保 (a) 我们对vcov
的新替换位于修订后的confint 中。 lm
的环境和 (b) 修改后的confint.lm
仍然可以访问其原始对象。 (例如,confint.lm
调用 stats 中的隐藏函数format.perc
,因此如果我们没有安排第二点为 true,则无法访问隐藏函数.)为了执行上述操作,我们创建一个新的
confint.lm
,它是相同的,只是它有一个新环境(代理环境),其中包含我们的替换vcov
并且其父级又是原始的confint.lm
环境。下面,代理环境被实现为原始对象,其中需要了解的关键项目是:(a) 原始对象是环境,以及 (b) 按照所示方式将函数放置在原始对象中,将其环境更改为该原始对象。另外,为了避免 S3 将confint
分派到confint.lm
时出现任何问题,我们直接调用confint.lm
方法。虽然
hccm
在这里似乎没有任何不同的结果,但我们可以通过观察trace
的输出来验证它是否已运行:有关另一个示例,请参见示例 2 此处。
2) 环境。没有原型的代码有点繁重(事实上,它大约使代码大小增加了一倍),但这里是:
编辑:清晰度方面的各种改进
We show how to do this using proxy objects (see Proxies section of this document), first using the proto package and then without:
1) proto. Since
confint.lm
is callingvcov
we need to ensure that (a) our new replacement forvcov
is in the revisedconfint.lm
's environment and (b) the revisedconfint.lm
can still access the objects from its original. (For example,confint.lm
calls the hidden functionformat.perc
in stats so if we did not arrange for the second point to be true that hidden function could not be accessed.)To perform the above we make a new
confint.lm
which is the same except it has a new environment (the proxy environment) which contains our replacmentvcov
and whose parent in turn is the originalconfint.lm
environment. Below, the proxy environment is implemented as a proto object where the key items to know here are: (a) proto objects are environments and (b) placing a function in a proto object in the way shown changes its environment to be that proto object. Also to avoid any problems from S3 dispatch ofconfint
toconfint.lm
we call theconfint.lm
method directly.Although the
hccm
does not seem to have any different result here we can verify that it was run by noticing the output of thetrace
:For another example, see example 2 here.
2) environments. The code is a bit more onerous without proto (in fact it roughly doubles the code size) but here it is:
EDIT: various improvements in clarity
这是因为函数
confint
和vcov
都位于命名空间“stats”中。您在此处调用的 confint() 有效地获取 stats::vcov,很大程度上是因为这就是命名空间的用途 - 您可以编写自己的版本,但不会损害其他预期的行为。在第一个示例中,您仍然可以安全地调用依赖 stats::lm 的其他函数,并且不会因本地修改而感到不安。
This is because the functions
confint
andvcov
are both in the namespace "stats". The confint() you call here effectively gets stats::vcov, pretty much because that is what namespaces are for - you are allowed to write your own versions of things but not to the detriment of otherwise expected behaviour.In your first example, you can still safely call other functions that rely on stats::lm and that will not get upset by your local modification.