How can I prevent a library from masking functions

  1. It is possible to prevent some functions from being masked?

I don't believe so but I could be wrong. I'm not sure what this would look like

  1. Is it possible to mask "the masking function" (e.g. xgboost::slice) with an early imported function (e.g. dplyr::slice)?

If you're asking about just or use in an interactive session you can always just define slice to be the function you actually want to use like so

slice <- dplyr::slice

and then you can use slice as if it is the dplyr version (because now it is).


The next version of R has this in the NEWS{.Rd} file (quoted from the NEWS file post-build):

• The import() namespace directive now accepts an argument except
  which names symbols to exclude from the imports. The except
  expression should evaluate to a character vector (after
  substituting symbols for strings). See Writing R Extensions.

There referenced text from the manual is here (in raw texi format).

So soon we can. Right now one cannot, and that is a huge pain in the aRse particular when functions from Base R packages are being masked: lag(), filter(), ...

We have used the term anti-social for this behaviour in the past. I don't think it is too strong.

To illustrate the problem, here is a snippet of code I wrote a decade ago (and had it posted on the now-vanished R Graph Gallery) which uses a clever and fast way to compute a moving average:

  ## create a (normalised, but that's just candy) weight vector
  weights <- rep(1/ndays, ndays)
  ## and apply it as a one-sided moving average calculations, see help(filter)
  bbmiddle <- as.vector(filter(dat$Close, weights,
                               method="convolution", side=1))

If you do library(dplyr) as you might in an interactive session, you're dead in the water as filter() is now something completely different. Not nice.


The solution is to manage your namespace like it is common to do in other languages. You can selectively import dplyr functions:

select <- dplyr::select

For convenience you can also import the whole package and selectively reimport functions from previously attached packages:

library("dplyr")
filter <- stats::filter

R has a great module system and attaching whole namespaces is especially handy for interactive use. It does requires a bit of manual adjusting if the preferences of the package authors do not match yours.

Note that in packages and long-term maintenance scripts you should privilege selective imports, in part because it is hard to predict new exported functions in future releases. Having several packages imported in bulk might give rise to unexpected masking over time.

More generally a good rule is to rely on a single attached package and selectively import the rest. To this end the tidyverse package might be handy if you're a heavy tidyverse user because it provides a single import point for several packages.

Finally it seems from your question that you think that the order of attached packages might have side effects inside other packages. This is nothing to worry about because all packages have their own contexts. The import scheme will only affect your script.


You can also now use the conflict_prefer() function from the conflicted package to specify which package's function should "win" and which should be masked when there are conflicting function names (details here). In your example, you would run

conflict_prefer("slice", "dplyr", "xgboost") 

right after loading your libraries. Then when you run slice, it will default to using dplyr::slice rather than xgboost::slice. Or you can simply run

conflict_prefer("slice", "dplyr")

if you want to give dplyr::slice precedence over all other packages' slice functions.

Tags:

R