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

在R的ggplot2分组柱状图中添加双侧柱子垂直时间标签的方法

问题描述

现有如下样本数据集,基于两个时间点的调研结果,按group1和group2分组:

df <- structure(list(label2plot = c("yes", "no", "yes", "no",
"yes", "no", "yes", "no"), gruppe = c("group1", "group1",
"group2","group2", "group1", "group1", "group2", "group2"), 
cohort = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), levels = c("20172018", "20192020"), class = "factor"), var_abs = c(4979L,
 3214L, 129L, 130L, 5476L, 3556L, 89L, 74L), var_rel = c(0.789565,
 0.8035, 0.871622, 0.8125, 0.793163, 0.805254, 0.839623,
 0.860465)), class = "data.frame", row.names = c(NA, -8L))

使用以下代码绘制分组柱状图,每个组单独展示:

var_label <- "blabla"
title <- "blublub"
subtitle <- "blablub"
val_label <- c("yes", "no")

packages2check <- c("ggplot2", "stringr")

for (package in packages2check) {
  if (!requireNamespace(package, quietly = TRUE)) {
    install.packages(package)
    library(package, character.only = TRUE)
  } else {
    library(package, character.only = TRUE)
  }
}

ggplot() +
  geom_bar (
    data = df,
    aes(
      x = factor(label2plot, levels = val_label),
      y = var_rel,
      group = cohort,
      fill = label2plot
    ),
    stat = "identity",
    position = position_dodge(),
    color = "white",
    linewidth = 0.5
  ) +
  scale_y_continuous(
    labels = scales::percent,
    limits = c(0, 1.15),
    breaks = seq(0, 1, 0.2)
  ) +
  theme_classic() +
  theme(
    legend.position = "none",
    plot.title = element_text(hjust = 0.5,
                              size = 14,
                              face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    plot.caption = element_text(hjust = 0.5),
  ) +
  scale_fill_manual(values = c("yes" = "#AFCDE4", "no" = "#389DC3")) +
  geom_text(
    data = df,
    size = 3,
    position = position_dodge2(preserve = 'single', width = 0.9),
    hjust = 0.5,
    vjust = -0.5,
    color = "black",
    aes(
      x = factor(label2plot, levels = val_label),
      y = var_rel,
      label = paste0(sprintf("%.1f", var_rel * 100), "%", "\n(N=", var_abs, ")")
    )
  ) +
  labs(
    subtitle = paste(subtitle),
    title = str_wrap(title, 45),
    x = var_label,
    y =  "",
    fill = ""
  ) +
  facet_wrap( ~ gruppe)

当前图表中,yes和no类别的两个时间点柱子仅左侧显示垂直cohort标签,需要实现每个柱子都对应显示垂直的时间点标签。

解决方案

通过新增一个geom_text图层,专门为每个柱子添加垂直的cohort标签,并通过位置对齐保证标签与柱子一一对应。以下是修改后的完整代码:

var_label <- "blabla"
title <- "blublub"
subtitle <- "blablub"
val_label <- c("yes", "no")

packages2check <- c("ggplot2", "stringr")

for (package in packages2check) {
  if (!requireNamespace(package, quietly = TRUE)) {
    install.packages(package)
    library(package, character.only = TRUE)
  } else {
    library(package, character.only = TRUE)
  }
}

ggplot() +
  geom_bar (
    data = df,
    aes(
      x = factor(label2plot, levels = val_label),
      y = var_rel,
      group = cohort,
      fill = label2plot
    ),
    stat = "identity",
    position = position_dodge(),
    color = "white",
    linewidth = 0.5
  ) +
  # 新增的cohort垂直标签图层
  geom_text(
    data = df,
    aes(
      x = factor(label2plot, levels = val_label),
      y = -0.05, # 标签位置:柱子底部下方
      label = cohort,
      group = cohort
    ),
    position = position_dodge(width = 0.9), # 和柱状图的dodge宽度匹配
    angle = 90, # 设置垂直显示
    hjust = 1,
    vjust = 0.5,
    size = 3
  ) +
  scale_y_continuous(
    labels = scales::percent,
    limits = c(-0.1, 1.15), # 调整y轴下限,容纳底部标签
    breaks = seq(0, 1, 0.2)
  ) +
  theme_classic() +
  theme(
    legend.position = "none",
    plot.title = element_text(hjust = 0.5,
                              size = 14,
                              face = "bold"),
    plot.subtitle = element_text(hjust = 0.5),
    plot.caption = element_text(hjust = 0.5),
  ) +
  scale_fill_manual(values = c("yes" = "#AFCDE4", "no" = "#389DC3")) +
  geom_text(
    data = df,
    size = 3,
    position = position_dodge2(preserve = 'single', width = 0.9),
    hjust = 0.5,
    vjust = -0.5,
    color = "black",
    aes(
      x = factor(label2plot, levels = val_label),
      y = var_rel,
      label = paste0(sprintf("%.1f", var_rel * 100), "%", "\n(N=", var_abs, ")")
    )
  ) +
  labs(
    subtitle = paste(subtitle),
    title = str_wrap(title, 45),
    x = var_label,
    y =  "",
    fill = ""
  ) +
  facet_wrap( ~ gruppe)

关键修改说明:

  • 新增geom_text图层:专门用于渲染cohort的垂直标签,设置angle = 90实现垂直显示
  • 位置对齐:position = position_dodge(width = 0.9)与柱状图的position_dodge()参数匹配,确保标签和对应柱子对齐
  • 标签位置调整:y = -0.05将标签放在柱子底部下方,同时调整scale_y_continuous的limits为c(-0.1, 1.15),避免标签被截断
  • 分组设置:aes中指定group = cohort,保证每个时间点的标签被正确分配到对应柱子

如果希望将标签放在柱子顶部,只需修改geom_text的y参数为y = var_rel + 0.02,并调整vjust参数即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:35:24