没有可见的全局函数定义符号“:=”。

24
我正在编写一个使用tidyeval的包。因为我使用了tidyeval,所以在描述文件中将rlang列为导入项之一。
其中一个函数包含几行代码使用了:=操作符。
就像这样:
data %>%
    dplyr::mutate(
      !!New_R := AP_R_X*!!X + AP_R_Y*!!Y + AP_R_Z*!!Z,
      !!New_U := AP_U_X*!!X + AP_U_Y*!!Y + AP_U_Z*!!Z,
      !!New_F := AP_F_X*!!X + AP_F_Y*!!Y + AP_F_Z*!!Z) 

代码按预期工作,但在运行devtools::check()时出现以下提示。
 no visible global function definition for ':='

如何摆脱这个注释?这不是rlang评估的一部分吗?
编辑: 我已经阅读了问题“没有可见的全局函数定义‘median’,尽管那里的答案解释了为什么会出现这样的问题。但它并没有解释为什么当我导入了rlang时,:=没有被定义。我已经编辑了问题以使其更清楚。

1
如果您正在使用 roxygen2,请添加一个 importFrom 语句。不确定这是来自 data.tablerlang 还是 dplyr 的 data.table 后端。 - NelsonGon
1
不确定这个答案是否有帮助?https://dev59.com/4V0Z5IYBdhLWcg3wvCSd#31132798 - Jaccar
1
可能是median函数没有可见的全局函数定义的重复问题。 - NelsonGon
1
我已经加入了@NelsonGon的重复关闭投票。为了更全面地说明您的上下文,它来自于rlang - duckmayr
2
你的更新为我澄清了问题。你的问题是在DESCRIPTION文件中导入了rlang,但仍需要NAMESPACE指令。 - duckmayr
显示剩余2条评论
3个回答

35

在你更新了你的答案之后,对我来说,这有点像是一个完全的重复或不是。唯一的区别在于你已经把rlang添加到了DESCRIPTION中的Imports,并且没有看到这与NAMESPACE指令的区别。

为了展示这种方法是不够的,我制作了一个示例包。首先,我设置了该包:

library(devtools)
create("anExample", rstudio = FALSE, open = FALSE)

接着,我将https://dplyr.tidyverse.org/articles/programming.html中的示例函数添加到文件R/my_mutate.R中:

#' A function
#'
#' @param df A dataframe
#' @param expr A variable in the dataframe
#'
#' @return The dataframe with new mean and sum columns
#' @export
my_mutate <- function(df, expr) {
    expr <- enquo(expr)
    mean_name <- paste0("mean_", quo_name(expr))
    sum_name <- paste0("sum_", quo_name(expr))

    mutate(df,
           !! mean_name := mean(!! expr),
           !! sum_name := sum(!! expr)
    )
}

注意没有roxygen2命名空间标签。 我确保在DESCRIPTION中将rlangdplyr添加到Imports并运行devtools :: document()。 然后当我运行devtools :: check()时,会得到以下结果:

my_mutate: no visible global function definition for ‘enquo’
  my_mutate: no visible global function definition for ‘quo_name’
  my_mutate: no visible global function definition for ‘mutate’
  my_mutate: no visible global function definition for ‘:=’
  Undefined global functions or variables:
    := enquo mutate quo_name

0 errors  | 1 warning  | 1 note 

然而,如果我将 R/my_mutate.R 更改为以下内容:

#' A function
#'
#' @param df A dataframe
#' @param expr A variable in the dataframe
#'
#' @return The dataframe with new mean and sum columns
#' @importFrom dplyr mutate
#' @importFrom rlang enquo
#' @importFrom rlang quo_name
#' @importFrom rlang :=
#' @export
my_mutate <- function(df, expr) {
    expr <- enquo(expr)
    mean_name <- paste0("mean_", quo_name(expr))
    sum_name <- paste0("sum_", quo_name(expr))

    mutate(df,
           !! mean_name := mean(!! expr),
           !! sum_name := sum(!! expr)
    )
}

在重新执行 document() 后,当我运行devtools::check()时,我没有看到那个提示。

简而言之,在 DESCRIPTION 中使用 Import 是不够的,您还需要 NAMESPACE 指令。


为了方便访问,请将所有的 @import@importFrom 指令放在 R/anExample.R 的头部。请参阅第10.6节“文档化包”-- https://r-pkgs.org/man.html - Gabi

5

2023年6月更新

你应该运行usethis::use_import_from("rlang", ":=")

usethis::use_import_from("rlang", ":=")将使用包级别文档中的@importFrom标签从rlang导入:=函数。更多信息,请查看这里的文档

这将使你的包级别文档看起来像这样:

@keywords internal
"_PACKAGE"

## usethis namespace: start
#' @importFrom rlang :=
## usethis namespace: end
NULL

关于这份文档的更多信息,请点击这里这里阅读R包书籍。

如果您想要使用更多来自rlang的tidy-eval函数,您应该使用usethis::use_import_from()进行导入。

usethis::use_tidy_eval已被标记为废弃自usethis 2.2.0版本,因为它导入并重新导出了过多的函数(请参见此问题发布说明)。

旧版更新(2023年3月)

我想在2023年的更新中添加一点内容 - 现在你可以运行usethis::use_tidy_eval()来处理这个问题。该函数将自动导入rlang::dyn-dots,或者rlang::`:=` ,以及rlang::enquorlang::enquosrlang::.datarlang::as_namerlang::as_label来处理使用tidyeval时可能出现的注意事项。这些将出现在一个名为utils-tidy-eval.R的新文件中。如果需要更多信息,请参阅此处的文档。
这个函数本质上与接受的答案做的是一样的,但它会创建一个新文件来保存这些@importFrom函数,并在您的包中为这些导入创建文档。
简而言之:只需运行usethis::use_tidy_eval()即可。

1
请参阅数据脱敏和整洁选择笔记使用dplyr包中。示例是针对.data,您可以将其更改为:=
总结一下,您必须在控制台上执行:
usethis::use_import_from("rlang", ":=")

这个命令会在一个以yourpackagename-package.R形式的文件中添加一行内容为#' @importFrom rlang :=的代码,Roxigen将理解这个文件并在你运行devtools::document()(或任何其他执行devtools::check()等操作)时在NAMESPACE文件中添加必要的条目。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接