在 R 包中使用 tidy eval

Kub*_*ba_ 4 r dplyr r-package tidyeval rlang

我有一个stacked_plot()使用整洁评估来制作堆叠图的函数。我想将它包含在我的包中,并从该包中调用另一个函数来调用它。这是最小的例子:

stacked_plot <- function(data, what, by = NULL, date_col = date){

  by <- rlang::enquo(by)
  what <- rlang::ensym(what)
  date_col <- rlang::ensym(date_col)
  data <- data %>%
    dplyr::group_by(!!date_col, !!by) %>%
    dplyr::summarise(!!what := sum(!!what, na.rm = TRUE)) %>%
    dplyr::ungroup() %>%
    tidyr::complete(!!date_col, !!by, fill = rlang::list2(!!what := 0))

  p <- data %>%
    ggplot2::ggplot(ggplot2::aes(!!date_col, !!what, fill = !!by)) +
    ggplot2::geom_area(position = 'stack')
  print(p)
}

#' @importFrom rlang .data
call_plot <- function() {
  to_plot <- data.frame(date = rep(seq(lubridate::ymd('2020-01-01'),
                                       lubridate::ymd('2020-03-30'),
                                       by = '1 day'), each = 3)) %>%
    dplyr::mutate(cat = rep(c('A', 'B', 'C'), 90), v1 = runif(270))

  p <- to_plot %>%
    stacked_plot(what = .data$v1, by = .data$cat)
  return(p)
}
Run Code Online (Sandbox Code Playgroud)

合并stacked_plot()到一个包中效果很好,我可以交互地调用它。但是,call_plot()afterload_all()导致错误。这是rlang::last_error()输出:

rlang::last_error()
<error/rlang_error>
Only strings can be converted to symbols
Backtrace:
  1. global::call_plot()
 10. mmmtools::stacked_plot(., what = .data$v1, by = .data$cat)
 11. rlang::ensym(what) R/stacked_plot.R:4:2
Run `rlang::last_trace()` to see the full context.
Run Code Online (Sandbox Code Playgroud)

我相信这是由于整洁评估的一些特殊性。但是,我真的找不到有关tidyeval在 R 包中使用的特性的任何来源。我唯一知道的是,我不能真正直接使用带引号的变量,.data$variable而是使用模式,而我在call_plot().

如何使用 adjuststacked_plot()使其可从其他包函数中使用?

akr*_*run 5

似乎 OP 想要采用不带引号的列名。如果是这种情况,请更改ensym为enquo

stacked_plot <- function(data, what, by = NULL, date_col = date){

  by <- rlang::enquo(by)
  what <- rlang::enquo(what)
  date_col <- rlang::enquo(date_col)
  data %>%
    dplyr::group_by(!! date_col, !!by) %>%
    dplyr::summarise(!!what := sum(!!what, na.rm = TRUE)) %>%
      dplyr::ungroup() %>%
      tidyr::complete(!!date_col, !!by, fill = rlang::list2(!!what := 0)) %>%  
    ggplot2::ggplot(ggplot2::aes(!!date_col, !!what, fill = !!by)) +
     ggplot2::geom_area(position = 'stack')



}

call_plot <- function() {
  to_plot <- data.frame(date = rep(seq(lubridate::ymd('2020-01-01'),
                                       lubridate::ymd('2020-03-30'),
                                       by = '1 day'), each = 3)) %>%
    dplyr::mutate(cat = rep(c('A', 'B', 'C'), 90), v1 = runif(270))

  p <- to_plot %>%
    stacked_plot(what =  v1, by =  cat)
  return(p)
}
Run Code Online (Sandbox Code Playgroud)

- 调用函数

call_plot()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


此外,enquo+!!可以完全替换为{{}}

stacked_plot <- function(data, what, by = NULL, date_col = date){



  data %>%
    dplyr::group_by({{date_col}}, {{by}}) %>%
    dplyr::summarise( {{what}} := sum({{what}}, na.rm = TRUE)) %>%
    dplyr::ungroup() %>%
    tidyr::complete({{date_col}}, {{by}}, fill = rlang::list2({{what}} := 0))  %>% 
    ggplot2::ggplot(ggplot2::aes({{date_col}}, {{what}}, fill = {{by}})) +
    ggplot2::geom_area(position = 'stack')



}
Run Code Online (Sandbox Code Playgroud)

它可以和上一个一样

call_plot()
Run Code Online (Sandbox Code Playgroud)