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.
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.
Load a package apart from one function
There are three nice ways to do that, rising in difficulty:
1. conflicted
It checks for name conflicts and will prevent you from using masked or masking functions by throwing an error if you do. But you can declare a session-wide preference, e.g.:
conflict_prefer("filter", "dplyr")
#> [conflicted] Will prefer dplyr::filter over any other package
conflicted on Github
2. import
It allows you to explicitly import specific functions from packages (and give them a custom name, if you like)
import::from(ggplot2, g = ggplot, aes, geom_point)
g(iris, aes(Petal.Width, Petal.Length)) + geom_point()
import on Github
3. modules
It gives you a Python-esque way of importing both modules (written as R source files) and libraries and a more cohesive fashion. The nice (but advanced) thing is that modules, if they have subgroups, can be loaded partially, e.g. str = import('tools/strings')
. This does not work for packages, however, as they are written as monoliths. modules has some advantages coding guideline wise, but will force you to write:
dplyr = import_package('dplyr')
cars %>% dplyr$filter(speed > 15)
modules on Github
Import one function in R package (without importFrom)
Questions about the appropriate attribution would probably be best resolved by contacting the package author directly. As noted in the comments above, that package appears to use GPL-3, which should mean that you can include the function in your package but your package must then also be GPL-3 licensed. (As always, probably no one here is a lawyer so that's on you to check...)
The primary downside to copying just the function you need is that then you are responsible for maintaining it. This probably also means maintaining it in a way that keeps it in sync with the original version from plotKML. Depending on the package, surrounding code and how often it is updated that could be fairly simple or it could be horrible.
R with roxygen2: How to use a single function from another package?
If ldply()
is important for your package's functionality, then you do want it in your package namespace. That is the point of namespace imports. Functions that you need, should be in the package namespace because this is where R will look first for the definition of functions, before then traversing the base namespace and the attached packages. It means that no matter what other packages are loaded or unloaded, attached or unattached, your package will always have access to that function. In such cases, use:
@importFrom plyr ldply
And you can just refer to ldply()
without the plyr::
prefix just as if it were another function in your package.
If ldply()
is not so important - perhaps it is called only once in a not commonly used function - then, Writing R Extensions 1.5.1 gives the following advice:
If a package only needs a few objects from another package it can use a fully qualified variable reference in the code instead of a formal import. A fully qualified reference to the function
f
in packagefoo
is of the formfoo::f
. This is slightly less efficient than a formal import and also loses the advantage of recording all dependencies in theNAMESPACE
file (but they still need to be recorded in theDESCRIPTION
file). Evaluatingfoo::f
will cause packagefoo
to be loaded, but not attached, if it was not loaded already—this can be an advantage in delaying the loading of a rarely used package.
(I think this advice is actually a little outdated because it is implying more separation between DESCRIPTION
and NAMESPACE
than currently exists.) It implies you should use @import plyr
and refer to the function as plyr::ldply()
. But in reality, it's actually suggesting something like putting plyr
in the Suggests
field of DESCRIPTION
, which isn't exactly accommodated by roxygen2 markup nor exactly compliant with R CMD check
.
In sum, the official line is that Hadley's advice (which you are quoting) is only preferred for rarely used functions from rarely used packages (and/or packages that take a considerable amount of time to load). Otherwise, just do @importFrom
like WRE advises:
Using
importFrom
selectively rather thanimport
is good practice and recommended notably when importing from packages with more than a dozen exports.
How to properly use functions from other packages in a R package
The basic question you need to answer is: "do you want the function to be available to all users of the package without further effort?". If yes, then use imports + the appropriate namespace declarations, if no, then use suggests and print an informative error message if require("psych")
returns FALSE
.
I don't understand your import related complaint that: "but on a computer that does not has psych installed it gives an error when loading my package". This is also true if your package is in depends!
How to load only specific functions from a package
Sure. Just use an importFrom
directive in your NAMESPACE file (as described here in R-exts).
importFrom(gdata, trim)
OP EDIT: As of R 3.2.0 there's now a base function: trimws()
Related Topics
Count the Number of Integer Digits
How to Dynamically Change Plotly Axis Based on Crosstalk Conditions
How to Start Ggplot2 Geom_Bar from Different Origin
Ggplot2: Change Factor Order in Legend
Adding Slight Curve (Or Bend) in Ggplot Geom_Path to Make Path Easier to Read
Error in Chol.Default(Cxx):The Leading Minor of Order Is Not Positive Definite
Possible Issue About Random Number Generator
Extract Date Elements from Posixlt and Put into Data Frame in R
Extracting Orthogonal Polynomial Coefficients from R's Poly() Function
Intersecting Points and Polygons in R
Getting the Column Names of a Data Frame with Sapply
Boxplot, How to Match Outliers' Color to Fill Aesthetics
R Plots: How to Draw a Border, Shadow or Buffer Around Text Labels
Is There an R Library That Estimates a Multivariate Natural Cubic Spline (Or Similar) Function
Convert Data Frame Common Rows to Columns
Create Line Graph with Ggplot2, Using Time Periods as X-Variable