覆盖在命名空间中导入的函数 [英] Override a function that is imported in a namespace

查看:128
本文介绍了覆盖在命名空间中导入的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于R中的 termplot 函数包含一些令人讨厌的bug的奇怪代码,我想在自己的测试代码中覆盖它,直到找到更长久解。问题在于改变的函数没有被 mgcv 包加载。 mgcv 包使用NAMESPACE文件中的 importFrom()从其名称空间中的stats包加载termplot。



我如何说服mgcv使用改变的termplot?我尝试过:

$ $ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ termplot,my.termplot,as.environment(package:stats))
lockBinding(termplot,as.environment(package:stats))

当应用于lm对象时,它将起作用并使用改变的termplot。但是,当使用mgcv包制作的gam-objects时,这不起作用。为了澄清,我也尝试过使用

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

所有可能的组合中,在附加mgcv之前,设法让它工作。






编辑:

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






一个可重现的例子:

 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(ys(x0)+ s(x1)+ s(x2)+ x3,data = dat)
plot(b,all = TRUE)

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






EDIT2:显然,我的例子有效。我现在看到我解决了我自己的问题:在第一个代码中,我没有在assignInNamespace中添加名称空间和包。在加载其他包之前,记住在命名空间和包中更改函数是很重要的。 Thx @hadley为我指出了正确的方向,@Marek用于测试代码并报告它的工作原理,其余部分用于努力解答。 解析方案

我被难住了 - 我找不到 plot.gam 是如何定位 termplot - 据我所知,它没有使用普通的范围规则。这似乎需要比我目前拥有更深入的命名空间的理解。

  my.termplot<  -  function(x)print( 我的新termplot)

#在哪里定义?
getAnywhere(termplot)
#在包和命名空间

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]
# b $ b $ < - 1:10
x < - 1:10 + runif(10)
xx < - lm(y〜x)
termplot(xx)#工作

library(mgcv)
b < - gam(y〜s(x),data = data.frame(x,y))
plot(b)#仍然会调用旧的termplot

#我很迷惑 - 如果试图从plot.gam的环境中查找termplot作为
#,它看起来像我们想要的

get(termplot,environment(plot.gam))


As the termplot function in R is containing some weird code that is giving me annoying bugs, I want to override it in my own test code until I find a more permanent solution. Problem is that the changed function is not loaded by the mgcv package. The mgcv package loads termplot from the stats package in its namespace, using importFrom() in the NAMESPACE file.

How can I convince mgcv to use the changed termplot? I tried :

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

and when applied to lm-objects, this works and the altered termplot is used. But when using gam-objects made by the mgcv package, this doesn't work. I'm not really going to build the stats package from source if I can avoid it...

To clarify, I also tried with

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

in all possible combinations, before attaching mgcv, after attaching mgcv, and I didn't manage to get it working.


EDIT :

I tried all options given here (apart from rebuilding either package), and couldn't get it to work. The easy way out for me is using a wrapper function. That discussion can be found here. Thanks for all the tips.


A reproducible example :

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 calls termplot for the non-smooth terms (x3 in this case), but fails to find the new termplot function.


EDIT2 : apparently, my example works. I see now I solved my own question: In the first code, I didn't add both the namespace and the package in assignInNamespace. It is important to remember to change the function both in the namespace and the package before loading the other package. Thx @hadley for pointing me in the right direction, @Marek for testing the code and reporting it works, and the rest for taking the effort to answer.

解决方案

I'm stumped - I can't figure out how plot.gam is locating termplot - it's not using the ordinary scoping rules as far as I can tell. This seems to need a deeper understanding of namespaces than I currently possess.

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

这篇关于覆盖在命名空间中导入的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