Use dependencies in R packages through library() / Description file - r

I'm writing an R package that has several dependencies of other packages, some of them are available in CRAN and other ones are homemade.
According to the help, library("my_package") will load the namespace of the package once I have previously installed it, i.e, install.package("my_package").
Nevertheless, once I have installed the package I am able to use all the functions of the installed but not loaded package through my_package::my_function(), so if my package has dependencies, beside adding those into DESCRIPTION file:
Imports:
dplyr,
my_package2,
ggvis,
in the root of the package folder.
Do I have to load the dependencies of the new package through library() or the final user will see an error if he has not installed on his computer as the required packages are specified in the Imports section?

No, the user does not have to load the packages that are used by functions in my_package.
The fact that you have listed a package under Imports: in the DESCRIPTION file means that during the installation of my_package, R will check that this package is available on your system. This means then that functions in my_package can use functions from these packages using the :: notation, as you suggested.
Using the :: notation is the recommended way to refer to functions from other packages, but there are also other options:
In order to make all the functions from, say, dplyr accessable without :: in my_package, you could add import(dplyr) to the NAMESPACE file. This is convenient, if you use many functions from a package.
If you intend to use only, say, the function select from dplyr, you could add importFrom(select, dplyr) to the NAMESPACE file.
You could also add the package to the DESCRIPTION file under Depends:. This would mean that the package is loaded to the global environment when you use library(my_package). This is almost never a good solution.
The general idea of dependencies is R is that my_package will have "it's own version" of the packages it depends on loaded. Therefore, you can always be sure that you will, e.g., use the function select() from the dplyr package, as you intended to do. The exception is the use of Depends: which bypasses this system. In this case, my_package will look for functions in the global environment and if somebody should have defined some function called select() in the global environment, my_package will use this function and you will get unexpected results.
Example 1:
DESCRIPTION file:
Imports:
dpylr
some function from my_package:
my_fun <- function(...) {
dplyr::mutate(...) %>%
dplyr::select(1:3)
}
Example 2:
DESCRIPTION file:
Imports:
dpylr
NAMESPACE file:
import(dplyr)
some function from my_package:
my_fun <- function(...) {
mutate(...) %>%
select(1:3)
}
Example 3:
DESCRIPTION file:
Imports:
dpylr
NAMESPACE file:
importFrom(dplyr,select)
some function from my_package:
my_fun <- function(...) {
dpylr::mutate(...) %>%
select(1:3)
}
You find more detailed explanations of how to handle dependencies in R packages on the web. For instance the following are useful:
On the DESCRIPTION file
On the NAMESPACE file
Also, it is not necessary to write the NAMESPACE file by hand. You can let roxygen2 do that for you. Read the documentation for more information.

Related

Conflicted package in R package building

I am creating my first package, here I am making some var estimations, the functions are running, however, I use packages that have the same function names.
Before writing the package I made an R script with the function and tests if it works, but at the top of my script I used the following code:
invisible(lapply(c("tibble","readxl","dplyr","stringr", "tidyr", "vars", "conflicted","forecast", "lubridate"), library, character.only = T))
conflict_prefer("select","dplyr")
conflict_prefer("lag", "dplyr")
conflict_prefer("filter", "dplyr")
The conflicted package chose the functions select, lag, and filter comes from the dplyr package rather from the stats package.
So I have not figured out how to use the conflict_prefer function inside the package.
Should they be the first lines of my function?
There is a roxygen way to prefer same-name functions?
I ask this because I get this warning:
> devtools::load_all()
i Loading FAVAR.MEF
Warning messages:
1: replacing previous import ‘dplyr::filter’ by ‘stats::filter’ when loading ‘FAVAR.MEF’
2: replacing previous import ‘dplyr::lag’ by ‘stats::lag’ when loading ‘FAVAR.MEF’
3: replacing previous import ‘stats::filter’ by ‘dplyr::filter’ when loading ‘FAVAR.MEF’
4: In setup_ns_exports(path, export_all, export_imports) :
Objects listed as exports, but not present in namespace: favar_est
Thanks in advance!!
If you are writing your own package and using external dependencies, you should not load them through repeated calls to library.
The proper way to do it is to state your dependencies in the DECRIPTION file of your package, which will mean that your dependencies are put on the search path in the correct order when your package is loaded. In your case, this removes the need for conflict_prefer, as dplyr will be higher up on the search path than stats. It also makes your package portable, because anyone who installs your package will have any missing dependencies installed automatically according to the packages listed in your DESCRIPTION file. Furthermore, doing it this way allows you to specify a minimum version of the dependency, so that anyone who already has an older version of the dependency installed will not come up against an obscure error when they try to use your package.
The DESCRIPTION file resides in the root directory of your package. It is a simple text file.
You need only add:
Depends:
tibble,
readxl,
dplyr,
stringr,
tidyr,
vars,
conflicted,
forecast,
lubridate
within this file, and your dependencies will be loaded with your package.

In an R Package, How do You Force Load Packages That Are Imports

