Переопределить функцию, импортированную в пространстве имен
Поскольку функция termplot
в R содержит некоторый странный код, который дает мне раздражающие ошибки, я хочу переопределить его в своем собственном тестовом коде, пока не найду более постоянное решение. Проблема в том, что измененная функция не загружается пакетом mgcv
. Пакет mgcv
загружает termplot из пакета статистики в своем пространстве имен, используя importFrom()
в файле NAMESPACE.
Как я могу убедить mgcv использовать измененный термин? Я пробовал:
unlockBinding("termplot", as.environment("package:stats"))
assign("termplot", my.termplot, as.environment("package:stats"))
lockBinding("termplot", as.environment("package:stats"))
и при применении к lm-объектам это работает, и используется измененный терминологический план. Но при использовании gam-объектов, сделанных пакетом mgcv, это не работает. Я не собираюсь строить пакет статистики из исходного кода, если я могу его избежать...
Чтобы уточнить, я также пробовал с помощью
assignInNamespace("termplot", my.termplot, ns="stats")
assignInNamespace("termplot", my.termplot, ns="mgcv")
во всех возможных комбинациях, перед прикреплением 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(y ~ s(x0) + s(x1) + s(x2) + x3, data = dat)
plot(b,all=TRUE)
plot.gam
вызывает в терминах termplot для негладких членов (x3 в этом случае), но не может найти новую функцию termplot.
EDIT2: видимо, мой пример работает. Я вижу, теперь я решил свой собственный вопрос: в первом коде я не добавлял пространство имен и пакет в assignInNamespace. Важно помнить об изменении функции как в пространстве имен, так и в пакете перед загрузкой другого пакета. спасибо @hadley за то, что указал мне в правильном направлении, @Marek для тестирования кода и сообщения об этом работает, а остальное - для ответа.
Ответы
Ответ 1
Я в тупике - я не могу понять, как 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))
Ответ 2
Попробуйте перезаписать функцию, из которой вы вызываете 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)
Ответ 3
Я думаю, что функция trace() автоматически выполняет попытку выше. У:
trace('termplot', edit='gedit')
Где gedit - это имя текстового редактора. Редактор откроется с исходным кодом, и вы можете вставить любой желаемый код замены.
Чтобы вернуться к исходной версии просто untrace ('termplot')
Предостережение. Я попытался использовать это, когда в текстовом редакторе было открыто много файлов, и это не сработало. Поэтому я использую "gedit", текстовый редактор в моей системе, который я часто не использую. Таким образом, я уверен, что R откроет новый экземпляр "gedit".
Я не уверен, что это поможет, но я думаю, что стоит попробовать. Последовательность поиска, когда существуют пространства имен, действительно запутывает.