Подтвердить что ты не робот

Переопределить функцию, импортированную в пространстве имен

Поскольку функция 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 для тестирования кода и сообщения об этом работает, а остальное - для ответа.

4b9b3361

Ответ 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".

Я не уверен, что это поможет, но я думаю, что стоит попробовать. Последовательность поиска, когда существуют пространства имен, действительно запутывает.