Override a function that is imported in a namespace

Solution 1:

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

Solution 2:

Try overwriting the function that you are calling termplot from. At a guess, this is plot.gam in the mgcv package.

First load the necessary package.

library(mgcv)

Here's your alternate termplot function, added to the stats namespace.

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

Likewise, here's the wrapper function, added to the mgcv namespace.

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

Here's an example to test it, taken from ?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) 

Solution 3:

I think the trace() function does automatically what is attempted above. Do:

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

Where 'gedit' is the name of a text editor. The editor will open with the original code and you can paste whatever substitution code you desire.

To return to the original version just untrace('termplot')

Caveat: I tried using this when the text editor had many files open and it didn't work. So I use 'gedit', a text editor on my system that I don't use often. This way I am sure that R will open a new instance of 'gedit'.

I'm not positive this will help, but I think it's worth a try. The search sequence when there are namespaces is really confusing.