R: use magrittr pipe operator in self written package

20,837

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.

Share:
20,837
alexander keth
Author by

alexander keth

Updated on September 08, 2020

Comments

  • alexander keth
    alexander keth over 3 years

    I would like to use the pipe-operator %>% introduced in the magrittr package in a package I wrote myself to chain dplyr data transformations. magrittr is listed as Import in the DESCRIPTION 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 %>% to magrittr::%>% in the function source code does not help either because the package cannot be built anymore.

  • tonytonov
    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
    Roman Luštrik over 9 years
    If you're using roxygen2, you could add #' importFrom magrittr "%>%" to have NAMESPACE populated automatically during roxygenize().
  • Roah
    Roah almost 9 years
    @RomanLuštrik, just missing @, should be #' @importFrom magrittr "%>%"
  • Ramnath
    Ramnath over 8 years
    Note 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 load magrittr. One way to solve this problem is to re-export the function. Here is an example of how to do it.
  • jzadra
    jzadra over 6 years
    When 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
    Mike Stanley over 6 years
    I 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
    JelenaČuklina about 6 years
    what is the purpose of @name %>% here?
  • Josh
    Josh almost 5 years
    Do 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 add use_pipe() at the beginning?
  • Andrew Brēza
    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
    jiggunjer almost 4 years
    This is also what the usethis package does, as mentioned here