You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R包tidy eval应用:stacked_plot函数内部调用报错问题

解决包内函数调用tidy eval堆叠图函数的报错问题

问题根源

你遇到的错误是因为rlang::ensym()只能接受**符号(比如v1)或字符串(比如"v1")**作为输入,但你在call_plot里传入的.data$v1是一个.data代词的调用表达式,并非符号/字符串,因此ensym()无法完成转换,抛出了"Only strings can be converted to symbols"的错误。

解决方案:替换ensym为enquo并使用curly-curly语法

我们需要修改stacked_plot函数,改用rlang::enquo()来捕获任意表达式(包括.data$xxx这种代词调用),同时用更简洁的{{ }}(curly-curly操作符)完成插值。以下是修改后的完整函数:

stacked_plot <- function(data, what, by = NULL, date_col = date){
  # 捕获所有参数的表达式(包括.data$xxx这类)
  by <- rlang::enquo(by)
  what <- rlang::enquo(what)
  date_col <- rlang::enquo(date_col)
  
  data <- data %>% 
    dplyr::group_by(!!date_col, !!by) %>% 
    # 提取what的变量名用于赋值,同时计算求和
    dplyr::summarise(
      !!rlang::as_name(what) := sum({{what}}, na.rm = TRUE),
      .groups = "drop"  # 替代ungroup(),更简洁
    ) %>% 
    tidyr::complete(
      !!date_col, !!by,
      fill = rlang::list2(!!rlang::as_name(what) := 0)
    )
  
  p <- data %>% 
    ggplot2::ggplot(ggplot2::aes({{date_col}}, {{what}}, fill = {{by}})) +
    ggplot2::geom_area(position = 'stack')
  
  print(p)
  invisible(p)  # 返回绘图对象但避免重复打印
}

如果你想进一步简化代码,可以省略手动enquo的步骤,直接用{{ }}替代!!enquo()的组合({{x}}等价于!!rlang::enquo(x)):

stacked_plot <- function(data, what, by = NULL, date_col = date){
  # 提前捕获what的表达式,用于提取变量名
  what_quo <- rlang::enquo(what)
  what_name <- rlang::as_name(what_quo)
  
  data <- data %>% 
    dplyr::group_by({{date_col}}, {{by}}) %>% 
    dplyr::summarise(
      !!what_name := sum({{what}}, na.rm = TRUE),
      .groups = "drop"
    ) %>% 
    tidyr::complete(
      {{date_col}}, {{by}},
      fill = rlang::list2(!!what_name := 0)
    )
  
  p <- data %>% 
    ggplot2::ggplot(ggplot2::aes({{date_col}}, {{what}}, fill = {{by}})) +
    ggplot2::geom_area(position = 'stack')
  
  print(p)
  invisible(p)
}

关键修改说明

  1. 用enquo替代ensym:enquo()可以捕获任意R表达式,包括.data$xxx这种代词调用,完美适配包内函数调用时的.data规范(避免R CMD check的"无可见绑定"警告)。
  2. 提取变量名用于赋值:在summarise和complete的fill参数中,我们需要用rlang::as_name()从捕获的表达式中提取原始变量名,保证结果数据框的列名和输入一致。
  3. curly-curly语法简化插值:{{ }}是!!enquo(x)的语法糖,让代码更简洁易读,同时保持tidy eval的灵活性。
  4. 返回绘图对象:加入invisible(p)确保函数返回ggplot对象的同时,不会在非交互式调用时重复打印图形。

测试修改后的代码

现在执行call_plot()就能正常生成堆叠图了,不管是交互式调用还是包内load_all()后的调用都不会报错。

内容的提问来源于stack exchange,提问作者Kuba_

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 06:47:40