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

ggplot2堆叠百分比条形图中C组a1与a3值异常互换问题

堆叠百分比条形图分组堆叠顺序异常排查与解决

我需要将数据框可视化为堆叠百分比条形图,要求每个柱子的堆叠部分按降序排列。数据已转换为长格式,示例代码如下:

df<- data.frame(ID=c("A","B","C","D","E"),
                a1=c((0.452),(0.558),(0.554),(0.484),(0.661)),
                a2=c((0.326),(0.373),(0.465),(0.434),(0.499)),
                a3=c((0.450),(0.481),(0.613),(0.473),(0.504)),
                a4=c((0.561),(0.681),(0.633),(0.504),(0.723)))

dflong<-df%>%
  pivot_longer(!ID, names_to="aa", values_to="prop")

dflong$ID<-as.factor(dflong$ID)

转换后的数据结构:

# A tibble: 15 × 3
   ID    aa     prop
   <fct> <chr> <dbl>
 1 A     a1    0.452
 2 A     a2    0.326
 3 A     a3    0.45 
 4 A     a4    0.561
 5 B     a1    0.558
 6 B     a2    0.373
 7 B     a3    0.481
 8 B     a4    0.681
 9 C     a1    0.554
10 C     a2    0.465
11 C     a3    0.613
12 C     a4    0.633
13 D     a1    0.484
14 D     a2    0.434
15 D     a3    0.473

使用以下代码绘图后,发现C组的a1(55.4%)和a3(61.3%)堆叠顺序总是互换,尝试过将ID/aa转为因子、重排原始数据框、重启会话、更新RStudio及在GNU R中运行等方法均无效,无错误提示。

dflong %>%
  ggplot(aes(x=ID,y=prop, fill=reorder(aa,-prop))) +
  geom_col(position ="fill", data=dflong%>%filter(ID=="A")) +
  geom_col(position ="fill", data=dflong%>%filter(ID=="B")) +
  geom_col(position ="fill", data=dflong%>%filter(ID=="C")) +
  geom_col(position ="fill", data=dflong%>%filter(ID=="D")) +
  geom_col(position ="fill", data=dflong%>%filter(ID=="E")) +
  geom_text(aes(label=scales::percent(prop)),
            position=position_fill(vjust=.5), size=3, colour="black") +
  scale_y_continuous(labels = NULL, breaks = NULL)+
  scale_fill_brewer(palette="GnBu",
                    name="")+
  coord_flip()+
  theme_minimal()+
  theme(legend.position = "bottom",
        legend.direction = "horizontal") +
  labs(caption="",
       x="",
       y="")

补充:使用多个独立geom_col是为了实现每个柱子单独按降序堆叠,参考相关方案。


问题原因

reorder(aa, -prop)是基于全局所有prop值对aa排序,而非每个ID分组内的局部排序,导致部分分组的堆叠顺序不符合预期。同时,多个geom_col的叠加并未覆盖全局的fill排序规则,反而容易出现层级混乱。

修复方案

先对数据按ID分组,在每个分组内将aa按prop降序排序,然后通过group参数控制堆叠顺序,无需拆分多个geom_col:

# 先对每个ID内的aa按prop降序排序
dflong_sorted <- dflong %>%
  group_by(ID) %>%
  arrange(desc(prop)) %>%
  mutate(aa_sorted = factor(aa, levels = unique(aa))) %>%
  ungroup()

# 绘图
dflong_sorted %>%
  ggplot(aes(x = ID, y = prop, fill = aa, group = aa_sorted)) +
  geom_col(position = "fill") +
  geom_text(aes(label = scales::percent(prop)),
            position = position_fill(vjust = .5), size = 3, colour = "black") +
  scale_y_continuous(labels = NULL, breaks = NULL) +
  scale_fill_brewer(palette = "GnBu", name = "") +
  coord_flip() +
  theme_minimal() +
  theme(legend.position = "bottom", legend.direction = "horizontal") +
  labs(caption = "", x = "", y = "")

说明

  • group_by(ID) %>% arrange(desc(prop)) %>% mutate(aa_sorted = factor(aa, levels = unique(aa))):在每个ID分组内按prop降序排列,将aa转换为对应分组内排序后的因子,保证每个柱子的堆叠顺序是局部降序。
  • 使用group = aa_sorted让ggplot按照每个分组内的排序规则堆叠,fill仍用原始aa保证图例一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 08:15:34