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

如何在ggplot的分面条带间添加垂直线?

嵌套分面外层添加垂直分隔线解决方案

问题说明

当前使用ggh4x::facet_nested绘制的图表中,外层分面(ffvv字段的a、b分组)之间无分隔线;期望在两个外层分组之间添加一条垂直红色分隔线,明确区分不同分组区域。

修改后可复现代码

library(tidyverse)
library(ggh4x)

df <- tibble::tibble(
  epoca = factor(c("H", "S", "S", "H", "S", "H", "S"), levels = c("S", "H")),
  ano = c("2019", "2018", "2019", "2021", "2022", "2022", "2021"),
  n = rep(3:1, c(3L, 2L, 2L)),
  etiqueta = rep(c("3", "2", "1"), c(3L, 2L, 2L)),
  ffvv = c(rep("a", 3), rep("b", 4))
)

df %>% 
  ggplot(aes(x = epoca, y = n, fill = epoca)) +
  geom_col(width = 0.8, position = position_dodge(0.8)) +
  geom_text(aes(x = epoca, label = etiqueta),
            position = position_dodge(0.9), vjust = 0, size = 8) +
  ggh4x::facet_nested(cols = vars(ffvv, ano),
                      switch = "x",
                      scales = "free_x",
                      space = "free_x") +
  # 添加外层分面分隔线
  geom_vline(xintercept = 2.5, color = "red", linewidth = 2) +
  theme(strip.background = element_rect(fill = "white"),
        strip.text = element_text(size = 25, lineheight = 0.6),
        strip.placement = "outside",
        axis.text.x = element_text(angle = 0, size = 27, lineheight = unit(.8, "lines")),
        # 消除面板间距,让分隔线贴合分组边界
        panel.spacing = unit(0, "lines"))

通用优化方案(适配数据变化)

如果后续ffvv的分组数量或每组内的类别数量发生变化,手动指定xintercept会失效,可通过代码动态计算分隔线位置:

# 先计算外层分组的边界位置
split_pos <- df %>% 
  group_by(ffvv) %>% 
  summarise(count = n_distinct(epoca)) %>% 
  pull(count) %>% 
  cumsum() %>% 
  {. - 0.5} %>% 
  head(-1)

df %>% 
  ggplot(aes(x = epoca, y = n, fill = epoca)) +
  geom_col(width = 0.8, position = position_dodge(0.8)) +
  geom_text(aes(x = epoca, label = etiqueta),
            position = position_dodge(0.9), vjust = 0, size = 8) +
  ggh4x::facet_nested(cols = vars(ffvv, ano),
                      switch = "x",
                      scales = "free_x",
                      space = "free_x") +
  geom_vline(xintercept = split_pos, color = "red", linewidth = 2) +
  theme(strip.background = element_rect(fill = "white"),
        strip.text = element_text(size = 25, lineheight = 0.6),
        strip.placement = "outside",
        axis.text.x = element_text(angle = 0, size = 27, lineheight = unit(.8, "lines")),
        panel.spacing = unit(0, "lines"))

该方案会自动根据ffvv每组的类别数量计算分隔线位置,无需手动调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 02:16:34