My DESCRIPTION file requires a handful of packages (I've shown two below for simplicity):
Imports:
tidyverse,
magrittr
In my NAMESPACE file, I then use export(functions) for functions I WRITE, and I used import(tidyverse), import(magrittr) so ALL functions in these packages get loaded automatically. However, this isn't working and I still have to call library(tidyverse) after I load my package.
Any ideas?

Extending a S4 class from another package: reconcilePropertiesAndPrototype error

I am trying to write a subclass for RJDBC::JDBCConnection as I need custom methods to connect the dbplyr package using the approach from dplyr#2941 (originally from here). However, I am not overwriting the *.JDBCConnection methods but want to write methods for a subclass of JDBCConnection.
Therefore, following the advise from this Stack Overflow question, I wrote my package which is essentially this:
### R/testclass.R ####################
#' Test class
#'
#' This extends JDBCConnection in package RJDBC
#'
#' #import RJDBC
#'
setClass("TestConnection", contains = "JDBCConnection")
### DESCRIPTION ######################
Package: test
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Author: Who wrote it
Maintainer: The package maintainer <yourself#somewhere.net>
Description: More about what it does (maybe more than one line)
Use four spaces when indenting paragraphs within the Description.
License: What license is it under?
Encoding: UTF-8
LazyData: true
The class I want to extend exists, as can be checked with help("JDBCConnection-class", package = "RJDBC").
Calling devtools::document() within this packages returns the following error:
Updating test documentation
Loading test
Error in reconcilePropertiesAndPrototype(name, slots, prototype, superClasses, :
no definition was found for superclass "JDBCConnection" in the specification of class "TestConnection"
I also tried replacing #import with #importClassesFrom as per this SO question, but the result was the same.
How can I get document() to run?
You also need to add
Imports: RJDBC
to your DESCRIPTION file. See, for example, this guide:
If your package is using functions in other packages, you also need to
add some lines to your DESCRIPTION file.
...
Imports is used for packages that are needed by your package but that
don’t need to be loaded with library(). Packages referred to in
#import or #importFrom statements in your Roxygen2 comments, or whose
functions are accessed via the :: operator, should be here.
After that, your package document()'d fine for me.
I succeeded to document the package when I do not rely on roxygen2 to write my DESCRIPTION file but add the packages myself. NAMESPACE is managed by roxygen2.
If I add the Line
Imports: methods, RJDBC
or
Depends: RJDBC
to the DESCRIPTION file manually, devtools::document() runs without error.
[duckmayr found it out in the same time]

R with roxygen2: How to use a single function from another package?

I'm creating an R package that will use a single function from plyr. According to this roxygen2 vignette:
If you are using just a few functions from another package, the
recommended option is to note the package name in the Imports: field
of the DESCRIPTION file and call the function(s) explicitly using ::,
e.g., pkg::fun().
That sounds good. I'm using plyr::ldply() - the full call with :: - so I list plyr in Imports: in my DESCRIPTION file. However, when I use devtools::check() I get this:
* checking dependencies in R code ... NOTE
All declared Imports should be used:
‘plyr’
All declared Imports should be used.
Why do I get this note?
I am able to avoid the note by adding #importFrom dplyr ldply in the file that is using plyr, but then I end but having ldply in my package namespace. Which I do not want, and should not need as I am using plyr::ldply() the single time I use the function.
Any pointers would be appreciated!
(This question might be relevant.)
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 package foo is of the form foo::f. This is slightly less efficient than a formal import and also loses the advantage of recording all dependencies in the NAMESPACE file (but they still need to be recorded in the DESCRIPTION file). Evaluating foo::f will cause package foo 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 than import is good practice and recommended notably when importing from packages with more than a dozen exports.

Order of DESCRIPTION Imports: and NAMESPACE import() in R 2.14.0 package checking

I'm trying to chase down what seems to be a conflict between function names as I check a package. I may eventually ask directly about the problem, but first, I am wondering about three things, none of which seem to be mentioned in R-exts:
The packages listed in DESCRIPTION: Imports and NAMESPACE imports() should be the same, right?
Within either list, does the order of importing matter? If so, is there any general advice about how to order them?
I use R --vanilla CMD check pkg_name to avoid having my .Rprofile interfere. When my .Rprofile is active and contains library(pkg_name) statements, does the order of those matter?
You asked three questions.
1. List packages in DESCRIPTION as well as NAMESPACE
Each package listed in DESCRIPTION Imports: must have a matching entry NAMESPACE import(...). The entry in DESCRIPTION may contain version information, but in NAMESPACE you only name the package.
Note for the unwary: Spell Imports with capital I and trailing s in DESCRIPTION
For example:
DESCRIPTION
Imports:
stringr (>= 0.5)
NAMESPACE
import(stringr)
2. Order matters
Packages that you load or import later masks packages that were loaded or imported earlier. This only matters if you import packages that have export a function with identical name.
For example, both lattice and ggplot2 export a layer function. Thus if you first import lattice and then ggplot2, it means that ggplot2::layer will mask lattice::layer.
In other words, using layer will refer to ggplot2::layer. If you want to refer to the lattice version you need to explicitly refer to lattice::layer in your function.
3. The order of loading packages also matter
For the same reason, the order of loading packages (either in a script or in .Rprofile) matters. Any new package that you load will mask functions with the same name in previously loaded packages.
When this happens, R does the sensible thing and tells you about it in a console message.
Here is an example of masking that occurs when loading the reshape package, which depends on plyr but also masks some functions in plyr:
library(reshape)
Loading required package: plyr
Attaching package: 'plyr'
The following object(s) are masked from 'package:braidppt':
.
Attaching package: 'reshape'
The following object(s) are masked from 'package:plyr':
rename, round_any

Resources