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

在R的ggplot中为facet_wrap添加纵向分类标签

问题描述

我有一个包含6个站点(城市)的数据集,每两个站点归为一个名为method的类别。我想用facet_wrap绘制每个站点的图表,设置为2列3行(每行对应一个method),并为每行添加method名称作为纵向标签,每个分面添加站点名称作为横向标签。我无法使用facet_grid,因为它会生成不符合需求的布局,且无法为单个分面设置标签。尝试过facet_wrap(method~factor(city_f....)和facet_grid(method~factor(city_f....)都没达到预期,想知道怎么用facet_wrap结合分类变量添加纵向标签。现有代码如下:

ggplot(effect, aes(x=year, y= log10(effect+1), fill=type))+
    geom_boxplot(width=0.6)+
    facet_wrap(~factor(city_f, levels=c('S','M','G','R','O1','O2')), ncol = 2, labeller = as_labeller(new_labels2))+ 
    scale_y_continuous(n.breaks = 8)+
    theme(axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 6))+
    labs(x="year", y="log[effect+1]", title="Effect by city")+
    geom_hline(yintercept=0,linetype="dashed")+ 
    geom_hline(aes(yintercept=-Inf)) + 
    geom_vline(aes(xintercept=-Inf))
解决方案

思路前提

首先确保每个站点(city_f)和对应的method绑定好,并且调整因子顺序,保证同一个method下的两个站点在facet_wrap中排在同一行。这里提供两种实用方法:


方法一:用annotation_custom给facet_wrap添加纵向行标签

这种方法不需要额外包(仅依赖ggplot2和grid),直接在现有图表基础上添加自定义注释:

  1. 绑定站点与method的映射关系
# 先创建映射表,替换成你的实际method名称
method_map <- data.frame(
  city_f = c('S','M','G','R','O1','O2'),
  method = c("方法A", "方法A", "方法B", "方法B", "方法C", "方法C")
)
# 合并到原数据集
effect <- merge(effect, method_map, by = "city_f")
# 调整因子顺序,保证同一method的站点相邻
effect$city_f <- factor(effect$city_f, levels = c('S','M','G','R','O1','O2'))
  1. 绘制基础图表并添加纵向标签
library(ggplot2)
library(grid)

p <- ggplot(effect, aes(x=year, y= log10(effect+1), fill=type))+
  geom_boxplot(width=0.6)+
  # 把站点标签放在分面底部,行间距调大给method标签留空间
  facet_wrap(~city_f, ncol = 2, labeller = as_labeller(new_labels2), strip.position = "bottom")+
  scale_y_continuous(n.breaks = 8)+
  theme(
    axis.text.x = element_text(size = 8), 
    axis.text.y = element_text(size = 6),
    strip.text = element_text(size = 10, face = "bold"),
    panel.spacing.y = unit(1.5, "cm")
  )+
  labs(x="year", y="log[effect+1]", title="Effect by city")+
  geom_hline(yintercept=0,linetype="dashed")+ 
  geom_hline(aes(yintercept=-Inf)) + 
  geom_vline(aes(xintercept=-Inf))

# 添加每行的method纵向标签,y_positions根据图表高度调整(0-1为相对位置)
method_labels <- unique(effect$method)
y_positions <- c(0.85, 0.5, 0.15)

for(i in seq_along(method_labels)){
  p <- p + annotation_custom(
    grob = textGrob(method_labels[i], rot = 90, gp = gpar(fontsize=10, fontface="bold")),
    xmin = -Inf, xmax = -Inf,
    ymin = y_positions[i], ymax = y_positions[i]
  )
}

# 显示图表
print(p)

方法二:用patchwork按method分组拼接图表

这种方法更灵活,能精准控制每行的标题和布局:

  1. 拆分数据集并定义绘图函数
library(ggplot2)
library(patchwork)

# 按method拆分数据
method_list <- split(effect, effect$method)

# 定义单个城市的绘图模板
plot_city <- function(data){
  ggplot(data, aes(x=year, y= log10(effect+1), fill=type))+
    geom_boxplot(width=0.6)+
    facet_wrap(~city_f, ncol=2, labeller = as_labeller(new_labels2))+
    scale_y_continuous(n.breaks = 8)+
    theme(
      axis.text.x = element_text(size = 8), 
      axis.text.y = element_text(size = 6),
      strip.text = element_text(size = 10, face = "bold")
    )+
    geom_hline(yintercept=0,linetype="dashed")+ 
    geom_hline(aes(yintercept=-Inf)) + 
    geom_vline(aes(xintercept=-Inf))
}
  1. 分别绘制每行并组合
# 给每个method的子图添加纵向标题
plot1 <- plot_city(method_list[["方法A"]]) + 
  plot_annotation(title = "方法A", theme = theme(plot.title = element_text(angle = 90, vjust = 0.5)))
plot2 <- plot_city(method_list[["方法B"]]) + 
  plot_annotation(title = "方法B", theme = theme(plot.title = element_text(angle = 90, vjust = 0.5)))
plot3 <- plot_city(method_list[["方法C"]]) + 
  plot_annotation(title = "方法C", theme = theme(plot.title = element_text(angle = 90, vjust = 0.5)))

# 组合成3行2列,统一收集图例和全局标题
(plot1 / plot2 / plot3) + 
  plot_layout(guides = "collect") +
  plot_annotation(title = "Effect by city", xlab = "year", ylab = "log[effect+1]")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 21:54:57