R堆叠柱状图:按指定规则排序柱子与柱内元素
解决堆叠柱状图中分组内元素独立排序的问题
要实现每个公司柱子内的投资者按配额独立排序,核心问题是同一投资者在不同公司的配额不同,全局因子水平无法满足分组内独立排序。你之前用group_by() + fct_reorder()的方法无效,是因为fct_reorder()会修改全局因子水平,ungroup后同一投资者的水平会被统一覆盖。
下面提供两种简洁的解决方法:
方法一:使用forcats::fct_reorder_within(推荐)
fct_reorder_within是forcats包专门用于分组内因子排序的函数,能直接给每个组内的元素设置独立排序:
library(tidyverse) # 加载你的数据集 df1 <- structure(list(Company = structure(c(1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), levels = c("Comp_A", "Comp_B", "Comp_C"), class = "factor"), Company_value = c(100, 100, 200, 200, 200, 60, 60, 60), Investor = structure(c(1L, 2L, 1L, 3L, 4L, 2L, 3L, 5L), levels = c("Inv_1", "Inv_2", "Inv_3", "Inv_4", "Inv_5"), class = "factor"), Investor_quota = c(10, 90, 100, 40, 60, 20, 30, 10)), row.names = c(NA, -8L), class = c("tbl_df", "tbl", "data.frame")) # 数据预处理:先排序公司,再给每个公司内的投资者按配额降序排序 df_processed <- df1 %>% # 按Company_value排序公司柱子 mutate(Company = fct_reorder(Company, Company_value)) %>% # 每个公司内,投资者按Investor_quota降序排序 mutate(Investor = fct_reorder_within(Investor, desc(Investor_quota), Company)) # 绘制堆叠柱状图 ggplot(df_processed, aes(x = Company, y = Investor_quota, fill = Investor)) + geom_col(position = "stack") + # 反转图例,使其与柱子内堆叠顺序一致 scale_fill_discrete(guide = guide_legend(reverse = TRUE)) + labs(x = "公司", y = "投资者配额", title = "公司按价值排序 · 投资者按配额堆叠排序")
方法二:手动创建分组复合因子(通用兼容)
如果不想依赖fct_reorder_within,可以通过创建「公司+投资者」的复合因子,实现分组内独立排序:
library(tidyverse) df_processed <- df1 %>% # 先按Company_value排序公司 mutate(Company = fct_reorder(Company, Company_value)) %>% # 分组后按配额降序排列,创建唯一的分组内因子 group_by(Company) %>% arrange(desc(Investor_quota), .by_group = TRUE) %>% mutate(Investor_grouped = paste(Company, Investor, sep = "_") %>% fct_inorder()) %>% ungroup() # 绘图并调整图例标签 ggplot(df_processed, aes(x = Company, y = Investor_quota, fill = Investor_grouped)) + geom_col(position = "stack") + # 将复合因子的图例标签还原为原投资者名称 scale_fill_discrete(labels = df_processed$Investor, name = "投资者") + labs(x = "公司", y = "投资者配额", title = "公司按价值排序 · 投资者按配额堆叠排序")
关键原理
两种方法的核心都是给每个分组内的元素创建独立的标识/因子水平,避免全局因子水平统一覆盖分组内的排序逻辑,从而实现每个柱子内的投资者按配额独立排序。
内容的提问来源于stack exchange,提问作者Stefano
相关产品推荐
相关产品推荐

