如何用ggplot绘制含两个x列、两个y列的分组箱线图
问题核心拆解
你现在没法用现成的gather代码出图的根本原因,是表结构和常规gather适配的场景不匹配:
常规gather方法适合的场景是「同一个X分组列下,并排多个Y变量」(比如单独一个Ocean.region列,对应MetaT、MetaG两个Y列);但你现在的原始表,是两套独立的X-Y观测序列横向拼接出来的:
- 第一组观测:X变量是
Ocean.regionT,对应Y值是MetaT - 第二组观测:X变量是
Ocean.regionG,对应Y值是MetaG
而且你提到Ocean.regionG/MetaG的有效长度短于另外两列,说明横向对齐的时候存在空值错位,直接硬拉平整表,不仅会打乱本来的配对关系,还会把长度不齐带来的空值错配带进后续绘图。
具体实现逻辑
核心思路是不要硬拉平整表,而是先把两套独立的X-Y配对序列拆出来,各自整理成统一格式的长表,再合并:
- 分别把两组配对的列单独拆出,统一列名后新增分组标识,单独删掉每组内部的空值(这一步就自动解决了你提到的两列长度不齐的问题,因为短列对应的空值会在本组内过滤,不会把另一组长列的有效观测删掉)
- 把两个整理好的长表按统一列名上下拼接,得到适合ggplot绘图的tidy格式
- 直接按常规分组箱线图的语法绘图
library(tidyverse) # 拆分第一组配对序列:Ocean.regionT + MetaT df_T <- BB %>% select(Ocean_region = Ocean.regionT, KO_Values = MetaT) %>% mutate(Data_Type = "MetaT") %>% drop_na() # 仅过滤本组内的空值,不影响另一组的有效数据 # 拆分第二组配对序列:Ocean.regionG + MetaG df_G <- BB %>% select(Ocean_region = Ocean.regionG, KO_Values = MetaG) %>% mutate(Data_Type = "MetaG") %>% drop_na() # 自动过滤长度不齐带来的空值行 # 上下合并为统一的长表,转换分类变量为因子 BB_tidy <- bind_rows(df_T, df_G) %>% mutate( Ocean_region = as.factor(Ocean_region), Data_Type = as.factor(Data_Type) ) # 绘制分组箱线图 ggplot(BB_tidy, aes(x = Ocean_region, y = KO_Values, fill = Data_Type)) + geom_boxplot(outlier.size = 0.5) + scale_fill_brewer(palette = "Set1") + scale_y_log10() + theme_bw()
容易踩的坑
- 不要直接对四列全表做gather拉平:比如直接把
Ocean.regionT/Ocean.regionG作为key列、MetaT/MetaG作为value列拉成两列,会完全打乱“T的X配T的Y、G的X配G的Y”的对应关系,画出来的箱线图分组和数值是错配的 - 空值过滤要放在每组拆分后单独做,不要在原表上一次性过滤:如果某一行里
Ocean.regionG是空,但Ocean.regionT是有有效观测的,在原表上整行删空值,会把本来有效的MetaT观测直接丢掉 - 示例数据里存在同个区域命名不一致的情况(比如
Ocean.regionT的Madagascar对应Ocean.regionG的MS),绘图前可以统一一下命名规则,避免x轴上出现只有单个数据组的空分组
内容的提问来源于stack exchange,提问作者MarineBioStudent
相关产品推荐
相关产品推荐

