覆盖在命名空间中导入的函数

时间:2011-06-06 15:59:21

标签: function r namespaces package

由于R中的termplot函数包含一些令我烦恼的错误的奇怪代码,我想在我自己的测试代码中覆盖它,直到我找到一个更永久的解决方案。问题是mgcv包未加载更改的功能。 mgcv包使用NAMESPACE文件中的importFrom()从其命名空间中的stats包加载termplot。

我怎样才能说服mgcv使用改变的termplot?我试过了:

unlockBinding("termplot", as.environment("package:stats"))
assign("termplot", my.termplot, as.environment("package:stats"))
lockBinding("termplot", as.environment("package:stats"))

当应用于lm-objects时,这个工作并且使用改变的termplot。但是当使用mgcv包生成的gam-object时,这不起作用。如果可以避免的话,我真的不打算从源代码构建stats包......

为了澄清,我也试过

assignInNamespace("termplot", my.termplot, ns="stats")
assignInNamespace("termplot", my.termplot, ns="mgcv")

在所有可能的组合中,在附加mgcv之后,在附加mgcv之后,我无法使其正常工作。


编辑:

我尝试了这里给出的所有选项(除了重建任何一个包),并且无法让它工作。对我来说简单的方法是使用包装函数。可以找到该讨论here。感谢您的所有提示。


可重现的例子:

my.termplot <- function (x) print("my new termplot")

  unlockBinding("termplot", as.environment("package:stats"))
  assignInNamespace("termplot", my.termplot, ns="stats", envir=as.environment("package:stats"))
  assign("termplot", my.termplot, as.environment("package:stats"))
  lockBinding("termplot", as.environment("package:stats"))


y <- 1:10
x <- 1:10
xx <- lm(y~x)
termplot(xx)
require(mgcv)
dat <- gamSim(1, n = 400, dist = "normal", scale = 2)
b <- gam(y ~ s(x0) + s(x1) + s(x2) + x3, data = dat)
plot(b,all=TRUE)

plot.gam为非平滑术语(本例中为x3)调用termplot,但未能找到新的termplot函数。


EDIT2:显然,我的例子有效。我现在看到我解决了自己的问题:在第一个代码中,我没有在assignInNamespace中添加命名空间和包。重要的是要记住在加载其他包之前更改命名空间和包中的功能。感谢@hadley指出我正确的方向,@ Mayk用于测试代码并报告它的工作原理,剩下的就是努力回答。

3 个答案:

答案 0 :(得分:11)

我很难过 - 我无法弄清楚plot.gam如何定位termplot - 据我所知,它并没有使用普通的范围规则。这似乎需要对名称空间的理解比我目前所拥有的更深入。

my.termplot <- function (x) print("my new termplot")

# where is it defined?
getAnywhere("termplot")
# in package and in namespace

unlockBinding("termplot", as.environment("package:stats"))
assign("termplot", my.termplot, "package:stats")

unlockBinding("termplot", getNamespace("stats"))
assign("termplot", my.termplot, getNamespace("stats"))

getAnywhere("termplot")[1]
getAnywhere("termplot")[2]
# now changed in both places

y <- 1:10
x <- 1:10 + runif(10)
xx <- lm(y ~ x)
termplot(xx) # works

library("mgcv")
b <- gam(y ~ s(x), data = data.frame(x, y))
plot(b) # still calls the old termplot

# I'm mystified - if try and find termplot as
# seen from the environment of plot.gam, it looks 
# like what we want
get("termplot", environment(plot.gam)) 

答案 1 :(得分:3)

尝试覆盖您正在调用的函数termplot。我猜这是plot.gam包中的mgcv

首先加载必要的包。

library(mgcv)

这是您的备用termplot函数,已添加到stats命名空间。

my.termplot <- function (model, ...) 
{
  message("In my.termplot")
}

unlockBinding("termplot", as.environment("package:stats"))
assign("termplot", my.termplot, as.environment("package:stats"))
lockBinding("termplot", as.environment("package:stats"))

同样,这是包装函数,添加到mgcv命名空间。

my.plot.gam <- function (x, ...) 
{
  message("In my.plot.gam")
  my.termplot()
}

unlockBinding("plot.gam", as.environment("package:mgcv"))
assign("plot.gam", my.plot.gam, as.environment("package:mgcv"))
lockBinding("plot.gam", as.environment("package:mgcv"))

以下是一个测试它的示例,取自?gam

dat <- gamSim(1, n = 400, dist = "normal", scale = 2)
b <- gam(y ~ s(x0) + s(x1) + s(x2) + s(x3), data = dat)
plot(b) 

答案 2 :(得分:2)

我认为trace()函数会自动执行上面尝试的操作。做:

trace('termplot', edit='gedit')

其中'gedit'是文本编辑器的名称。编辑器将打开原始代码,您可以粘贴您想要的任何替换代码。

要返回原始版本,只需取消('termplot')

警告:当文本编辑器打开了许多文件并且它不起作用时,我尝试使用它。所以我使用'gedit',我的系统上的文本编辑器,我不经常使用。这样我相信R会打开一个'gedit'的新实例。

我不肯定这会有所帮助,但我认为这值得一试。有命名空间时的搜索顺序真的令人困惑。