Nadpisuje funkcję importowaną w przestrzeni nazw

Ponieważ termplot Funkcja W R zawiera jakiś dziwny kod, który powoduje irytujące błędy, chcę ją nadpisać w moim własnym kodzie testowym, dopóki nie znajdę bardziej trwałego rozwiązania. Problem polega na tym, że zmieniona funkcja nie jest ładowana przez pakiet mgcv. Pakiet mgcv ładuje termplota z pakietu stats w jego przestrzeni nazw, używając importFrom() w pliku przestrzeni nazw.

Jak mogę przekonać mgcv do użycia zmienionego termplot? Próbowałem:

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

I po zastosowaniu do obiektów lm działa to i zmieniony termplot jest używany. Ale podczas korzystania z obiektów gam wykonanych przez pakiet mgcv, to nie działa. Nie zamierzam budować pakietu statystyk ze źródła, jeśli mogę go uniknąć...

Aby wyjaśnić, próbowałem również z

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

We wszystkich możliwych kombinacjach, przed podłączeniem mgcv, po podłączeniu mgcv i nie udało mi się go uruchomić.


EDIT:

Wypróbowałem wszystkie podane tutaj opcje (poza przebudową obu pakietów) i nie mogłem go uruchomić. Łatwym wyjściem dla mnie jest użycie funkcji owijania. Tę dyskusję można znaleźć tutaj . Dzięki za wszystkie wskazówki.


Powtarzalny przykład:

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 wywołuje termplot dla nie-gładkich terminów (w tym przypadku x3), ale nie znajduje nowej funkcji termplot.


EDIT2: najwyraźniej mój przykład działa. Widzę teraz rozwiązałem własne pytanie: w pierwszym kodzie nie dodałem zarówno przestrzeni nazw, jak i pakietu w assignInNamespace. Ważne jest, aby pamiętaj, aby zmienić funkcję zarówno w przestrzeni nazw, jak i pakietu przed załadowaniem drugiego pakietu. Thx @hadley za wskazanie mi właściwego kierunku, @Marek za testowanie kodu i zgłoszenie, że działa, a reszta za podjęcie wysiłku, aby odpowiedzieć. [odpowiedz]

Author: Joris Meys, 2011-06-06

3 answers

Jestem zakłopotany - nie mogę rozgryźć, jak plot.gam lokalizuje termplot - z tego, co wiem, nie używa zwykłych zasad przeszukiwania. Wydaje się, że wymaga to głębszego zrozumienia przestrzeni nazw niż obecnie posiadam.

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)) 
 11
Author: hadley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-09 05:17:29

Spróbuj nadpisać funkcję, z której wywołujesz termplot. Domyślam się, że jest to plot.gam w mgcv pakiecie.

Najpierw załaduj niezbędny pakiet.

library(mgcv)

Oto Twoja alternatywna Funkcja termplot, dodana do przestrzeni nazw 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"))

Podobnie, oto funkcja wrapper, dodana do przestrzeni nazw 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"))

Oto przykład do przetestowania, zaczerpnięty z ?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
Author: Richie Cotton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-06 17:17:50

Myślę, że funkcja trace() wykonuje automatycznie to, co zostało opisane powyżej. Do:

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

Gdzie 'gedit' to nazwa edytora tekstu. Edytor otworzy się z oryginalnym kodem i możesz wkleić dowolny kod zastępczy, który chcesz.

Aby powrócić do oryginalnej wersji wystarczy untrace ('termplot')

Zastrzeżenie: próbowałem tego użyć, gdy edytor tekstu miał wiele otwartych plików i nie działał. Używam więc "gedit", edytora tekstu w moim systemie, którego nie używam często. Tędy. Jestem pewien, że R otworzy nową instancję "gedit".

Nie jestem pewien, czy to pomoże, ale myślę, że warto spróbować. Sekwencja wyszukiwania, gdy istnieją przestrzenie nazw, jest naprawdę myląca.
 2
Author: Andre Michaud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-06 19:47:16