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

如何为两家经销商的堆叠条形图分别按销量高低排序车型?

问题描述

现有一个名为cars的数据集,用于描述两家经销商的汽车品牌销售占比,数据集定义如下:

cars <- data.frame(dealership = rep(c("a", "b"), 3), car = rep(c("toyota", "ford", "opel"), each = 2), percent = c(10, 65, 40, 5, 50, 30))

需求:用堆叠条形图可视化该数据,每个经销商对应一个条形,且每个条形内的汽车品牌需按销量占比从高到低排序。

尝试了以下代码,但仅经销商B的车型排序正确,经销商A的车型顺序跟随B的顺序(toyota-opel-ford),而非正确的opel-ford-toyota:

#Arrange cars by dealership and sort them
cars <- cars %>%
  group_by(dealership) %>%
  arrange(percent, .by_group = TRUE)

#Create the stacked barplot
ggplot(cars, aes(x = dealership, y = percent, fill = car)) +
  geom_bar(stat = "identity") +
  labs(title = "Car brands sold by dealership",
       x = "Dealership",
       y = "Percent") +
  coord_flip() +
  theme_minimal() +
  scale_fill_brewer(palette = "Set2")
解决方案

问题出在ggplot2中,fill参数使用的car是全局因子,其顺序是统一的,不会因为数据框的行顺序而在分组内独立变化。要实现每个经销商内的车型按销量排序,需要为每个经销商创建独立的车型排序因子。

具体步骤:

  • 分组排序后,为每个经销商内的车型生成带分组标识的复合标签,并将其转换为因子,因子顺序与分组排序后的行顺序一致。
  • 绘图时使用这个复合因子作为fill的映射,再通过调整图例标签去掉分组前缀,保持图例简洁。

完整代码:

library(dplyr)
library(ggplot2)

# 原始数据集
cars <- data.frame(dealership = rep(c("a", "b"), 3), 
                   car = rep(c("toyota", "ford", "opel"), each = 2), 
                   percent = c(10, 65, 40, 5, 50, 30))

# 分组排序并创建带经销商标识的车型顺序因子
cars_sorted <- cars %>%
  group_by(dealership) %>%
  arrange(desc(percent), .by_group = TRUE) %>% # 按销量降序排列,升序去掉desc()即可
  mutate(car_order = paste(dealership, car, sep = "-")) %>% # 创建复合标签区分不同经销商的同品牌车型
  mutate(car_order = factor(car_order, levels = car_order)) # 按排序后的行顺序设置因子水平

# 绘制堆叠条形图
ggplot(cars_sorted, aes(x = dealership, y = percent, fill = car_order)) +
  geom_bar(stat = "identity") +
  labs(title = "Car brands sold by dealership",
       x = "Dealership",
       y = "Percent",
       fill = "Car Brand") +
  coord_flip() +
  theme_minimal() +
  scale_fill_brewer(palette = "Set2",
                    labels = function(x) gsub("^.*-", "", x)) # 移除图例标签中的经销商前缀

代码说明:

  • arrange(desc(percent), .by_group = TRUE):确保每个经销商内的车型按销量降序排列,若需要升序显示,去掉desc()即可。
  • car_order变量:通过拼接经销商和车型名称,让每个经销商的车型拥有独立的因子水平,彻底避免全局顺序的干扰。
  • scale_fill_brewer的labels参数:用gsub正则匹配去掉复合标签的经销商前缀,让图例仅显示车型名称,保持视觉简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 11:59:57