R: What's the How to Overwrite a Function from a Package

R: what's the proper way to overwrite a function from a package?

There are lots of different cases here.

If it's a bug in someone else's package
Then the best practice is to contact the package maintainer and persuade them to fix it. That way everyone gets the fix, not just you.

If it's a bug while developing your own package
Then you need to find a workflow where rebuilding packages is easy. Like using the devtools package and typing build(mypackage), or clicking a button ("Build & Reload" in RStudio; "R CMD build" in Architect).

If you just want different behaviour to an existing package
If it isn't a bug as such, or the package maintainer won't make the fix that you want, then you'll have to maintain you own copy of f1. Using assignInNamespace to override it in the existing package is OK for exploring, but it's a bit hacky so it isn't really suitable for a permanent solution.

Your best bet is to create your own package containing copies of f1 and f2. This is less effort than it sounds, since you can just define f2 <- existingpackage::f2.


In response to the comment:

Second and third cases makes sense if you are alone but they require to build and install the packages which is tricky in the case of my organisation as the packages are deployed on dozens of computer and I need root access to update the packages.

So take a copy of the existing package source, apply your patch, and host it on your company network or github or Bitbucket. Then the updated package can be installed programmatically via

install.packages("//some/network/path/mypackage_0.0-1.tar.gz", repos = NULL)

or

library(devtools)
install_github("mypackage", "mygithubusername")

Since the installation is just a line of code, you can easily push it to as many machines as you like. You don't need root access either - just install the package to a library folder that doesn't require root access to write to. (Read the Startup and .libPaths help pages for how to define a new library.) You'll need network access to those machines, but I can't help you with that. Speak to your network administrator or your boss or whoever can get you permission.

How to copy a foreign package and overwrite a function?

My sense is you have at least two potential options here. This first is what I think you need but I include both for completeness.

  1. Create your own package and extend the base package
  2. Create your own function that extends the base package function

nb: If you could provide the package and function you wish to extend that would be super helpful as I had to make this slightly generic. I have referenced the original StackOverflow posts that helped me in this situation. In terms of further/deeper reading my recommendation would be to read:

  • R Inferno By: Patrick Burns

    • Covers the nuances of R
    • Read Section 7 - Circle 7 Tripping on Object Orientation
  • R Packages By: Hadley Wickham

    • Chapter 8. Namespaces
    • Hadley does a great job of explaining R namespaces.

Solution Options:

Create Your own Package and extend base package

In this context, my sense is to direct you to take a look at section 1.5.6 of the Writing R Extensions manual.

  • https://cran.r-project.org/doc/manuals/R-exts.pdf

Why? Well, based on your description my sense would be to import the functions from the package, and then write your extension function.

You can do this by importing the classes and methods explicitly, with directives

importClassesFrom(package, ...)
importMethodsFrom(package, ...)

listing the classes and functions with methods respectively. Suppose we had two small packages A and B with B using A. Then they could have NAMESPACE files

export(f1, ng1)
exportMethods("[")
exportClasses(c1)

and

importFrom(A, ng1)
importClassesFrom(A, c1)
importMethodsFrom(A, f1)
export(f4, f5)
exportMethods(f6, "[")
exportClasses(c1, c2)

respectively.

Note that importMethodsFrom will also import any generics defined in the namespace on those methods. It is important if you export S4 methods that the corresponding generics are available. You may, for example, need to import plot from graphics to make visible a function to be converted into its implicit generic. But it is better practice to make use of the generics exported by stats4 as this enables multiple packages to unambiguously set methods on those generics.

Here is the StackOverflow question and answer that helped me previously:

  • Ref: In R, how can I extend generic methods from one package in another?

Create your own function that extends the base package function

See: Overwrite method to extend it, using the original implementation

I hope the above helps.

R Package development: overriding a function from one package with a function from another?

The solution I ended up using (thanks to Uwe and Kurt), is using "local" to create a localized environment with the package options. If you're curious, the function is called "dendextend_options", and is here:
https://github.com/talgalili/dendextend/blob/master/R/zzz.r

Here is an example for its use:

dendextend_options <- local({
options <- list()
function(option, value) {
# ellipsis <- list(...)
if(missing(option)) return(options)

if(missing(value))
options[[option]]
else options[[option]] <<- value
}
})
dendextend_options("a")
dendextend_options("a", 1)
dendextend_options("a")
dendextend_options("a", NULL)
dendextend_options("a")
dendextend_options()

Overriding a package function inherited by another package

Changing the function in the formatR namespace doesn't change what knitr uses because knitr is already loaded. So, you could unload and reload it.

assignInNamespace("tidy.source", function()print("My tidy.source"), "formatR")
detach('package:knitr', unload=TRUE)
library(knitr)
get("tidy.source", envir=asNamespace("knitr"))
#function()print("My tidy.source")

How to override exported function from R package listed in Imports

One possibility could be to create a function length.path() in your own package. If the base type of your path-objects is compatible with base::length() you could just unclass it to avoid infinite recursion:

length.path <- function(x) length(unclass(x))

However, this is potentially slow compared to a direct call to base::length() because it copies the object and needs method dispatch two times.

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

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

Change internal function of a package

Try

?assignInNamespace

to replace .HMR.fit1 in the HMR package with your version.

Possible duplicate of :

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



Related Topics



Leave a reply



Submit