如何在ggplot中按支出排序多分组条形图?
解决方案
问题出在你使用reorder(country, values)时,values包含了收入和支出两类数据,reorder默认用所有值的中位数来排序,自然不是你要的按支出单独排序的结果。正确的做法是在数据透视前就基于支出金额确定国家的排序,并将country转为有序因子,这样后续绘图时分组条形的顺序和间距都会正常。
修改后的代码
# 原始数据 df_country <- data.frame(country = c('Denmark', 'Finland', 'Japan', 'Norway', 'Switzerland', 'Germany', 'USA'), revenues = c(283631, 238985, 133487, 354506, 221348, 235079, 181078), expenses = c(261849, 243311, 144859, 314360, 212768, 227343, 218995)) # 按支出金额排序,将country转为有序因子 df_country_sorted <- df_country %>% arrange(expenses) %>% # 按支出升序排序,降序用arrange(desc(expenses)) mutate(country = factor(country, levels = country)) # 锁定因子顺序 # 绘图 df_country_sorted %>% pivot_longer(cols = c('revenues', 'expenses'), names_to = 'vars', values_to = 'values') %>% ggplot(aes(x = country, y = values, fill = vars)) + geom_bar(stat = 'identity', width = 0.7, position = position_dodge(width = 0.9)) + scale_y_continuous(breaks = seq(0, 3.5e+5, 5e+4)) + scale_fill_manual(values = c('#ff9214', '#003f5c')) + labs(x = NULL) + theme( axis.text.x = element_text(hjust = -0.25, margin = margin(t = -2, unit = 'mm')), axis.ticks = element_blank(), panel.background = element_blank(), panel.grid.major.x = element_blank(), panel.grid.major.y = element_line(colour = '#909090'), text = element_text(family = 'serif') )
关键说明
arrange(expenses):先对原始数据按支出金额排序(升序,需要降序就改成arrange(desc(expenses)))。mutate(country = factor(country, levels = country)):把country列转为因子,并且指定levels为排序后的国家顺序,这样ggplot绘图时会严格按照这个顺序展示x轴类别,不会自动调整。- 后续的数据透视和绘图逻辑和你原来的代码一致,只是x轴用的是已经锁定顺序的因子型
country,既满足了按支出排序的需求,也不会出现条形间距错乱的问题。
内容的提问来源于stack exchange,提问作者Henning Åsheim
相关产品推荐
相关产品推荐

