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

如何在ggplot2的百分比堆叠柱状图中按指定填充类别重排X轴

问题描述

我有如下数据集:

id=c(1,2,3,1,2,3,1,2,3)
total_num=c(40,200,70,40,200,70,40,200,70)
category=c(rep("level1",3),rep("level2",3),rep("level3",3))
value=c(30,160,50,6,30,15,4,10,5)

df=data.frame(id,total_num,category,value)
df$percent=round(df$value/df$total_num,3)

我生成了如下堆叠柱状图的代码:

mycolors<-c("#E78AC3","#E5C494","#66C2A5")

library(forcats)
df%>%
  ggplot(aes(x=reorder(id,-percent),
             y=percent, 
             fill=factor(category,levels=c("level3","level2","level1"))))+
  geom_bar(position="fill",stat="identity") + 
  geom_text(
    data=df,
    aes(y=percent,
        label = ifelse(category == "level3", paste0(percent*100,"%"), "")),
    stat = "identity",
    position = position_stack(vjust = 0.5),size=2.5) +
  scale_fill_manual(values = mycolors,
                    labels=c('Serious', 'Moderate','Normal')) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1,size=10)) +
  labs(x="ID",y="",fill="Level") +  
  scale_y_continuous(n.breaks=10,labels = scales::label_percent(accuracy = 1))

我希望按照category=="level3"(即图例中的"Serious")的百分比值对ID进行降序排列,理想顺序为1、3、2,请问如何修改上述代码?

解决方案

原代码中reorder(id,-percent)会默认用每个ID对应的所有percent均值排序,不符合需求。我们需要单独提取level3类别的百分比数据,以此为依据指定ID的排序顺序,具体修改如下:

mycolors<-c("#E78AC3","#E5C494","#66C2A5")

library(forcats)
library(dplyr)

# 提取level3类别的百分比数据,用于排序
level3_percent <- df %>% 
  filter(category == "level3") %>% 
  select(id, percent)

# 将ID转换为按level3百分比降序排列的因子
df$id <- factor(df$id, 
                levels = level3_percent %>% arrange(desc(percent)) %>% pull(id))

# 绘制图表
df%>%
  ggplot(aes(x=id,
             y=percent, 
             fill=factor(category,levels=c("level3","level2","level1"))))+
  geom_bar(position="fill",stat="identity") + 
  geom_text(
    data=df,
    aes(y=percent,
        label = ifelse(category == "level3", paste0(percent*100,"%"), "")),
    stat = "identity",
    position = position_stack(vjust = 0.5),size=2.5) +
  scale_fill_manual(values = mycolors,
                    labels=c('Serious', 'Moderate','Normal')) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust=1,size=10)) +
  labs(x="ID",y="",fill="Level") +  
  scale_y_continuous(n.breaks=10,labels = scales::label_percent(accuracy = 1))

关键修改说明

  • 先筛选出category=="level3"的子集,获取每个ID对应的Serious类别百分比
  • 将df$id转换为因子类型,指定levels参数为按Serious百分比降序排列的ID序列
  • 绘图时直接使用处理好的因子型id,无需再调用reorder函数

修改后ID会按照Serious类别的百分比从高到低排列,得到你需要的1、3、2顺序。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:43:21