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

如何在ggplot2的geom_bar中移除条形间多余空白(不增宽条形)

移除ggplot2条形图的多余空白

问题描述

我需要移除ggplot2生成的条形图中多余的空白(如图中标记区域),要求不合并所有条形、不增加条形宽度。

原始图表:
原始条形图

需要移除的空白区域:
需要移除的空白

数据结构:

structure(list(hypoxic2 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), levels = c("No", "Yes"), class = "factor"), Season = structure(c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), levels = c("Pre", "Peak", "Post"), class = "factor")), row.names = c(NA, -185L), class = "data.frame")

原始绘图代码:

ggplot(df, aes(x = Season, ..count..)) +
  geom_bar(aes(fill = hypoxic2),
           position = position_dodge2(width = 1, preserve = "single")) + 
  ggtitle("TITLE") +
  labs(x="Season", fill = "Hypoxic (DO < 2 mg/L)", y = "Frequency") + 
  ggsci::scale_fill_igv(palette = "default") +
  scale_x_discrete(labels = c("Pre-Hypoxic",
                              "Peak-Hypoxic",
                              "Post-Hypoxic")) + 
  scale_y_continuous(limits = c(0,100),
                     expand = expand_scale(mult = c(0, 0.01),
                                           add = c(0, 0))) +
  theme_bw() +
  theme(legend.position = c(0.85,0.9),
        plot.title = element_text(hjust=0.5, face = "bold", family = "Arial",
                                  size=15),
        legend.background = element_rect(fill = "white", color = 1),
        axis.ticks.x = element_blank(),
        axis.title = element_text(size=15),
        legend.title.align = 0.5,
        legend.title = element_text(face = "bold"),
        axis.title.y = element_text(size = 15, 
                                    margin = margin(t = 0, r = 10, b = 0, l = 0), 
                                    color = "black"),
        axis.title.x.top = element_text(size = 14, 
                                        margin = margin(t = 0, r = 0, b = 10, l = 0), 
                                        color = "black"),
        text = element_text(family = "Times New Roman"),
        axis.text.y = element_text(color = "black", 
                                   size = 10, 
                                   angle = 0, 
                                   vjust = 0.5, 
                                   hjust = 1,
                                   margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.text.x = element_text(color = "black", 
                                   size = 12, 
                                   angle = 0, 
                                   vjust = 0, 
                                   hjust = 0.5,
                                   margin = margin(t = 0, r = 5, b = 0, l = 0)),
        strip.text.y = element_text(size=18), 
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank())

解决方案

问题出在两个参数:position_dodge2()的width值,以及x轴的默认留白。修改这两处即可移除目标空白:

修改后的代码

ggplot(df, aes(x = Season, ..count..)) +
  geom_bar(aes(fill = hypoxic2),
           # 缩小组内条形的间距,避免过宽留白
           position = position_dodge2(width = 0.6, preserve = "single"),
           # 固定条形宽度,满足不增宽的要求
           width = 0.5) + 
  ggtitle("TITLE") +
  labs(x="Season", fill = "Hypoxic (DO < 2 mg/L)", y = "Frequency") + 
  ggsci::scale_fill_igv(palette = "default") +
  scale_x_discrete(labels = c("Pre-Hypoxic",
                              "Peak-Hypoxic",
                              "Post-Hypoxic"),
                   # 移除x轴两侧的多余留白,0.2为标签预留少量空间
                   expand = c(0, 0.2)) + 
  scale_y_continuous(limits = c(0,100),
                     expand = expand_scale(mult = c(0, 0.01),
                                           add = c(0, 0))) +
  theme_bw() +
  theme(legend.position = c(0.85,0.9),
        plot.title = element_text(hjust=0.5, face = "bold", family = "Arial",
                                  size=15),
        legend.background = element_rect(fill = "white", color = 1),
        axis.ticks.x = element_blank(),
        axis.title = element_text(size=15),
        legend.title.align = 0.5,
        legend.title = element_text(face = "bold"),
        axis.title.y = element_text(size = 15, 
                                    margin = margin(t = 0, r = 10, b = 0, l = 0), 
                                    color = "black"),
        axis.title.x.top = element_text(size = 14, 
                                        margin = margin(t = 0, r = 0, b = 10, l = 0), 
                                        color = "black"),
        text = element_text(family = "Times New Roman"),
        axis.text.y = element_text(color = "black", 
                                   size = 10, 
                                   angle = 0, 
                                   vjust = 0.5, 
                                   hjust = 1,
                                   margin = margin(t = 0, r = 5, b = 0, l = 0)),
        axis.text.x = element_text(color = "black", 
                                   size = 12, 
                                   angle = 0, 
                                   vjust = 0, 
                                   hjust = 0.5,
                                   margin = margin(t = 0, r = 5, b = 0, l = 0)),
        strip.text.y = element_text(size=18), 
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank())

关键修改点

  1. position_dodge2(width = 0.6):将原width=1缩小,减少同一Season组内两个条形的间距,同时保持条形独立不合并。
  2. geom_bar(width = 0.5):固定条形宽度,避免调整dodge参数后条形自动变宽。
  3. scale_x_discrete(expand = c(0, 0.2)):移除x轴两侧的默认留白,0表示完全移除外侧空白,0.2为x轴标签预留少量空间防止截断,可根据实际显示效果微调。

这样修改后,就能移除你标记的空白区域,同时满足条形独立、宽度不变的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 11:41:02