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

使用ggh4x::facet_manual时如何在空白面板下方显示X轴

问题描述

我正在处理多组有时共享数值范围的图形(示例数据未体现该特性),希望用ggh4x::facet_manual实现并排展示,但无法在图形下方的空白面板区域显示X轴。

facet_manual()的官方文档中,axes参数可选值如下:

  • "margins"或FALSE:仅在外部边缘绘制轴(默认)
  • "x":在外部边缘和所有内部X轴绘制轴
  • "y":在外部边缘和所有内部Y轴绘制轴
  • "all"或TRUE:为每个面板绘制轴

但这些选项都无法让空白面板(如示例设计中的#和h位置)显示X轴。

可复现代码如下:

# Data ----
library(tibble)
reprex_data <- tibble(
  date = as.Date(rep(
    rep(
      c(
        "2022-01-15", "2022-02-15", "2022-03-15", "2022-04-15", "2022-05-15",
        "2022-06-15", "2022-07-15", "2022-08-15", "2022-09-15", "2022-10-15",
        "2022-11-15", "2022-12-15", "2023-01-15", "2023-02-15", "2023-03-15",
        "2023-04-15", "2023-05-15", "2023-06-15", "2023-07-15", "2023-08-15",
        "2023-09-15", "2023-10-15", "2023-11-15", "2023-12-15"
      ),
      2
    ),
    rep(c(1L, 5L), each = 24L)
  )),
  group = c(
    "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A",
    "A", "A", "A", "A", "A", "A", "A", "A", "A", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B", "C", "E", "F", "D", "B", "C",
    "E", "F", "D", "B", "C", "E", "F", "D", "B"
  ),
  value = c(
    1032.8, 976.4, 885.6, 893.7, 793.8, 777.4, 847.8, 815.9, 795.4, 862.7, 873.4,
    1086.4, 964.1, 870.4, 837.8, 812, 778, 759.1, 731.4, 759.6, 778.3, 820.3,
    857.7, 943.7, 200.4, 38.6, 20.6, 64.5, 245.7, 188.2, 38.6, 17.6, 56.2, 235.1,
    182.6, 36.7, 17.4, 56.6, 238.6, 183.9, 34.6, 17.6, 65.5, 238.6, 165.5, 34.1,
    16.5, 48.8, 234, 157.8, 34.3, 16.1, 47.8, 237.8, 164.2, 34.3, 16.9, 52, 241.1,
    157.8, 34.8, 17, 51.8, 241.6, 160, 36.4, 16.1, 47.4, 242.3, 173.9, 36.6, 17.1,
    55.3, 246.9, 179.7, 38.1, 17.4, 62.3, 242.8, 219.9, 42.5, 21.1, 103.7, 257.5,
    201.9, 40.6, 18.3, 93.6, 240.3, 186.6, 37.5, 18.9, 72.7, 238.7, 182.4, 36.7,
    18.6, 63.4, 237, 173.4, 34.3, 17.8, 56.3, 231.5, 164.1, 34, 16, 54, 227.9,
    150.1, 31.9, 15, 48.8, 235.6, 145.6, 31.7, 14, 46.8, 234.6, 151.9, 32.3, 16,
    48.8, 234.7, 154.3, 33.8, 15.8, 49, 239.7, 163.8, 36.8, 16.9, 56, 243.4,
    177.4, 37.3, 18, 60.2, 243.9, 196, 37.4, 20.2, 76.8, 243.5
  )
)
 
# Code ----
# install.packages("ggh4x")
library(ggplot2)
library(ggh4x)

design <- c("a#
            bc
            d#
            ef
            #h")

ggplot(data = reprex_data) +
  geom_point(aes(x = date, y= value), colour = "black", size = 1.5, shape = 19, alpha = 0.2) + 
  geom_line(aes(x = date, y = value), colour = "black", linewidth = 0.5, alpha = 0.2) + 
  facet_manual(~ group, design, scales = "free_y") 
解决方案

facet_manual的axes参数仅对包含数据的面板生效,空白面板没有对应的数据组,因此无法直接通过参数控制显示X轴。以下两种方法可实现需求:

方法1:添加虚拟数据组

给空白面板对应的位置添加虚拟数据组,让axes参数能识别并绘制X轴:

library(dplyr)

# 创建虚拟数据,包含空白面板的组和X轴范围
dummy_data <- tibble(
  date = range(reprex_data$date),
  group = rep(c("#", "h"), each = 2),
  value = 0  # 虚拟值,后续会隐藏
)

# 合并原始数据与虚拟数据
reprex_data_full <- bind_rows(reprex_data, dummy_data)

# 绘制图形,设置axes="x"显示所有X轴
ggplot(data = reprex_data_full) +
  geom_point(aes(x = date, y= value), colour = "black", size = 1.5, shape = 19, alpha = 0.2) + 
  geom_line(aes(x = date, y = value), colour = "black", linewidth = 0.5, alpha = 0.2) + 
  facet_manual(~ group, design, scales = "free_y", axes = "x") +
  # 隐藏虚拟组的Y轴范围(排除虚拟值0)
  scale_y_continuous(limits = function(y) {
    if (any(y == 0)) {
      range(y[y != 0])
    } else {
      range(y)
    }
  })

方法2:手动修改gtable对象

直接提取ggplot的gtable结构,复制已有面板的X轴并添加到空白面板下方:

library(grid)
library(gtable)

# 先绘制基础图形
p <- ggplot(data = reprex_data) +
  geom_point(aes(x = date, y= value), colour = "black", size = 1.5, shape = 19, alpha = 0.2) + 
  geom_line(aes(x = date, y = value), colour = "black", linewidth = 0.5, alpha = 0.2) + 
  facet_manual(~ group, design, scales = "free_y", axes = "x")

# 转换为gtable对象
gt <- ggplotGrob(p)

# 获取已有底部X轴的模板(取第一个底部轴)
axis_template <- gt$grobs[grepl("axis-b", gt$layout$name)][[1]]

# 定位空白面板的位置(通过gtable布局确认)
blank_panel_pos <- c(
  which(gt$layout$t == 1 & gt$layout$l == 2),  # 第一行第二列的空白面板
  which(gt$layout$t == 3 & gt$layout$l == 2),  # 第三行第二列的空白面板
  which(gt$layout$t == 5 & gt$layout$l == 1)   # 第五行第一列的空白面板
)

# 给每个空白面板添加X轴
for (pos in blank_panel_pos) {
  gt <- gtable_add_grob(
    gt, 
    axis_template,
    t = gt$layout$b[pos] + 1,  # 放在面板下方
    l = gt$layout$l[pos],
    r = gt$layout$r[pos]
  )
}

# 调整轴的高度,避免重叠
gt$heights[gt$layout$b[blank_panel_pos] + 1] <- unit(5, "pt")

# 绘制修改后的图形
grid.draw(gt)

方法1操作简单,适合快速实现;方法2无需修改原始数据,更灵活,但需要对gtable结构有基础了解。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:22:05