Как переопределить невидимую функцию в пространстве имен пакета? - PullRequest
28 голосов
/ 05 января 2012

Я хочу изменить невидимую функцию пакета. Для видимых функций, то есть функций, которые не имеют звёздочки, когда к ним вызывается methods, я нашел два сообщения о том, как мне достичь своей цели:

  1. Использование assignInNamespace: см. Сообщение на R-help .
  2. Использование fix: см. Сообщение о stackoverflow

Хотя оба подхода работают для экспортированной / видимой функции (я использую predict.lm в качестве примера ниже для второго подхода и проверил первый подход с функцией subset.data.frame), они не работают для невидимой функция, например predict.ar. Это почему? Есть ли обходной путь?

Вот минимальный пример:

Показать, что предикат.lm виден, предикат.ar - нет:

methods(predict)
 [1] predict.Arima*             predict.HoltWinters*       predict.StructTS*         
 [4] predict.ar*                predict.arima0*            predict.glm               
 [7] predict.lm                 predict.loess*             predict.mlm               
[10] predict.nls*               predict.poly               predict.ppr*              
[13] predict.prcomp*            predict.princomp*          predict.smooth.spline*    
[16] predict.smooth.spline.fit*

Применить predict.lm:

x <- rnorm(5)
y <- x + rnorm(5)
predict(lm(y ~ x))
#          1          2          3          4          5 
#  1.0783047  1.5288031  0.3268405  0.8373520 -0.9833746

Измените predict.lm, введя cat ("Первая строка изменена для Предсказания.m \ n") в начале функции тела. (Вы должны сделать это вручную в редакторе):

fix(predict.lm)
predict(lm(y ~ x))
# First line changed for predict.lm
#          1          2          3          4          5 
#  1.0783047  1.5288031  0.3268405  0.8373520 -0.983374

Применить predict.ar:

sunspot.ar <- ar(sunspot.year)
predict(sunspot.ar, n.ahead=25)
# $pred
# Time Series:
# Start = 1989 
# End = 2013 

Попробуйте изменить predict.ar:

fix(predict.ar) #Here, an empty function body appears for me
fix("stats:::predict.ar") #Here as well
fix(stats:::predict.ar)
#Error in fix(stats:::predict.ar) : 'fix' requires a name

Попробуйте вместо этого использовать assignInNamespace. (Обратите внимание, что я просто скопировал функцию stats:::predict.ar в редакторе и добавил строку cat("First line changed for predict.ar\n") в начале тела. Поскольку тело функции довольно длинное, я показываю только первые пару строк здесь)

mypredict <- function (object, newdata, n.ahead = 1, se.fit = TRUE, ...) 
{
    cat("First line changed for predict.ar\n")
    if (n.ahead < 1) 
        stop("'n.ahead' must be at least 1")
    #Rest of body of stats:::predict.ar
}
assignInNamespace("predict.ar", mypredict, ns="stats")
predict(sunspot.ar, n.ahead=25)
# First line changed for predict.ar
# Error in predict.ar(sunspot.ar, n.ahead = 25) : 
#   object 'C_artoma' not found

Так как «Первая строка изменена для предиката .ar» фактически выводится на консоль, предикат.ар должен быть изменен. Однако, почему объект 'C_artoma' больше не найден?

ОБНОВЛЕНИЕ: ОК, это очень неловко, но я больше не могу удалить этот пост: ответ был уже по ссылке, которую я дал с ответом Ричи Коттона в конце. Извините за потраченное время! Я думаю, что все проверил, и тогда я не вижу очевидного. Может ли кто-то просто опубликовать это как ответ, и я принимаю это. Снова извините.

fixInNamespace(predict.ar, pos="package:stats")

1 Ответ

23 голосов
/ 05 января 2012

Используйте fixInNamespace.:)

fixInNamespace("predict.ar", "stats")

или

fixInNamespace("predict.ar", pos="package:stats")

(Несколько лет спустя ...)
Из комментария Николаса Х: если вы хотите отправить какой-то код в CRANзависит от внутренней функции из другого пакета, она выдаст предупреждение о сборке и будет отклонена R-core.Если вам нужна эта внутренняя функция, вам нужно просто взять ее копию с помощью оператора ::: и поддерживать ее самостоятельно.

predict.ar <- stats:::predict.ar
...