How do I use functions in one R package masked by another package?
You could run into deeper problems, but at the top level car::recode
should do the trick. Not sure what happens if recode uses functions that are also masked.
Using functions from other packages - when to use package::function?
If you're actually creating an R package (as opposed to a script to source, R Project, or other method), you should NEVER use library()
or require()
. This is not an alternative to using package::function()
. You are essentially choosing between package::function()
and function()
, which as highlighted by @Bernhard, explicitly calling the package ensures consistency if there are conflicting names in two or more packages.
Rather than require(package)
, you need to worry about properly defining your DESCRIPTION and NAMESPACE files. There's many posts about that on SO and elsewhere, so won't go into details, see here for example.
Using package::function()
can help with above if you are using roxygen2
to generate your package documentation (it will automatically generate a proper NAMESPACE file.
How to unmask functions masked by `library(...)`?
As someone suggested in the comments, just redefine the vanilla baz
.
baz <- bar::baz
R - deliberately mask a function in a package function?
You can programatically create a function
foo <- function(...) if(!require('MASS')) stop('foo')
testfun <- function(fun){
require <- function(...) FALSE
fff <- function(){}
formals(fff) <- formals(fun)
body(fff) <- body(fun)
fff
}
testfoo <- testfun('foo')
require
is defined as is testfun
when the function is now created.
foo()
## Loading required package: MASS
detach(package:MASS)
testfoo()
# Error in testfoo() : foo
You could do something similar with local
, but I think it would be messier
eg
testfoo2 <- local({
require <- function(...) FALSE
foo <- function(...) if(!require('MASS')) stop('foo')
})
testfoo2()
## Error in testfoo2() : foo
(From mathematicalcoffee - a followup based on this answer).
I was able to define a function:
overrideIn <- function(f, ...) {
overrides <- list(...)
nms <- names(overrides)[names(overrides) != '']
# stub out the functions
for (nm in nms) {
assign(nm, overrides[[nm]])
}
# copy over f
fff <- function () {}
formals(fff) <- formals(f)
body(fff) <- body(f)
return(fff)
}
so that I could do
f <- overrideIn(myFunc, require=function (...) FALSE)
Now when I call f
it has the overridden version of require
in it, so I can do (using the fantastic testthat package):
expect_that(f(), throws_error('You do not have rgdal installed'))
A slightly more succinct version of the overide function (mnel again)
overRideIn2 <- function(fun,...){
e <- environment()
.list <- list(...)
ns <- nchar(names(.list))>0L
list2env(.list[ns], envir = e)
fff <- as.function(as.list(fun))
}
Masked functions in R
UsingR::QQPlot()
and/or QRMlib::QQPlot()
Try to load preferred library last, since it will mask the "unwanted" function...
All the best!
What does The following object is masked from 'package:xxx' mean?
The message means that both the packages have functions with the same names. In this particular case, the testthat
and assertive
packages contain five functions with the same name.
When two functions have the same name, which one gets called?
R will look through the search
path to find functions, and will use the first one that it finds.
search()
## [1] ".GlobalEnv" "package:assertive" "package:testthat"
## [4] "tools:rstudio" "package:stats" "package:graphics"
## [7] "package:grDevices" "package:utils" "package:datasets"
## [10] "package:methods" "Autoloads" "package:base"
In this case, since assertive
was loaded after testthat
, it appears earlier in the search path, so the functions in that package will be used.
is_true
## function (x, .xname = get_name_in_parent(x))
## {
## x <- coerce_to(x, "logical", .xname)
## call_and_name(function(x) {
## ok <- x & !is.na(x)
## set_cause(ok, ifelse(is.na(x), "missing", "false"))
## }, x)
## }
<bytecode: 0x0000000004fc9f10>
<environment: namespace:assertive.base>
The functions in testthat
are not accessible in the usual way; that is, they have been masked.
What if I want to use one of the masked functions?
You can explicitly provide a package name when you call a function, using the double colon operator, ::
. For example:
testthat::is_true
## function ()
## {
## function(x) expect_true(x)
## }
## <environment: namespace:testthat>
How do I suppress the message?
If you know about the function name clash, and don't want to see it again, you can suppress the message by passing warn.conflicts = FALSE
to library
.
library(testthat)
library(assertive, warn.conflicts = FALSE)
# No output this time
Alternatively, suppress the message with suppressPackageStartupMessages
:
library(testthat)
suppressPackageStartupMessages(library(assertive))
# Also no output
Impact of R's Startup Procedures on Function Masking
If you have altered some of R's startup configuration options (see ?Startup
) you may experience different function masking behavior than you might expect. The precise order that things happen as laid out in ?Startup
should solve most mysteries.
For example, the documentation there says:
Note that when the site and user profile files are sourced only the
base package is loaded, so objects in other packages need to be
referred to by e.g. utils::dump.frames or after explicitly loading the
package concerned.
Which implies that when 3rd party packages are loaded via files like .Rprofile
you may see functions from those packages masked by those in default packages like stats, rather than the reverse, if you loaded the 3rd party package after R's startup procedure is complete.
How do I list all the masked functions?
First, get a character vector of all the environments on the search path. For convenience, we'll name each element of this vector with its own value.
library(dplyr)
envs <- search() %>% setNames(., .)
For each environment, get the exported functions (and other variables).
fns <- lapply(envs, ls)
Turn this into a data frame, for easy use with dplyr.
fns_by_env <- data_frame(
env = rep.int(names(fns), lengths(fns)),
fn = unlist(fns)
)
Find cases where the object appears more than once.
fns_by_env %>%
group_by(fn) %>%
tally() %>%
filter(n > 1) %>%
inner_join(fns_by_env)
To test this, try loading some packages with known conflicts (e.g., Hmisc
, AnnotationDbi
).
How do I prevent name conflict bugs?
The conflicted
package throws an error with a helpful error message, whenever you try to use a variable with an ambiguous name.
library(conflicted)
library(Hmisc)
units
## Error: units found in 2 packages. You must indicate which one you want with ::
## * Hmisc::units
## * base::units
Prefering functions in tidyverse over other loaded packages
If you don't want to worry aboutpackage loading order, as you see in @benson23 answer, this is one way:
library(dplyr)
library(MASS)
select <- dplyr::select
Another way is using conflicted package:
library(conflicted)
library(dplyr)
library(MASS)
conflict_prefer("select", "dplyr")
At last, if you use want to use tidymodels meta-package (includes dplyr), you can do this too:
library(tidyverse)
library(tidymodels)
library(MASS)
tidymodels_prefer()
How can I prevent a library from masking functions
- 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
- 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).
Related Topics
How to Make Graphics with Transparent Background in R Using Ggplot2
How to Parametrize Function Calls in Dplyr 0.7
Get All Diagonal Vectors from Matrix
Rcpparmadillo Pass User-Defined Function
How to Define the "Mid" Range in Scale_Fill_Gradient2()
What Does "S3 Methods" Mean in R
Creating a Local R Package Repository
Remove All Line Breaks (Enter Symbols) from the String Using R
Splitting a File Name into Name,Extension
How to Add Multiple Columns to a Data.Frame in One Go
Include Space for Missing Factor Level Used in Fill Aesthetics in Geom_Boxplot
How to Delete Everything After Nth Delimiter in R
Ggplot2 0.9.0 Automatically Dropping Unused Factor Levels from Plot Legend
How to Tell Cran to Install Package Dependencies Automatically