考虑以下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都是通用函数,我不知道这是否是它无法正常工作的原因。这不是我感兴趣的具体例子;而是概念课。这是命名空间还是范围“问题”?
答案 0 :(得分:4)
我们使用代理对象展示了如何执行此操作(请参阅此document的代理部分),首先使用proto package,然后不使用:
1)proto 。由于confint.lm
正在调用vcov
,我们需要确保(a)vcov
的新替换位于修订后的confint.lm
环境中,以及(b)修订后的confint.lm
1}}仍然可以从原始对象访问对象。 (例如,confint.lm
调用统计信息中的隐藏函数format.perc
,因此如果我们没有安排第二个点为真,则无法访问隐藏函数。)
为了执行上述操作,我们创建了一个新的confint.lm
,除了它有一个新环境(代理环境),其中包含我们的替换vcov
且其父级反过来是原始的confint.lm
环境。下面,代理环境被实现为一个proto对象,其中要知道的关键项是:(a)proto对象是环境,(b)以显示的方式在proto对象中放置一个函数,将其环境更改为proto对象。另外,为了避免从confint
到confint.lm
的S3调度出现任何问题,我们直接调用confint.lm
方法。
虽然hccm
似乎没有任何不同的结果,但我们可以通过注意trace
的输出来验证它是否已运行:
library(car)
library(proto)
trace(hccm)
model <- lm(len ~ dose, data=ToothGrowth)
proto(environment(stats:::confint.lm), # set parent
vcov = function(x) hccm(x), #robust var-cov matrix
confint.lm = stats:::confint.lm)[["confint.lm"]](model)
有关其他示例,请参阅示例2 here。
2)环境。没有proto的代码有点繁琐(实际上它大约是代码大小的两倍)但是它在这里:
library(car)
trace(hccm)
model <- lm(len ~ dose, data=ToothGrowth)
local({
vcov <- function(x) hccm(x) #robust var-cov matrix
confint.lm <- stats:::confint.lm
environment(confint.lm) <- environment()
confint.lm(model) # confint will call vcov, but not the above one.
}, envir = new.env(parent = environment(stats:::confint.lm)))
编辑:清晰度的各种改进
答案 1 :(得分:2)
这是因为函数confint
和vcov
都在名称空间“stats”中。你在这里调用的confint()实际上得到了stats :: vcov,几乎是因为这就是命名空间的用途 - 你可以编写你自己的东西版本,但不会损害其他预期的行为。
在第一个示例中,您仍然可以安全地调用依赖于stats :: lm的其他函数,并且不会因本地修改而感到不安。