I'm making a package for data manipulation that uses some other libraries under the hood. Let's say that my data always has a class "custom"
and that I have a function custom_select()
to select some columns.
I would like my package to have few dependencies but also a similar syntax as functions from dplyr
. Because several dplyr
functions are generics, I can use the same function names for a different input type. In my situation, I could make a method select.custom()
so that the user can either pass a data.frame
or a custom
object to select()
and both would work.
Now from my understanding, this requires putting dplyr
in Imports
because I need to have access to its select()
generic. I'd like to avoid doing this because I want to limit the number of hard dependencies.
The scenario I have in mind is:
- the user already loads
dplyr
anyway, then they can useselect()
with the data of classcustom
and it should work - the user doesn't have
dplyr
installed/loaded, and I don't want to force them to have it, so they can use the functioncustom_select()
instead.
Ideally, I'd like to put dplyr
in Suggests
so that it's not strictly necessary but it adds something if the user has it.
Example
custom.R
:
#' @export
#' @importFrom dplyr select
custom_select <- function(data, select) {
print("Hello, world!")
}
#' @export
select.custom <- custom_select
NAMESPACE
:
# Generated by roxygen2: do not edit by hand
export(custom_select)
export(select.custom)
importFrom(dplyr,select)
R CMD check errors if I don't put dplyr
in Imports
and putting it in Suggests
also doesn't work (same error for both cases):
❯ checking package dependencies ... ERROR
Namespace dependency missing from DESCRIPTION Imports/Depends entries: 'dplyr'
In summary, is there a way to keep dplyr
out of hard dependencies while still providing methods for dplyr
's generics if it is available?
Edit: I tried @VonC's answer but couldn't make it work. In the example below, dplyr
is loaded before my custom package so select.custom()
should be available but isn't:
library(dplyr, warn.conflicts = FALSE)
library(custompackage)
foo <- letters
class(foo) <- "custom"
custom_select(foo)
#> [1] "Hello, world!"
select(foo)
#> Error in UseMethod("select"): no applicable method for 'select' applied to an object of class "custom"
Here are the important files:
custom.R
#' @export
custom_select <- function(data, select) {
print("Hello, world!")
}
if (requireNamespace("dplyr", quietly = TRUE)) {
select.custom <- function(data, select) {
custom_select(data, select)
}
utils::globalVariables("select.custom")
}
NAMESPACE
# Generated by roxygen2: do not edit by hand
export(custom_select)
DESCRIPTION
(no Imports
)
[...]
Suggests:
dplyr