From [package] import [function] in R
You can explicitly tell R which package should be used for a given function using the package::function()
construction. You can even use that to call functions from packages that you haven't loaded with library
.
library(dplyr) # Has a function called filter()
library(plyr) # Also has a filter() function
dplyr::filter(foo)
plyr::filter(bar)
If you want to make sure you're minimizing the possibility for confusion in your code, I highly recommend the conflicted
package, which forces you to explicitly identify the package for all ambiguous function calls: https://www.tidyverse.org/articles/2018/06/conflicted/
import all the functions of a package except one when building a package
The NAMESPACE file is somewhat flexible here, as described in Writing R Extensions.
The two main import directives are:
import(PACKAGE)
which imports all objects in the namespace into your package. The second option is to do specific imports using:
importFrom(PACKAGE, foo)
which gives you access to foo()
without needing the fully qualified reference PACKAGE::foo()
.
But these aren't the only two options. You can also use the except
argument to exclude just a handful of imports:
import(PACKAGE, except=c(foo,bar))
which gives you everything from PACKAGE's namespace but foo()
and bar()
. This is useful - as in your case - for avoiding conflicts.
For roxygen, great catch on figuring out that you can do:
#' @rawNamespace import(PACKAGE, except = foo)
to pass a raw NAMESPACE directive through roxygen.
How to import an R function from another package such that it would be available for the user?
The imported function must be exported in the NAMESPACE file for it to be available to users:
S3method(forecat, myobj)
importFrom(forecast, forecast)
export(forecast)
For an example, see the dplyr package's NAMESPACE file which imports %>%
from the magrittr package and exports it so that it is accessible by the user.
R package building: How to import a function from a package not on CRAN
A super easy trick is to add a ‘remotes’ field into our DESCRIPTION
file specifying the username/package_name target of our target package on Github.
Remotes:
github::User/PackageNotOnCRAN
Import:
PackageNotOnCRAN
Suggests:
devtools,
testthat
Not only will this work very well for files on github (github::
), but works for git, bitbucket, local packages and more.
More information, how I figured it out.
Importing Functions into Current Namespace
Use the source()
command. In your case:
source("/path/to/file/my_fn_lib1.r")
Incidentally, creating a package is fairly easy with the package.skeleton()
function (if you're planning to reuse this frequently).
How to import only one function from another package, without loading the entire namespace
You can't.
If you declare memisc
in the Imports:
field, the namespace will be loaded when the package is loaded and the exported objects will be findable by your package. (If you specify it in Depends:
, the namespace will be loaded and attached to the search path which makes the exported objects findable by any code.)
Part of loading a namespace is registering methods with the generic. (I looked but couldn't find a canonical documentation that says this; I will appeal to the fact that functions are declared as S3 methods in the NAMESPACE
file as evidence.) The defined methods are kept with the generic and have the visibility of the generic function (or, perhaps, the generic function's namespace).
Typically, a package will define a method either for a generic it creates or for a class it defines. The S3 object system does not have a mechanism for formally defining an S3 class (or what package created the class), but the general idea is that if the package defines functions which return an object with that class attribute (and is the only package that does), that class is that package's class. If either of these two conditions hold, there will not be a problem. If the generic is defined in the package, it can only be found if the package is attached; if the class is defined in the package, objects of that class would only exist (and therefore be dispatched on) if the package is attached and used.
In the memisc
example, neither holds. The aggregate
generic is defined in the stats
package and the formula
object is also defined in the stats
package (based on that package defining as.formula
, [.formula
, etc.) Since it is neither memisc
's generic nor memisc
's object, the effects can be seen even (and the method dispatched to) if memisc
is simply loaded but not attached.
For another example of this problem, but with reorder.factor
, see Reordering factor gives different results, depending on which packages are loaded.
In general, it is not good practice to add methods to generics for which the package does not control either the object or the generic; doubly so if it overrides a method in a core package; and egregiously so if it is not a backwards compatible function to the existing function in the core packages.
For your example, you may be better off copying the code for memisc::describe
into your package, although that approach has its own problems and caveats.
Export and import functions and code from one file to another in R
Technically, you can:
foo <- function() {
message("Hello")
}
dput(foo, "foo.R")
foo2 <- source("foo.R")$value
foo2()
#> Hello
Created on 2022-03-28 by the reprex package (v2.0.1)
But I have never seen anyone do this and the somewhat janky syntax is a good indication that what I wrote here is not inteded to save an load functions. You can also use saveRDS(foo, "foo.rds")
to save the function and readRDS("foo.rds")
to read it. Note that in both cases the name of the function is not stored so you need to assign it with foo3 <- readRDS("foo.rds")
.
I think what you would usually do is to create a file called (for example) "custom_functions.R" to store all your functions for a project and then use source("custom_functions.R")
at the start of each script to load them.
custom_functions.R:
# function to do stuff
foo <- function() {
message("Hello")
}
your normal script:
source("custom_functions.R")
foo()
#> Hello
You do not need to assign names in this case.
R also makes it very straightforward to create your personal package, which is another good option (see, e.g., https://r-pkgs.org/).
Related Topics
Twitter Sentiment Analysis W R Using German Language Set Sentiws
Installing R Packages Error in Readrds(File):Error Reading from Connection
Replace Every Single Character at the Start of String That Matches a Regex Pattern
Determining Minimum Values in a Vector in R
R Create Function to Add Water Year Column
How to Put a Complicated Equation into a R Formula
Aggregating Values on a Data Tree with R
How to Show a Loading Screen When the Output Is Being Calculated in a Background Process
Apply a Function to All Variables Starting with Specific Pattern in R
R: I Have to Do Softmatch in String
Rstudio Shiny Not Able to Use Ggvis
How to Write an Xts Object Using Write.CSV in R
Setting Working Directory: Julia Versus R
Plot Only One Side/Half of the Violin Plot
System Is Computationally Singular: Reciprocal Condition Number in R
Parsimonious Way to Add North Arrow and Scale Bar to Ggmap