R:如何调整柱状图中各月份柱子之间的间距?
要让各月份的柱子等距排列,可以把横轴改为按月份排序的因子,再用 width 调整柱间空白。width 越小,柱子越窄,空白越大;反之,空白越小。
保留日期轴时也能调整 width,但相邻月份的柱子中心距离仍由实际天数决定。
为什么 Jan 和 Feb 之间更宽?
原代码把日期类型的 month_day 映射到横轴,并使用 scale_x_date(),因此柱子按实际时间间隔排列。
假设每个月的数据都在月初,将日期统一到 2027 年后:
- 1 月 1 日到 2 月 1 日相差 31 天。
- 2 月 1 日到 3 月 1 日相差 28 天。
所以,Jan 和 Feb 的柱子中心距离比 Feb 和 Mar 更大。统一年份仍会保留月份天数的差异,"%b" 也只改变标签的显示格式。
推荐做法:使用离散月份轴
将月份转换为因子,并指定 1 至 12 月的顺序。这样,相邻月份在离散轴上的中心距离就相同了,柱间空白则由柱宽控制。ggplot2 离散位置刻度说明
同一个月有多条日期记录时,可以先按年月和类别汇总,再绘图。以下代码保留了按年份分面、按类别堆叠和柱内标签。Month 需已是 Date 或 lubridate 能处理的日期时间类型。
library(dplyr)
library(lubridate)
library(ggplot2)
my_group_sum <- my_group %>%
mutate(
year = year(Month),
month_num = month(Month)
) %>%
group_by(year, month_num, Category) %>%
summarise(
Incidents = sum(Incidents),
.groups = "drop"
) %>%
mutate(
month_label = factor(
month_num,
levels = 1:12,
labels = month.abb
)
)
ggplot(
my_group_sum,
aes(x = month_label, y = Incidents, fill = Category)
) +
geom_col(
width = 0.7,
position = position_stack(reverse = TRUE)
) +
geom_text(
aes(label = Incidents, color = Category),
position = position_stack(reverse = TRUE, vjust = 0.5),
size = 5,
fontface = "bold"
) +
scale_x_discrete(drop = FALSE) +
facet_wrap(~ year) +
labs(x = NULL, y = "Incidents") +
theme(
axis.text.x = element_text(
color = "black",
size = 12,
angle = 45,
hjust = 1
)
)
geom_col() 直接绘制汇总后的 Incidents,与原来的 geom_bar(stat = "identity") 用途一致,两者都支持设置 width。ggplot2 柱状图说明
在离散轴上,可以尝试以下柱宽:
width = 0.5 # 柱子较窄,柱间空白较大
width = 0.9 # 柱子较宽,柱间空白较小
width = 1 # 相邻月份都有柱子时,柱体边缘相接
调整 width 时,月份中心的位置保持不变。原有的图例、字体和边框等 theme() 设置可以继续添加到示例末尾。
保留日期轴时如何调整?
如果需要表达真实的时间间隔,可以保留原来的 month_day 和日期轴,在柱形图层中增加 width:
geom_bar(
stat = "identity",
width = 20,
alpha = 1,
position = position_stack(reverse = TRUE)
)
对于 Date 横轴,width = 20 表示柱宽为 20 天。减小这个值会增大柱间空白,增大则会缩小空白。如果柱宽超过相邻日期的距离,柱子就会重叠。
日期刻度可以这样设置:
scale_x_date(
date_breaks = "1 month",
date_labels = "%b"
)
date_breaks 控制刻度间隔,date_labels 控制标签格式,两者都不会让月份等距排列。ggplot2 日期刻度说明
注意事项
- 原代码中的
size = 2.5不控制柱宽,调整柱间空白应使用width。 scale_x_discrete(drop = FALSE)会保留全部 12 个月的位置。缺少数据的月份留空,不会自动补成零。如果只想显示数据中出现的月份,可以去掉这一设置。expand控制横轴两端的留白,panel.spacing控制年份分面之间的距离。调整同一面板内的柱间空白时,应优先设置width。- 改用月份因子后,不再需要构造固定年份的
month_day,也应移除原来的scale_x_date()。
备注:内容仅供参考。
