Loading depending packages using .onLoad - r

My package requires ggplot2 package, but I am having trouble to fix the following NOTES that I get when I run R CMD check.
no visible global function definition for qplot
'library' or 'require' call not declared from: ggplot2
I also have a .onLoad function,
.onLoad <- function(libname, pkgname){
.libPaths("~/RLibrary")
require(ggplot2)
}
Any suggestions on how to solve the errors? Where should I place the onLoad function?
Thank you
San

I don't think you should do it like that. It is best to either make your package depend on ggplot2 or import the namespace of ggplot2. Do the in the DESCRIPTION file by adding Depends: ggplot2 and the second by adding Imports: ggplot2 in DESCRIPTION and import(ggplot2) in NAMESPACE (or be more exact with importfrom(ggplot2,"somefunction").
Alternatively you could set Suggests: ggplot2 in DESCRIPTION and put a require("ggplot2") in any functions that uses it, but I don't like this alot.
See also:
http://cran.r-project.org/doc/manuals/R-exts.html#The-DESCRIPTION-file
EDIT: To be a bit more clear. With Depends the package is loaded every time your package is loaded and its functions are all available for the user.
With Imports you can use the functions of the package, but the package is not loaded when your package is not loaded (functions are not available to the user).
With Suggests the package is not loaded when you load your package and you can't use its functions. You need to declare a require somewhere to use them. Basically this can be used to make clear that you use this package somewhere (in an example or so).
It all depends on how you want your users to be able to use the depended package and how important it is for your package. For example, if your package is a frontend to ggplot2 Depends is best, if it does some analysis and has an plot function Imports is best.

Related

How to declare a dependency on an R package from which you only use S3/S4 methods, but no exports?

Currently I have in my package DESCRIPTION, a dependency on dbplyr:
Imports:
dbplyr,
dplyr
dbplyr is useful almost solely because of the S3 methods it defines: https://github.com/tidyverse/dbplyr/blob/main/NAMESPACE. The actual functions you call to use dbplyr are almost entirely from dplyr.
By putting dbplyr in my Imports, it should automatically get loaded, but not attached, which should be enough to register its S3 methods: https://r-pkgs.org/dependencies-mindset-background.html#sec-dependencies-attach-vs-load.
This seems to work fine, but whenever I R CMD check, it tells me:
N checking dependencies in R code (10.8s)
Namespace in Imports field not imported from: ‘dbplyr’
All declared Imports should be used.
Firstly, why does R CMD check even check this, considering that it often makes sense to load packages without importing them. Secondly, how am I supposed to satisfy R CMD check without loading things into my namespace that I don't want or need?
I am pretty sure two of your assumptions are false.
First, putting Imports: dbplyr into your DESCRIPTION file won't load it, so its methods won't be loaded from that alone. Basically the Imports field in the DESCRIPTION file just guarantees that dbplyr is available to be loaded when requested. If you import something via the NAMESPACE file, that will cause it to be loaded. If you evaluate dbplyr::something that will cause it to be loaded. Executing loadNamespace("dbplyr") is another way, and there are a few others. You may also load some other package that loads it.
Second, I think you have misinterpreted the error message. It isn't saying that you loaded it without importing it (though it would complain about that too), it is saying that it can't detect any use of it in your package, so maybe it shouldn't be a requirement for installing your package.
Unfortunately, the code to detect uses is fallible, so it sometimes misses uses. Examples I've heard about are:
if the package is only used in the default value for a function argument. This has been fixed in R-devel.
if the package is only used during the build to construct some object, e.g. code like someclass <- R6::R6Class( ... ) needs R6, but the check code won't see it because it looks at someclass, not at the source code that created it.
if the use of the package is hidden by specifying the name of the package in a character variable.
if the need for the package is indirect, e.g. you need to use ggplot2::geom_hex. That needs the hexbin package, but ggplot2 only declares it as "Suggested".
These examples come from this discussion: https://github.com/hadley/r-pkgs/issues/828#issuecomment-1421353457 .
The recommended workaround there is to create an object that refers to the imported package explicitly, e.g. putting the line
dummy_r6 <- function() R6::R6Class
into your package is enough to suppress the note without actually loading R6. (It will be loaded if you ever call this function.)
However, your requirement is stronger: you do need to make sure dbplyr is loaded if you want its methods to be used. I'd put something in your .onLoad() function that triggers the load. For example,
.onLoad <- function(lib, pkg) {
# Make sure the dbplyr methods are loaded
loadNamespace("dbplyr")
}
EDITED TO ADD: As pointed out in the comments, there's a bug in the check code that means it won't detect this as being a use of dbplyr. You really need to do both things, e.g.
.onLoad <- function(lib, pkg) {
# Make sure the dbplyr methods are loaded
loadNamespace("dbplyr")
# Work around bug in code checking in R 4.2.2 for use of packages
dummy <- function() dbplyr::across_apply_fns
}
The function used in the dummy construction is arbitrary; it probably doesn't even need to exist, but I chose one that does.

