如何按比例堆叠条形图中Yes占比对ggplot条形进行排序?
按“Yes”占比排序堆叠条形图的方法
你没法直接在ggplot()调用内部完成这种排序,必须先预处理数据计算每组“Yes”的百分比,再用因子重排工具调整thingy的水平顺序,之后再绘图。下面是具体实现方式:
方法一:先预处理计算占比,再重排因子
用dplyr先统计每组“Yes”的占比,再用forcats::fct_reorder()根据这个占比从高到低排序thingy:
library(ggplot2) library(dplyr) library(forcats) demo <- data.frame( thingy = rep(c("cow", "dog", "cat"), c(10, 10, 10)), value = factor(c(rep("Yes", 9), "No", rep("Yes", 7), rep("No", 3), rep("Yes", 0), rep("No", 10)), levels = c("Yes", "No"))) # 预处理:计算每组Yes的占比,并重排thingy的因子水平 demo_processed <- demo |> group_by(thingy) |> summarise(yes_pct = mean(value == "Yes"), .groups = "drop") |> right_join(demo, by = "thingy") |> mutate(thingy = fct_reorder(thingy, yes_pct, .desc = TRUE)) # 绘图 demo_processed |> ggplot(aes(x = thingy, fill = value)) + geom_bar(position = "fill") + scale_fill_manual(values = c("darkred", "darkgray")) + labs(x = NULL, y = NULL) + scale_y_continuous(labels = scales::label_percent())
方法二:在ggplot的aes中直接用fct_reorder结合统计变换
不用单独生成预处理数据框,直接在aes(x = ...)里用fct_reorder,结合after_stat()引用绘图时计算的“Yes”占比,同样能实现排序:
library(ggplot2) library(forcats) demo <- data.frame( thingy = rep(c("cow", "dog", "cat"), c(10, 10, 10)), value = factor(c(rep("Yes", 9), "No", rep("Yes", 7), rep("No", 3), rep("Yes", 0), rep("No", 10)), levels = c("Yes", "No"))) demo |> ggplot(aes(x = fct_reorder(thingy, after_stat(prop), .desc = TRUE), fill = value, group = value)) + geom_bar(position = "fill", stat = "count") + scale_fill_manual(values = c("darkred", "darkgray")) + labs(x = NULL, y = NULL) + scale_y_continuous(labels = scales::label_percent())
这里after_stat(prop)会获取geom_bar计算的每组内比例,因为value的levels优先设为"Yes",所以能直接用这个值排序thingy,得到你想要的cow、dog、cat顺序。
为什么不能纯ggplot内完成?
geom_bar(position="fill")是在绘图阶段动态计算每组比例,但x轴的因子顺序需要在绘图前就确定——ggplot没法在绘图过程中反向调整x轴顺序,所以必须先获取每组“Yes”的占比,再用这个值重排thingy的因子水平。
内容的提问来源于stack exchange,提问作者itsMeInMiami
相关产品推荐
相关产品推荐

