R:临时覆盖函数和作用域/命名空间

6
考虑以下 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个回答

4

我们展示如何使用代理对象实现这一点(请参见此文档的代理部分),首先使用proto包,然后再次进行操作:

1)proto。由于confint.lm调用了vcov,我们需要确保(a)我们新替换的vcov在修改后的confint.lm环境中,并且(b)修改后的confint.lm仍然可以访问其原始对象。(例如,confint.lm在统计中调用隐藏函数format.perc,如果我们没有安排第二点为真,则无法访问该隐藏函数。)

为了执行上述操作,我们创建一个新的confint.lm,它与原来的相同,只是有一个新的环境(代理环境),其中包含我们替换的vcov,而其父级则是原始的confint.lm环境。下面,代理环境被实现为一个proto对象,需要知道的关键项是:(a)proto对象是环境,(b)以所示方式将函数放入proto对象中会更改其环境为该proto对象。此外,为避免出现对confint.lm的S3分派到confint的任何问题,我们直接调用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个示例这里

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)))

编辑:在清晰度方面做出了各种改进


太棒了,我之前不熟悉proto包,但它看起来非常有用。我继续阅读了vignette,感觉很不错。感谢你的努力! - Stefan

2
这是因为函数confintvcov都在命名空间"stats"中。你在此处调用的confint()实际上得到了stats::vcov,基本上就是因为这就是命名空间的作用 - 你可以编写自己版本的东西,但不能损害其他预期行为。
在您的第一个示例中,您仍然可以安全地调用依赖于stats::lm的其他函数,并且不会受到您的本地修改的影响。

好的,除了class(model) <- c("lmr", class(model)); vcov.lmr <- function(x) hccm(x); confint(model);之外,没有指向所需函数的技巧吗?(对于内联注释感到抱歉) - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接