如何实现ggplot2两个facet分面中boxplot箱线图各自独立重排序
问题原因
你原有代码的排序逻辑是基于全数据集的甲醛中位数计算的,ggplot的分类变量因子水平为全局统一值,默认无法为不同分面设置独立的分类轴排序,可通过以下两种方案解决:
方案1:无额外依赖的基础实现方案
通过拼接传感器名和季节名生成唯一的x轴变量,手动设置因子水平后隐藏标签后缀实现视觉上的分面独立排序:
library(tidyverse) # 1. 数据预处理,生成带排序的拼接变量 DATALL_sort <- DATALL %>% # 按季节+传感器分组计算甲醛中位数 group_by(season, sensor) %>% summarise(med_formaldehyde = median(Formaldehyde), .groups = "drop_last") %>% # 每个季节内按中位数升序排列 arrange(med_formaldehyde, .by_group = TRUE) %>% # 生成传感器+季节的唯一拼接变量,并设置对应因子水平 mutate(sensor_season = factor(paste0(sensor, "_", season), levels = paste0(sensor, "_", season))) %>% ungroup() %>% # 将排序结果关联回原数据集 right_join(DATALL, by = c("season", "sensor")) # 2. 绘图 ggplot(DATALL_sort, aes(x = sensor_season, y = Formaldehyde, fill = sensor)) + geom_jitter(position = position_jitter(width = 0.3, height = 0.2), aes(colour = sensor), alpha = 0.4) + geom_boxplot(outlier.shape = NA) + facet_wrap(~season, scales = "free_x", ncol = 1) + scale_y_continuous(limits = quantile(DATALL$Formaldehyde, c(0.1, 0.98))) + # 去掉x轴标签的季节后缀,仅显示传感器名 scale_x_discrete(labels = ~stringr::str_remove(., "_.+$")) + labs(x = "", y = expression(Formaldehyde~(30~min)~(µg/ m^{3}))) + theme(legend.position = "none")
方案2:使用ggh4x包的简化实现方案
ggh4x是ggplot的拓展包,支持直接为分面设置独立的分类轴水平,代码更简洁:
library(tidyverse) library(ggh4x) ggplot(DATALL, aes(x = sensor, y = Formaldehyde, fill = sensor)) + geom_jitter(position = position_jitter(width = 0.3, height = 0.2), aes(colour = sensor), alpha = 0.4) + geom_boxplot(outlier.shape = NA) + facet_wrap(~season, scales = "free_x", ncol = 1) + # 为每个分面设置独立的x轴排序规则 scale_x_facet( facets = vars(season), levels = ~reorder(.$sensor, .$Formaldehyde, FUN = median) ) + scale_y_continuous(limits = quantile(DATALL$Formaldehyde, c(0.1, 0.98))) + labs(x = "", y = expression(Formaldehyde~(30~min)~(µg/ m^{3}))) + theme(legend.position = "none")
内容的提问来源于stack exchange,提问作者Maria
相关产品推荐
相关产品推荐

