如何在ggplot中基于Total的Number值降序排列X轴?
解决ggplot条形图按指定类别数值排序的问题
需求说明
现有boxchart3数据集,已用ggplot绘制分组条形图,需将经coord_flip()翻转后的Y轴(对应原X轴的Treatment),基于Type为'Total'的Number值按降序(从高到低)排列。
数据集
boxchart3 <- structure(list(Treatment = c("Referral to secondary care", "Watchful waiting", "Watchful waiting", "Referral to secondary care", "Post operation: control", "Injection (corticosteroid)", "Post operation: removing sutures", "Additional examination", "Post operation: control", "Prescription for pain medication", "Additional examination", "To plan a physical contact", "Injection (corticosteroid)", "Post operation: removing sutures", "Referral to paramedical care", "Prescription for pain medication", "To plan a physical contact", "Referral to paramedical care", "Prescription for antibiotics or prednison", "Prescription for antibiotics or prednison", "Prescription for cutane creme", "Prescription for cutane creme"), Type = c("Total", "Total", "Sensitivity Analysis", "Sensitivity Analysis", "Total", "Total", "Total", "Total", "Sensitivity Analysis", "Total", "Sensitivity Analysis", "Total", "Sensitivity Analysis", "Sensitivity Analysis", "Total", "Sensitivity Analysis", "Sensitivity Analysis", "Sensitivity Analysis", "Total", "Sensitivity Analysis", "Total", "Sensitivity Analysis" ), Number = c(1540L, 1434L, 732L, 591L, 175L, 124L, 122L, 87L, 67L, 56L, 54L, 53L, 51L, 47L, 38L, 29L, 26L, 15L, 13L, 9L, 7L, 3L), Percentage = c(37.6804502079765, 35.0868607780768, 40.5764966740577, 32.7605321507761, 4.28186934181551, 3.03401027648642, 2.98507462686567, 2.12870075850257, 3.7139689578714, 1.37019818938096, 2.99334811529933, 1.29679471494984, 2.82705099778271, 2.60532150776053, 0.929777342794226, 1.60753880266075, 1.44124168514412, 0.831485587583148, 0.318081722534867, 0.498891352549889, 0.171274773672621, 0.16629711751663)), row.names = c(NA, -22L), class = "data.frame")
当前绘图代码
box <- ggplot(boxchart3) + geom_bar( aes(x = reorder(Treatment, Number), y=Percentage, fill = Type, group = Type), stat = "identity", position = "dodge") + geom_text( aes(x=reorder(Treatment, Number), y= Percentage, label =Number, group = Type), hjust = -0.25, size =2.3, position = position_dodge(width = 1), inherit.aes = TRUE) + coord_flip() + theme_minimal() + theme(legend.position = "bottom", legend.title = element_blank(), legend.text = element_text(color = "gray33"), axis.text.x = element_text(angle = 45, vjust = 0.5, color = "gray33"), axis.text.y = element_text(color = "gray33"), axis.title = element_text(color = "gray33"), panel.grid.major.x = element_blank()) + labs(y = "Percentage (%)", x = "Treatment")
无效尝试
以下两种方法未达到预期效果:
1.
boxchart3 <- boxchart3 %>% mutate(Treatment = reorder(Treatment, -ifelse(Type == 'Total', Number, 0), FUN = sum)) |> arrange(Treatment)
boxchart3<- boxchart3 %>% arrange(fct_reorder2(as.factor(Treatment2), Number, Type, .fun = \(x, y) x[y == 'Total']))
有效解决方案
方案一:预处理数据集,将Treatment转为有序因子
先提取每个Treatment对应Total组的Number值作为排序依据,把Treatment转为按该值降序排列的因子:
library(dplyr) library(forcats) # 获取每个Treatment的Total组Number值 sort_values <- boxchart3 %>% filter(Type == "Total") %>% select(Treatment, Number) # 将Treatment转为按Total组Number降序的因子 boxchart3 <- boxchart3 %>% left_join(sort_values, by = "Treatment", suffix = c("", "_total")) %>% mutate(Treatment = fct_reorder(Treatment, -Number_total)) %>% select(-Number_total)
修改绘图代码的x参数为Treatment(此时已为有序因子):
box <- ggplot(boxchart3) + geom_bar(aes(x = Treatment, y = Percentage, fill = Type, group = Type), stat = "identity", position = "dodge") + geom_text(aes(x = Treatment, y = Percentage, label = Number, group = Type), hjust = -0.25, size = 2.3, position = position_dodge(width = 1), inherit.aes = TRUE) + coord_flip() + theme_minimal() + theme(legend.position = "bottom", legend.title = element_blank(), legend.text = element_text(color = "gray33"), axis.text.x = element_text(angle = 45, vjust = 0.5, color = "gray33"), axis.text.y = element_text(color = "gray33"), axis.title = element_text(color = "gray33"), panel.grid.major.x = element_blank()) + labs(y = "Percentage (%)", x = "Treatment")
方案二:直接在ggplot中指定排序逻辑
无需预处理数据集,在reorder函数中仅使用Total组的Number值作为排序依据:
box <- ggplot(boxchart3) + geom_bar(aes(x = reorder(Treatment, -ifelse(Type == "Total", Number, NA), na.rm = TRUE), y = Percentage, fill = Type, group = Type), stat = "identity", position = "dodge") + geom_text(aes(x = reorder(Treatment, -ifelse(Type == "Total", Number, NA), na.rm = TRUE), y = Percentage, label = Number, group = Type), hjust = -0.25, size = 2.3, position = position_dodge(width = 1), inherit.aes = TRUE) + coord_flip() + theme_minimal() + theme(legend.position = "bottom", legend.title = element_blank(), legend.text = element_text(color = "gray33"), axis.text.x = element_text(angle = 45, vjust = 0.5, color = "gray33"), axis.text.y = element_text(color = "gray33"), axis.title = element_text(color = "gray33"), panel.grid.major.x = element_blank()) + labs(y = "Percentage (%)", x = "Treatment")
失败原因说明
- 第一种尝试中,虽修改了Treatment的因子顺序,但绘图代码仍使用
reorder(Treatment, Number),覆盖了预先设置的排序; - 第二种尝试中使用了不存在的变量
Treatment2,导致逻辑失效。
内容的提问来源于stack exchange,提问作者RvS
相关产品推荐
相关产品推荐

