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

如何设置ggplot标签,使grid.arrange排列的3幅图宽度均等?

问题描述

用ggplot绘制3幅关联图表,通过gridExtra::grid.arrange()横向排列后,最左侧图表因带有较长的纵向行标签(y轴)被挤压得非常狭窄。要求3幅图的绘图区域宽度保持一致,即使整体宽度缩小以容纳行标签。此前尝试用ggtextable解决但未成功。

绘图代码

p1 <- ggplot(main.frame2, aes(x=item.true.prev, y=reorder(substring(Shorthand,5), item.true.prev), color=item.republican))+
  geom_point(size=3)+
  theme_forest()+
  xlim(0,1)+ xlab("True Prevalence")+ylab("Item")+
  scale_colour_gradient(low="blue", high="red")+
  geom_stripes(odd = "#33333333", even = "#00000000")+
  tidytext::scale_y_reordered() +
  guides(color = "none") +
  theme(text = element_text(size=18))

p2 <- ggplot(main.frame2, aes(x=perceived.prev, y=reorder(item.id.short, item.true.prev), color=item.republican))+
  geom_point(size=3)+
  theme_forest()+
  xlim(0,1)+xlab("Perceived Prevalence")+ylab("")+
  scale_colour_gradient(low="blue", high="red")+
  geom_stripes(odd = "#33333333", even = "#00000000")+
  tidytext::scale_y_reordered() +
  theme(axis.text.y=element_blank())+
  guides(color = "none") +
  theme(text = element_text(size=18))

p3 <- ggplot(main.frame2, aes(x=generic.acceptance, y=reorder(item.id.short, item.true.prev), color=item.republican))+
  geom_point(size=3)+
  theme_forest()+
  xlim(0,1)+xlab("Generic Acceptance")+ylab("")+
  scale_colour_gradient(low="blue", high="red")+
  geom_stripes(odd = "#33333333", even = "#00000000")+
  tidytext::scale_y_reordered() +
  guides(color = "none")+
  theme(axis.text.y=element_blank(),
        axis.ticks.y=element_blank())+
  theme(text = element_text(size=18))

gridExtra::grid.arrange(p1,p2, p3, nrow=1)

数据样例

item.id.short Shorthand                    perceived.prev item.true.prev generic.acceptance
           <dbl> <chr>                                 <dbl>          <dbl>              <dbl>
 1            22 "(D) Liberal identity "              0.0755           0.07             0.0288
 2            42 "(R) Conservative identity "         0.0935           0.13             0.0336
 3            62 "(R) Prayer in schools"              0.132            0.18             0.0935
 4            40 "(R) Require Lord's Prayer"          0.139            0.42             0.0959
 5            28 "(D) Decrease police"                0.140            0.11             0.101 
 6            64 "(R) US as Christian nation"         0.141            0.06             0.0911
 7            52 "(R) Ban trans soldiers"             0.142            0.11             0.0671
 8            55 "(R) Withdraw Paris Deal"            0.154            0.11             0.0839
 9            56 "(R) Build southern wall"            0.154            0.13             0.0839
10            60 "(R) Eliminate gun permits"          0.156            0.17             0.0983
解决方案

方法1:调整grid.arrange()的宽度分配

通过widths参数手动分配各图的总宽度,给左侧带标签的p1额外预留标签空间,确保三个图的绘图区域宽度一致:

# 假设绘图区域基础宽度为1单位,p1的y轴标签需要0.8单位额外宽度
gridExtra::grid.arrange(p1, p2, p3, nrow=1, widths = grid::unit(c(1.8, 1, 1), "null"))

可根据实际标签长度调整1.8的数值,直到三个图的绘图区域视觉上等宽。

方法2:使用patchwork包实现更灵活的排列

patchwork包对多图排列的对齐和宽度控制更直观,默认优先保证绘图区域等宽,同时自动适配标签空间:

library(patchwork)

# 横向排列,设置宽度比例,确保p1有足够空间放标签,同时纵向对齐
p1 + p2 + p3 + plot_layout(nrow = 1, widths = c(1.8, 1, 1), align = "v")

align = "v"参数可确保三个图的纵向轴完全对齐,提升整体美观度。

补充优化:缩短y轴标签长度

如果标签过长,可先对标签进行自动换行处理,减少所需宽度:

# 在p1的y轴映射中加入换行处理
p1 <- ggplot(main.frame2, aes(x=item.true.prev, y=reorder(stringr::str_wrap(substring(Shorthand,5), width = 15), item.true.prev), color=item.republican))+
  geom_point(size=3)+
  theme_forest()+
  xlim(0,1)+ xlab("True Prevalence")+ylab("Item")+
  scale_colour_gradient(low="blue", high="red")+
  geom_stripes(odd = "#33333333", even = "#00000000")+
  tidytext::scale_y_reordered() +
  guides(color = "none") +
  theme(text = element_text(size=18),
        axis.text.y = element_text(hjust = 1)) # 右对齐换行后的标签

调整width = 15的数值可控制每行标签的字符数,让标签显示更紧凑。


内容的提问来源于stack exchange,提问作者eric andre the gian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:35:21