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

Posted

技术标签:

【中文标题】R:临时覆盖函数和范围/命名空间【英文标题】:R: temporarily overriding functions and scope/namespace 【发布时间】:2012-03-12 13:45:36 【问题描述】:

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

【问题讨论】:

【参考方案1】:

我们展示了如何使用代理对象来做到这一点(请参阅此document 的代理部分),首先使用proto package,然后不使用:

1) 原型。由于confint.lm 正在调用vcov,我们需要确保(a)我们对vcov 的新替换是在修改后的confint.lm 的环境中,并且(b)修改后的confint.lm 仍然可以从其访问对象原版的。 (例如confint.lm在stats中调用了隐藏函数format.perc,所以如果我们不安排第二点为真,隐藏函数就无法访问。)

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

另一个例子,见例子2here。

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 包,但它似乎很有用。我继续阅读小插图,这是一本很好的书。感谢您的努力!【参考方案2】:

这是因为函数confintvcov 都在命名空间“stats”中。您在此处调用的 confint() 有效地获取了 stats::vcov,这很大程度上是因为这就是名称空间的用途 - 您可以编写自己的版本,但不会损害其他预期的行为。

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

【讨论】:

好的,所以除了 class(model)

以上是关于R:临时覆盖函数和范围/命名空间的主要内容,如果未能解决你的问题,请参考以下文章

如何覆盖包命名空间中的不可见函数?

函数进阶

*args **kwargs函数的命名空间。

命名空间和作用域

Javascript命名空间 - 如何根据命名导出函数范围内定义的函数和变量?

python 函数进阶