R package fails devtools::check, because "could not find function" even though the function is imported in NAMESPACE
Asked Answered
C

2

10

Trying to build my first R package using roxygen2 and devtools. I have added a function that uses %>% and mutate in the @examples section. When I run check() it fails, because it cannot find the function %>% or mutate.

Based on this, this, and this I have tried the following:

I have #' importFrom magrittr %>% and #' importFrom dplyr mutate in the function's .R file. I also have magrittr and dplyr under Imports: in the DESCRIPTION file. After running document(), my NAMESPACE file contains importFrom(dplyr,mutate) and importFrom(magrittr,"%>%").

minimal R/test.R file:

#' Conditional mutate
#'
#' \code{mutate_cond} mutates the \code{data.frame} only on the rows that
#' satisfy the condition.
#' 
#' @param .data \code{data.frame}
#' @param condition expression with the condition to be evaluated
#' @param ... arguments passed to \code{mutate}
#' @param envir environment inherited from \code{parent.frame()}
#'
#' @return \code{data.frame}
#' @importFrom dplyr mutate
#' @importFrom magrittr %>%
#'
#' @examples
#' data(iris)
#' iris %>%
#'    mutate(aux = 0) %>%
#'    mutate_cond(Petal.Length > 1.3,aux = 3)
#'
#' @export
mutate_cond <- function(.data, condition, ..., envir = parent.frame()) {
  condition <- eval(substitute(condition), .data, envir)
  .data[condition, ] <- .data[condition, ] %>% mutate(...)
  .data
}

minimal DESCRIPTION file:

Package: test
Version: 0.1
Date: 2019-06-07
Title: Functions
Description: Some functions I use.
Author: me
Maintainer: me <[email protected]>
Encoding: UTF-8
License: GPL-3
Imports: dplyr, magrittr

NAMESPACE generated with document():

# Generated by roxygen2: do not edit by hand

export(mutate_cond)
importFrom(dplyr,mutate)
importFrom(magrittr,"%>%")

I expect this example code to run successfully and pass check(). Instead I get this error message:

❯ checking examples ... ERROR
  Running examples in ‘test-Ex.R’ failed
  The error most likely occurred in:

  > base::assign(".ptime", proc.time(), pos = "CheckExEnv")
  > ### Name: mutate_cond
  > ### Title: Conditional mutate
  > ### Aliases: mutate_cond
  > 
  > ### ** Examples
  > 
  > data(iris)
  > iris %>%
  +    mutate(aux = 0) %>%
  +    mutate_cond(Petal.Length > 1.3,aux = 3)
  Error in iris %>% mutate(aux = 0) %>% mutate_cond(Petal.Length > 1.3,  : 
    could not find function "%>%"
  Execution halted

1 error ✖ | 0 warnings ✔ | 0 notes ✔

Also, if I add require(dplyr) and require(magrittr) to the @examples section the error goes away or if I remove the whole @examples section the error goes away.

Why won't this package pass check()?

Thank you!

Compound answered 8/6, 2019 at 18:21 Comment(11)
If %>% is imported that means you can use it in the code of your package, but not in the examples. So add require(magrittr) in the example.Pustulate
Or you can make the %>% function available to the users of your package without the need to load the magrittr package, by importing it and then exporting it. See here for example.Pustulate
I don't seem to have any trouble using functions from the stats package in examples without loading stats. Is that because it is a default package while dplyr and magrittr are not? Thanks.Compound
BTW (and to @StéphaneLaurent), using require(magrittr) without checking the return status is meaningless: execution will happily continue if the package is not available, which is almost certainly not what you want in that case. If you are going to load a library in code, either do if (require(magrittr))... or library(magrittr), never do require(...) by itself. (Good reads: https://mcmap.net/q/63717/-what-is-the-difference-between-require-and-library and yihui.name/en/2014/07/library-vs-require/.)Ellerd
Yes, stats is a base package. You never need to load it. @r2evans: Agreed.Pustulate
@StéphaneLaurent: That's not right. The only package that is guaranteed to be present is base. Others are loaded by default (e.g. typically stats, graphics, grDevices, utils, datasets, methods), but there are other base packages which are not loaded unless you ask for them, e.g. compiler, grid, parallel, etc.)Kirst
stats is nevertheless called a "base" package. It is in r-base. But that's not very important ^^Pustulate
Ah ok you mean not all base packages are loaded by default. You're right.Pustulate
Some "base" packages are always installed/available but not always loaded in non-interactive R sessions.Ellerd
@r2evans: That's not right, either. "Base" packages are part of R, and are always available to be loaded. They can never be updated without an update of R. That's what "base" means. The other possibilities for the priority of a package are "recommended", which means most R distributions include them, but they're not part of R and could be updated when R is not, and "contributed", which means you have to install them, they aren't distributed with R.Kirst
You mis-read my comment, I said "always installed/available". If you write a package that relies on (say) complete.cases, then a Rcmd check is likely going to complain about a function not defined in the global environment. As an example, stats is a "base" package (so installed with R) and is always available to be loaded in a session -- in interactive sessions it is loaded by default -- but is not automatically loaded all of the time. You are right that they are not to be updated separately, but I think that's ancillary to this discussion.Ellerd
F
4

Running usethis::use_pipe() in the console will do the trick as well.

Fennelflower answered 18/2, 2020 at 20:39 Comment(0)
G
0

Adding

exportPattern("^[[:alpha:]]+")

to my NAMESPACE file solved the problem on my side.

Gahl answered 1/2, 2020 at 3:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.