如何在ggplot2条形图中正确排序月-年格式的X轴?
问题:ggplot2条形图坐标轴排序异常
我有一个包含年份(J)、月份(M)、年月组合(Monat,格式为月份-年份)、部门名称(Wer)和月度收入(Einnahmen)的数据框。需要绘制堆叠条形图,以Monat为X轴、Einnahmen为Y轴、Wer作为分类填充变量,但当前X轴的排序不符合实际年月顺序。尝试过将M和J转为因子、使用reorder函数,都没解决问题。另外因为X轴标签密集,用了coord_flip()翻转坐标轴,这也给排序处理带来了麻烦。
相关代码如下:
library(dplyr) library(ggplot2) df_cre <- data.frame(J=c(2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2020, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023), M=c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 11, 12, 12, 1, 1, 2, 2, 3, 4, 5, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 1, 2, 3, 4, 5, 5), Wer=c("Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt2", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt1", "Abt2"), Einnahmen=c(20265.43, 9323.48, 3350.52, 3338.37, 3317.05, 7223.91, 4632.8, 23264.63, 3678.72, 3374.29, 8290, 8176.53, 7805.57, 3276.87, 3490.59, 3189.03, 3189.72, 7115.97, 3183.22, 3182.24, 3475.89, 3343.2, 203.71, 8095.84, 599.64, 3214.26, 639.52, 3567.89, 509.28, 7327.42, 644.01, 3452.29, 3623.8, 3363.84, 7580.19, 3975.35, 1913, 3796.32, 1110, 3765.24, 1110, 3976.99, 1110, 7542.8, 1549, 3529.44, 3451.7, 3476.97, 3495.02, 4110.98, 485.48, 447.02), Monat=c("1-2020", "2-2020", "3-2020", "4-2020", "5-2020", "6-2020", "7-2020", "8-2020", "9-2020", "10-2020", "11-2020", "12-2020", "1-2021", "2-2021", "3-2021", "4-2021", "5-2021", "6-2021", "7-2021", "8-2021", "9-2021", "10-2021", "10-2021", "11-2021", "11-2021", "12-2021", "12-2021", "1-2022", "1-2022", "2-2022", "2-2022", "3-2022", "4-2022", "5-2022", "6-2022", "7-2022", "7-2022", "8-2022", "8-2022", "9-2022", "9-2022", "10-2022", "10-2022", "11-2022", "11-2022", "12-2022", "1-2023", "2-2023", "3-2023", "4-2023", "5-2023", "5-2023")) df_cre %>% ggplot(aes(fill=Wer, y=Einnahmen, x=Monat)) + geom_bar(position="stack", stat="identity") + coord_flip() + #scale_x_discrete(breaks = scales::pretty_breaks(n=10)) scale_x_discrete(guide = guide_axis(n.dodge = 2))
当前错误的排序效果:
解决方法
问题根源是Monat列是字符串类型,ggplot默认按字典序排序(比如"1-2021"会排在"10-2020"前面)。以下两种方案可解决排序问题:
方案1:生成有序因子
基于日期排序后,将Monat转为有序因子,保留原显示文本:
library(dplyr) library(ggplot2) df_cre <- df_cre %>% # 生成日期列用于排序 mutate(date = as.Date(paste0(J, "-", M, "-01")), # 按日期顺序生成有序因子 Monat_ordered = factor(Monat, levels = unique(Monat[order(date)]))) # 使用有序因子作为x轴绘图 df_cre %>% ggplot(aes(fill=Wer, y=Einnahmen, x=Monat_ordered)) + geom_bar(position="stack", stat="identity") + coord_flip() + scale_x_discrete(guide = guide_axis(n.dodge = 2)) + labs(x = "年月")
方案2:直接使用日期轴
将年月转为日期类型,让ggplot自动按时间排序,同时自定义标签格式:
df_cre <- df_cre %>% mutate(date = as.Date(paste0(J, "-", M, "-01"))) df_cre %>% ggplot(aes(fill=Wer, y=Einnahmen, x=date)) + geom_bar(position="stack", stat="identity") + coord_flip() + # 自定义日期显示为"月份-年份"格式 scale_x_date(date_labels = "%m-%Y", breaks = "1 month", guide = guide_axis(n.dodge = 2)) + labs(x = "年月")
说明
- 方案1适合需要严格保留原
Monat文本的场景,通过有序因子强制指定排序顺序。 - 方案2更符合时间序列数据的处理逻辑,利用日期类型的天然排序属性,同时灵活自定义显示格式。
内容的提问来源于stack exchange,提问作者Joysn
相关产品推荐
相关产品推荐

