ggplot2分组条形图中因子顺序失效问题求助
问题描述
尝试用ggplot2绘制分组条形图,希望每个日期分组内的条形按count值排序,但ggplot2似乎忽略了因子水平,无法实现预期效果。可复现代码如下:
library(ggplot2) library(dplyr) library(forcats) set.seed(42) daily_data <- expand.grid( date = seq.Date(from = as.Date("2024-01-01"), to = as.Date("2024-01-10"), by = "1 day"), location = c("West", "East", "North") ) %>% mutate(count = sample(10:100, size = n(), replace = TRUE)) daily_data <- daily_data %>% group_by(date) %>% mutate(location = fct_reorder2(location, date, count)) %>% ungroup() p <- ggplot(daily_data, aes(x = factor(date), y = count, fill = location)) + geom_col(stat = "identity", position = "dodge") + theme(axis.text.x = element_text(angle = 45, hjust = 1)) print(p)
已尝试方法:
- 使用
factor()手动设置因子水平 - 在
mutate调用及aes()的fill参数中使用fct_reorder()和fct_reorder2()
解决方案
核心问题在于:ggplot2中分组条形的顺序由全局因子水平决定,group_by()后用fct_reorder()只能在组内临时排序,无法保留每组独立的顺序。要实现每个日期组内按count排序,需创建包含date和location的交互变量,按count排序后作为x轴变量,再调整x轴标签显示日期即可。
修改后的完整代码:
library(ggplot2) library(dplyr) library(forcats) set.seed(42) daily_data <- expand.grid( date = seq.Date(from = as.Date("2024-01-01"), to = as.Date("2024-01-10"), by = "1 day"), location = c("West", "East", "North") ) %>% mutate(count = sample(10:100, size = n(), replace = TRUE)) # 创建date和location的交互变量,按count降序排序(.desc=TRUE改为FALSE可实现升序) daily_data <- daily_data %>% group_by(date) %>% mutate(date_loc = fct_reorder(interaction(date, location), count, .desc = TRUE)) %>% ungroup() p <- ggplot(daily_data, aes(x = date_loc, y = count, fill = location)) + geom_col(stat = "identity") + # 将x轴标签还原为原始日期,去掉交互变量中的location后缀 scale_x_discrete(labels = function(x) gsub("\\..*", "", x)) + theme(axis.text.x = element_text(angle = 45, hjust = 1)) print(p)
原理说明
interaction(date, location)将日期和地点合并为唯一组合变量,对应每个独立条形fct_reorder(..., count, .desc = TRUE)让每个日期组内的条形按count值降序排列scale_x_discrete(labels = ...)把x轴标签还原为原始日期,避免显示交互变量的冗余后缀
内容的提问来源于stack exchange,提问作者Sam Swanson
相关产品推荐
相关产品推荐

