R:暂时覆盖函数和范围/命名空间

时间:2012-02-22 08:19:23

标签: r namespaces scope

考虑以下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都是通用函数,我不知道这是否是它无法正常工作的原因。这不是我感兴趣的具体例子;而是概念课。这是命名空间还是范围“问题”?

2 个答案:

答案 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对象。另外,为了避免从confintconfint.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)

这是因为函数confintvcov都在名称空间“stats”中。你在这里调用的confint()实际上得到了stats :: vcov,几乎是因为这就是命名空间的用途 - 你可以编写你自己的东西版本,但不会损害其他预期的行为。

在第一个示例中,您仍然可以安全地调用依赖于stats :: lm的其他函数,并且不会因本地修改而感到不安。