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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:40:09