R:在自写包中使用 magrittr 管道运算符

Posted

技术标签:

【中文标题】R:在自写包中使用 magrittr 管道运算符【英文标题】:R: use magrittr pipe operator in self written package 【发布时间】:2015-03-12 21:31:02 【问题描述】:

我想在我自己编写的包中使用magrittr 包中引入的管道运算符%>% 来链接dplyr 数据转换。 magrittrDESCRIPTION 文件中列为Import。加载我自己的包并测试使用管道运算符的函数后,我收到以下错误消息:

函数名错误(参数,:找不到函数“%>%”

在函数源代码中将%>% 更改为magrittr::%>% 也无济于事,因为无法再构建包。

【问题讨论】:

我建议不要在包内的函数内使用管道运算符。它使调试变得更加困难(调用堆栈在管道中变得非常深)。对于包我只是覆盖一个临时变量,这使得测试更容易(想想:R 告诉你错误发生在哪一行)。管道非常适合交互式使用,但对于编程来说可能是一种负担。 【参考方案1】:

如果您在Depends 中列出了magrittr,它应该可以正常工作。但是,这是not advised。相反,您将magrittr 留在Imports 中,并将以下行添加到NAMESPACE

importFrom(magrittr,"%>%")

我建议阅读Writing R extensions。第 1.1.3 和 1.5.1 段涵盖了您的问题。

【讨论】:

@alexanderketh 在这种情况下,您应该点击答案旁边的绿色勾号将其标记为已接受。欢迎来到 SO! 如果您使用的是roxygen2,您可以添加#' importFrom magrittr "%>%" 以在roxygenize() 期间自动填充NAMESPACE。 @RomanLuštrik,只是少了@,应该是#' @importFrom magrittr "%>%" 请注意,这只允许您在包内部使用%>%。如果您的 API 要求用户使用 %>% 链接函数,他们仍然必须显式加载 magrittr。解决此问题的一种方法是重新导出函数。这是an example 的操作方法。 这也是usethis包的作用,如here所提到的【参考方案2】:

现在有一种更简单的方法来支持您的包中的管道。精彩的包usethis有功能use_pipe()。您运行该函数一次,它会处理所有事情。 use_pipe() 函数在 usethis 文档中是这样描述的:

在你的包内部使用 magrittr 的管道是否需要设置 并为您的包的用户重新导出它:

将 magrittr 添加到说明中的“导入”

使用必要的 roxygen 模板创建 R/utils-pipe.R

【讨论】:

您是否将use_pipe() 行添加到您用于构建包的代码中?例如,我运行: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)。我可以在开头添加use_pipe() 吗? @Josh 您在开发包时使用了一次usethis 函数。然后,这些函数将必要的部分添加到构建指令和其他所有内容中。【参考方案3】:

另一种解决方案 - 使用 roxygen 包。它作为devtools 包的一部分实现。安装devtools 后,调用devtools::document() 将为您更新您的NAMESPACE。它还自动构建带有文档的 .Rd 文件,这很方便。

您只需将#' @import packagename 格式的特殊注释添加到文件中以从该包中导入所有函数,或#' @importFrom packagename functionname 以导入函数。您可以在文件中包含任意数量的这些 cmets,因此您可以在每个文件的顶部放置一组它们,或者与需要外部函数的每个函数一起使用。

然后您运行 devtools::document() 并解析您的代码以查找这些 cmets,然后为您创建一个适当的 NAMESPACE 文件。很简单。

【讨论】:

当我这样做时,它会弄乱以下与 R 脚本中第一个函数的帮助文件有关的氧气 cmets。如何将全局氧气 cmets 与帮助文件分开? 我通常将 import cmets 与每个函数单独放在一起。这样,如果文件中的其他函数发生更改,您的导入将保持准确。所以没有全局定义。【参考方案4】:

假设您使用 RStudio,Hadley 的 devtools 包,并在 DESCRIPTION 文件的 Imports 部分中列出了 magrittr,以下是我为使 %>% 在我的包函数中工作所采取的步骤(s )。

首先,编写函数foo.R

#' Convert \codedata.frame to \codelist.
#' 
#' @importFrom magrittr %>%
#' @name %>%
#' @rdname pipe
#' @export
#' @param x A \codedata.frame object.
#' @examples
#' my_result <- foo(iris)
#'
foo <- function(x) 
    x %>%
        as.list()

其次,运行devtools::document()

第三,运行devtools::load_all()

this 之类的文件将在您的 R/ 目录中创建,您的函数应该可以按预期工作。

【讨论】:

这里@name %&gt;%的目的是什么?

以上是关于R:在自写包中使用 magrittr 管道运算符的主要内容,如果未能解决你的问题,请参考以下文章

python 导入自写包时ModuleNotFoundError 解决

%.% (dplyr) 和 %>% (magrittr) 之间的差异

如何使用具有多参数功能的 magrittr 管道?

suppressWarnings() 不适用于管道运算符

如何将管道链(magrittr)的结果提供给对象

获取在“magrittr”管道调用的函数中计算为点的表达式