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

R语言中使用整洁评估时ggplot2 facet_wrap标签的问题

问题:动态设置ggplot分面标签(包含聚合计算结果)

需要编写可适配不同数据集的函数,根据传入的列参数进行分面,且分面标签需包含对应分组下percBackground列的总和。尝试使用rlang的{{}}语法但未成功,运行代码时报错。

测试数据与原代码

data.test <- data.frame(broad = c("A", "A", "A", "B", "B", "C", "C", "C", "C"),
                        detail = c("a", "b", "c", "d", "e", "f", "g", "h", "i"),
                        sr.Summer = c(12, 23, 32, 12, 12, 11, 14, 15, 18),
                        percBackground = c(1.5, 4.3, 3.4, 4.6, 3.4, 4.1, 3.9, 2.9, 1.8))

func.test <- function(data, facet.by){
  
  aggr <- data %>% aggregate(percBackground ~ facet.by, FUN = sum) %>%
    mutate(label = paste0(facet.by, " - ", round(percBackground, digits = 2), "%"))
  
  facet_label <- aggr$label
  names(facet_label) <- unique(facet_label)
  
  ggplot(data = data, aes(x = detail)) +
    geom_point(aes(y = sr.Summer)) +
    facet_wrap(~facet.by, labeller = labeller(facet.by = facet_label))
  
}

func.test(data = data.test, 
          facet.by = broad)

报错信息

> Error in eval(predvars, data, env) : object 'broad' not found

     13. eval(predvars, data, env)
     12. eval(predvars, data, env)
     11. model.frame.default(formula = by, data = x)
     10. stats::model.frame(formula = by, data = x)
     9. eval(m, parent.frame())
     8. eval(m, parent.frame())
     7. aggregate.formula(x = by, data = x, FUN = FUN, ...)
     6. aggregate.data.frame(., percBackground ~ facet.by, FUN = sum)
     5. aggregate(., percBackground ~ facet.by, FUN = sum)
     4. aggregate(., percBackground ~ facet.by, FUN = sum)
     3. mutate(., label = paste0(facet.by, " - ", round(percBackground,
        digits = 2), "%"))
     2. data %>% aggregate(percBackground ~ facet.by, FUN = sum) %>%
        mutate(label = paste0(facet.by, " - ", round(percBackground,
        digits = 2), "%"))
     1. func.test(data.test, broad)
解决方案

错误根源是未正确处理非标准求值(NSE),即函数参数中的列名未被正确解析。以下是修改后的代码及关键要点:

修改后的完整代码

library(tidyverse)

data.test <- data.frame(broad = c("A", "A", "A", "B", "B", "C", "C", "C", "C"),
                        detail = c("a", "b", "c", "d", "e", "f", "g", "h", "i"),
                        sr.Summer = c(12, 23, 32, 12, 12, 11, 14, 15, 18),
                        percBackground = c(1.5, 4.3, 3.4, 4.6, 3.4, 4.1, 3.9, 2.9, 1.8))

func.test <- function(data, facet.by){
  # 计算分组总和并生成自定义标签
  aggr <- data %>%
    group_by({{facet.by}}) %>%
    summarize(total_perc = sum(percBackground), .groups = "drop") %>%
    mutate(label = paste0({{facet.by}}, " - ", round(total_perc, 2), "%"))
  
  # 构建标签映射:原始分组值 -> 带总和的标签
  facet_label <- set_names(aggr$label, aggr %>% pull({{facet.by}}))
  
  # 绘图,用{{}}传递动态列参数
  ggplot(data, aes(x = detail)) +
    geom_point(aes(y = sr.Summer)) +
    facet_wrap(vars({{facet.by}}), labeller = labeller(facet.by = facet_label))
}

# 调用函数
func.test(data = data.test, facet.by = broad)

关键修改说明

  • {{}}语法的正确使用:在group_by()、pull()、vars()中用{{facet.by}}引用动态列参数,让R正确识别数据框中的目标列。
  • 替换聚合方式:用group_by()+summarize()替代aggregate,更适配非标准求值场景,代码可读性更高。
  • 正确构建标签映射:用set_names()创建键值对,键为分组的原始值(如"A"、"B"),值为自定义标签,确保labeller能精准匹配替换。
  • ggplot分面语法适配:用vars({{facet.by}})替代~facet.by,符合ggplot的非标准求值语法要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:17:50