Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
290 views
in Technique[技术] by (71.8m points)

r - How do I override a non-visible function in the package namespace?

I basically want to change a non-visible function of a package. For visible functions, i.e. functions that have no asterix when methods is called on them, I found two posts how I could achieve my goal:

  1. Use assignInNamespace: see post on R-help.
  2. Use fix: see post on stackoverflow

Although both approaches work for an exported / visible function (I use predict.lm as an example further below for the second approach and tested the first approach with the function subset.data.frame), they do not work for a non-visible function, e.g. predict.ar. Why is that? Is there a workaround?

Here is a minimal example:

Show that predict.lm is visible, predict.ar is not:

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*

Apply 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

Change predict.lm by entering cat("First line changed for predict.lm ") at the beginning of the function body. (You have to do that manually in the editor):

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

Apply predict.ar:

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

Try to change 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

Try to use assignInNamespace instead. (Note that I just copied the function stats:::predict.ar in an editor and added the line cat("First line changed for predict.ar ") at the beginning of the body. Because the function body is quite long, I only show the first couple of lines here)

mypredict <- function (object, newdata, n.ahead = 1, se.fit = TRUE, ...) 
{
    cat("First line changed for predict.ar
")
    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

Since "First line changed for predict.ar" is actually printed to the console, predict.ar must have been changed. However, why is the object 'C_artoma' not found anymore?

UPDATE: OK, this is super embarrassing, but I can't delete that post anymore: The answer was already at the link I provided with Richie Cotton's answer at the end. Sorry for wasting your time! I think I checked everything and then I don't see the obvious. Could someone just post this as an answer an I accept it. Sorry again.

fixInNamespace(predict.ar, pos="package:stats")
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Use fixInNamespace. :)

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

or

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

(Several years later...)
From Nicholas H's comment: if you want to push some code to CRAN that depends upon an internal function from another package, it will throw a build warning and be rejected by R-core. If you want that internal function, you should just take a copy of it using the ::: operator and maintain it yourself.

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...