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

如何在ggplot2的facet_wrap分面中添加各分面数据均值线?

在ggplot分面中添加各人员的均值水平线(管道内实现)

问题背景

现有包含各中心人员不同日期销售数据的DataFrame,示例数据生成代码:

library(tidyverse)

tibble(
  centre = rep(c('A', 'B'), 4),
  person = c('p1', 'p2', 'p3', 'p4', 'p5', 'p6', 'p7', 'p8')
) %>%
  full_join(
    tibble(date = seq(as.Date('2022-01-01'), as.Date('2022-01-5'), 1)),
    by = character()
  ) %>%
  mutate(
    num = round(runif(nrow(.), min = 50, max = 100),0)
  ) ->
  df

绘制人员销售额随日期变化的趋势图代码:

library(ggplot2)

df %>%
  group_by(centre, person) %>%
  mutate(mean_num = mean(num, na.rm = TRUE)) %>%
  ungroup() %>%
  ggplot(aes(x = date, y = num)) +
  geom_point() +
  geom_line() +
  facet_wrap(~person, scales = 'free') +
  xlab('Date') +
  ylab('Sales') +
  ggtitle('Sales vs Date') ->
  plt

尝试给每个分面添加对应人员的平均销售额水平线,以下三种方法均失败:

# Method 1
plt +
geom_hline(yintercept = mean(num), linetype = 'dotted', colour = 'red')

# Method 2
plt +
geom_hline(yintercept = mean_num, linetype = 'dotted', colour = 'red')

# Method 3
plt +
stat_summary(fun = mean, geom = 'line', colour = 'red')

希望在单一数据管道内完成该需求,需明确错误原因及修正方案。

错误原因分析

  • 方法1:mean(num)计算的是整个数据集的全局均值,并非每个分面(人员)的单独均值,导致所有分面显示同一条水平线,不符合需求。
  • 方法2:未通过aes()映射yintercept到mean_num,ggplot无法将分面与对应人员的均值关联,无法正确匹配每个分面的数值。
  • 方法3:使用geom='line'错误,均值是单一数值,应绘制水平线而非折线,且未指定针对分面分组计算。

管道内实现的正确方案

方案一:利用预计算的均值,通过geom_hline映射匹配

提前计算每个人员的均值后,在geom_hline中通过data参数筛选出每个人员唯一的均值,确保分面与均值正确对应:

df %>%
  group_by(centre, person) %>%
  mutate(mean_num = mean(num, na.rm = TRUE)) %>%
  ungroup() %>%
  ggplot(aes(x = date, y = num)) +
  geom_point() +
  geom_line() +
  # 筛选每个person的唯一均值,映射到yintercept
  geom_hline(aes(yintercept = mean_num), 
             data = ~distinct(.x, person, mean_num),
             linetype = 'dotted', colour = 'red') +
  facet_wrap(~person, scales = 'free') +
  xlab('Date') +
  ylab('Sales') +
  ggtitle('Sales vs Date')

方案二:用stat_summary直接在分面内计算并绘制均值线

无需提前计算均值,通过stat_summary自动在每个分面内计算销售额均值,并绘制水平线:

df %>%
  ggplot(aes(x = date, y = num)) +
  geom_point() +
  geom_line() +
  # 在每个分面内计算y的均值,绘制水平线
  stat_summary(fun = mean, geom = 'hline', 
               aes(yintercept = after_stat(y)),
               linetype = 'dotted', colour = 'red') +
  facet_wrap(~person, scales = 'free') +
  xlab('Date') +
  ylab('Sales') +
  ggtitle('Sales vs Date')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:30:50