Imports - functions with the same name but from different package

I'm working on update of my package. However I'm struggling with dependencies/imports. I use two conflicted packages - ggplot2 and psych and their functions alpha and of course alpha object of ggplot2 differs from alpha function of psych package.
When building package I get an warning:
Warning: replacing previous import 'ggplot2::alpha' by 'psych::alpha' when loading 'ShinyItemAnalysis'
Hence I wont be able to publish my package on CRAN (untill I solved this warning). Is there any easy way how to avoid this import conflict?
Note that when using roxygen2 package to build NAMESPACE from fellow .R scripts, it is very helpful to delete the NAMESPACE file and run roxygen2 again. Solves many problems.

I'm writing a package. How can make it such that when library(my_package) is called, other packages are loaded as well?

Title should be pretty clear I hope. I'm writing a package called forecasting, with imports for dplyr among other packages. With the imports written in to the DESCRIPTION file, I am able to force these other packages to be installed along with forecasting - is there an equivalent way to do this for the loading of the package? In other words, is there a way that when I load my package with library(forecasting), it automatically also loads dplyr and the other packages?
Thanks
Yes.
Re-read "Writing R Extensions". The Depends: forces both the initial installation as well as the loading of the depended-upon packages.
But these days you want Imports: along with importFrom() in the NAMESPACE file which is more fine-grained.
But first things first: get it working with Depends.
Edit:
Opps you're correct, the documentation I referenced is not a primary source. Perhaps this is better:
From the R documentation:
The ‘Depends’ field gives a comma-separated list of package names which this package depends on. Those packages will be attached before the current package when library or require is called.
and
The ‘Imports’ field lists packages whose namespaces are imported from (as specified in the NAMESPACE file) but which do not need to be attached. Namespaces accessed by the ‘::’ and ‘:::’ operators must be listed here, or in ‘Suggests’ or ‘Enhances’
Original:
From the R packages documentation:
Adding a package dependency here [the DESCRIPTION file] ensures that it’ll be installed. However, it does not mean that it will be attached along with your package (i.e., library(x)). The best practice is to explicitly refer to external functions using the syntax package::function(). This makes it very easy to identify which functions live outside of your package. This is especially useful when you read your code in the future.

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

How to properly use functions from other packages in a R package

I am a bit confused about this. I have an R package that has a small function (not a mayor part of the package) in which the principal function of the psych package is called. How do I correctly specify this in DESCRIPTION and NAMESPACE?
Setting Depends: psych in DESCRIPTION makes sure the psych package is loaded every time my package is loaded. This works, but it seems redundant for such a small part of my package.
Setting Suggests: psych and entering a require("psych") in the function is what I do now, however this does not work if psych is not installed, and seems to be the wrong way of doing this (writing R extensions says that suggest is meant mainly for examples).
I think I need to import the function. I tried setting Imports: psych in DESCRIPTION and importFrom(psych,"principal") in NAMESPACE. This works, but on a computer that does not has psych installed it gives an error when loading my 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!

Resources