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

R语言ggplot:为stat_summary中位数线添加IQR丝带/误差棒问题

问题描述

现有代码可通过stat_summary绘制三组数据的中位数折线,但无法添加IQR(四分位距)对应的丝带或误差棒。涉及变量:

  • 分组变量:otherside_surgery_yesno(含三组:NA、"0"、非NA)
  • X轴:Jahre(年份)
  • Y轴:po_constant_impaired_score_a

尝试自定义上下四分位计算函数,但geom_errorbar无法正常工作,寻求可行方案。

现有可运行代码:

both_sides %>% 
  ggplot() +
  # RTSA
  stat_summary(data = both_sides %>% filter(is.na(otherside_surgery_yesno)),
                 aes(x = Jahre, 
                   y = po_constant_impaired_score_a),
              fun = median, 
              geom = "line",
              color = "red") +
  # Healthy without surgery
  stat_summary(data = both_sides %>% filter(otherside_surgery_yesno == "0"),
                 aes(x = Jahre, 
                   y = po_constant_impaired_score_a),
              fun = median, 
              geom = "line",
              color = "darkgreen") +
  stat_summary(data = both_sides %>% filter(!is.na(otherside_surgery_yesno)),
                 aes(x = Jahre, 
                   y = po_constant_impaired_score_a),
              fun = median, 
              geom = "line",
              color = "blue") +
  theme_classic() +
  ylab("Constant Score absolute") +
  xlab("Time (years)")

尝试的失效代码:

calculate_lower <- function(data) {
  return(quantile(data, 0.25))
}

calculate_upper <- function(data) {
  return(quantile(data, 0.75))
}

geom_errorbar(
  aes(ymin = calculate_lower(data), ymax = calculate_upper(data)),
  width = 0.2
)
解决方案

方法1:使用stat_summary的fun.data参数(推荐)

无需重复调用stat_summary,先统一分组标签,再用fun.data一次性计算中位数、上下四分位,同时绘制折线和误差棒/丝带。

# 先整理分组标签,方便图例展示
both_sides <- both_sides %>%
  mutate(group = case_when(
    is.na(otherside_surgery_yesno) ~ "RTSA",
    otherside_surgery_yesno == "0" ~ "Healthy without surgery",
    !is.na(otherside_surgery_yesno) ~ "Other surgery"
  ))

# 绘制中位数折线 + IQR误差棒
both_sides %>%
  ggplot(aes(x = Jahre, y = po_constant_impaired_score_a, color = group)) +
  # IQR误差棒
  stat_summary(fun.data = function(x) {
    tibble(
      y = median(x),
      ymin = quantile(x, 0.25),
      ymax = quantile(x, 0.75)
    )
  }, geom = "errorbar", width = 0.2, position = position_dodge(0.2)) +
  # 中位数折线
  stat_summary(fun = median, geom = "line") +
  # 自定义分组颜色
  scale_color_manual(values = c(
    "RTSA" = "red", 
    "Healthy without surgery" = "darkgreen",
    "Other surgery" = "blue"
  )) +
  theme_classic() +
  labs(y = "Constant Score absolute", x = "Time (years)", color = "Group")

如果想用丝带替代误差棒,只需修改stat_summary的geom参数并调整透明度:

both_sides %>%
  ggplot(aes(x = Jahre, y = po_constant_impaired_score_a, color = group, fill = group)) +
  # IQR丝带
  stat_summary(fun.data = function(x) {
    tibble(
      y = median(x),
      ymin = quantile(x, 0.25),
      ymax = quantile(x, 0.75)
    )
  }, geom = "ribbon", alpha = 0.2, color = NA) +
  # 中位数折线
  stat_summary(fun = median, geom = "line") +
  scale_color_manual(values = c(
    "RTSA" = "red", 
    "Healthy without surgery" = "darkgreen",
    "Other surgery" = "blue"
  )) +
  scale_fill_manual(values = c(
    "RTSA" = "red", 
    "Healthy without surgery" = "darkgreen",
    "Other surgery" = "blue"
  )) +
  theme_classic() +
  labs(y = "Constant Score absolute", x = "Time (years)", color = "Group", fill = "Group")

方法2:先预处理统计数据再绘图

如果习惯先计算好每组每年的统计值,再用基础图层绘图:

# 预处理:计算每组每年的中位数、上下四分位
summary_data <- both_sides %>%
  mutate(group = case_when(
    is.na(otherside_surgery_yesno) ~ "RTSA",
    otherside_surgery_yesno == "0" ~ "Healthy without surgery",
    !is.na(otherside_surgery_yesno) ~ "Other surgery"
  )) %>%
  group_by(group, Jahre) %>%
  summarise(
    median_score = median(po_constant_impaired_score_a, na.rm = TRUE),
    q25 = quantile(po_constant_impaired_score_a, 0.25, na.rm = TRUE),
    q75 = quantile(po_constant_impaired_score_a, 0.75, na.rm = TRUE),
    .groups = "drop"
  )

# 绘图
summary_data %>%
  ggplot(aes(x = Jahre, y = median_score, color = group)) +
  geom_errorbar(aes(ymin = q25, ymax = q75), width = 0.2, position = position_dodge(0.2)) +
  geom_line() +
  scale_color_manual(values = c(
    "RTSA" = "red", 
    "Healthy without surgery" = "darkgreen",
    "Other surgery" = "blue"
  )) +
  theme_classic() +
  labs(y = "Constant Score absolute", x = "Time (years)", color = "Group")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:00:31