R: use magrittr pipe operator in self written package
Solution 1
It should have worked correctly if you had magrittr
listed in Depends
. However, this is not advised. Instead, you leave magrittr
in Imports
and add the following line to NAMESPACE
:
importFrom(magrittr,"%>%")
I suggest reading Writing R extensions. Your question is covered in paragraphs 1.1.3 and 1.5.1.
Solution 2
There's now an easier way to support the pipe in your packages. The wonderful package usethis
has the function use_pipe()
. You run that function once and it handles everything. This is how the use_pipe()
function is described in the usethis
documentation:
Does setup necessary to use magrittr's pipe internally in your package and to re-export it for users of your package:
Adds magrittr to "Imports" in DESCRIPTION
Creates R/utils-pipe.R with the necessary roxygen template
Solution 3
One additional solution - use the roxygen
package. It's implemented as part of the devtools
package. Once devtools
is installed, calling devtools::document()
will update your NAMESPACE
for you. It also auto-builds .Rd files with documentation, which is handy.
All you do is add a special comment in the format #' @import packagename
to a file to import all functions from that package, or #' @importFrom packagename functionname
to import a function. You can have as many of these comments as you want in your files, so you can have a set of them at the top of each file, or with each of your functions that needs an external function.
Then you run devtools::document()
and it parses your code looking for those comments, and then it creates an appropriate NAMESPACE
file for you. Easy.
Solution 4
Assuming that you're using RStudio, Hadley's devtools
package, and listed magrittr
in the Imports section of the DESCRIPTION
file, here are steps I took to make %>%
work in my package function(s).
First, write function foo.R
:
#' Convert \code{data.frame} to \code{list}.
#'
#' @importFrom magrittr %>%
#' @name %>%
#' @rdname pipe
#' @export
#' @param x A \code{data.frame} object.
#' @examples
#' my_result <- foo(iris)
#'
foo <- function(x) {
x %>%
as.list()
}
Second, run devtools::document()
.
Third, run devtools::load_all()
.
A file like this will be created in your R/
directory and your function should work as expected.
alexander keth
Updated on September 08, 2020Comments
-
alexander keth over 3 years
I would like to use the pipe-operator
%>%
introduced in themagrittr
package in a package I wrote myself to chaindplyr
data transformations.magrittr
is listed asImport
in theDESCRIPTION
file. After loading my own package and testing the function which uses the pipe-operator I get the following error message:Error in functionname(parameter, : could not find function "%>%"
Changing
%>%
tomagrittr::%>%
in the function source code does not help either because the package cannot be built anymore. -
tonytonov over 9 years@alexanderketh In that case you should hit the green tick mark next to the answer to mark it as accepted. Welcome to SO!
-
Roman Luštrik over 9 yearsIf you're using
roxygen2
, you could add#' importFrom magrittr "%>%"
to have NAMESPACE populated automatically duringroxygenize()
. -
Roah almost 9 years@RomanLuštrik, just missing @, should be
#' @importFrom magrittr "%>%"
-
Ramnath over 8 yearsNote that this will only allow you to use
%>%
internally in your package. If your API requires users to chain functions using%>%
, they will still have to explicitly loadmagrittr
. One way to solve this problem is to re-export the function. Here is an example of how to do it. -
jzadra over 6 yearsWhen I do this, it messes up the following oxygen comments that pertain to the help file for the first function in the R script. How do I separate global oxygen comments from the help file ones?
-
Mike Stanley over 6 yearsI usually put the import comments with each function individually. That way if other functions in the file change, your imports stay accurate. So then there are no global definitions.
-
JelenaČuklina about 6 yearswhat is the purpose of
@name %>%
here? -
Josh almost 5 yearsDo you add the line
use_pipe()
to the code that you use to build the package? For example, I run:usethis::use_description(usethis_description); usethis::use_build_ignore(directories); usethis::use_build_ignore(paste0(pkg_name, ".Rproj")); if (file.exists(file.path(pkg_path, "NAMESPACE"))) { file.remove(file.path(pkg_path, "NAMESPACE")) }; devtools::document(pkg_path); devtools::check(pkg_path); devtools::load_all(pkg_path); devtools::install(pkg_path)
. Would I just adduse_pipe()
at the beginning? -
Andrew Brēza almost 5 years@Josh you use the
usethis
functions once when you're developing the package. Those functions then add the necessary parts to the build instructions and everything else. -
jiggunjer almost 4 yearsThis is also what the usethis package does, as mentioned here