You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot箱线图X轴添加空分组以实现多数据集对比?

问题描述

我们正在对比蛋白质组(proteome)和转录组(transcriptome)两个数据集,二者分组基本匹配,但蛋白质组数据缺少一个分组。为了让两组图表上下排列后便于对比,需要在蛋白质组的ggplot箱线图X轴上显示这个缺失的“空”分组。

尝试实现时因分组为字符型遇到错误:

Error in factor("a", "b", "c", "d", "e"): unused argument ("e")

未找到可行解决方案。


示例数据

当前示例数据生成代码如下(欢迎提供更优方案):

library(tidyverse)

crete_exp_df <- function(gene_nr, sample_nr){
  df <- replicate(sample_nr, rnorm(gene_nr))
  df <- as.data.frame(df)
  colnames(df) <- paste("Sample", c(1:ncol(df)))
  rownames(df) <- paste("Gene", c(1:nrow(df)))
  return(df)
}

df1 <- crete_exp_df(5, 20)

# 样本注释
san <- data.frame(
  id = colnames(df1),
  group = sample(letters[1:4], 20, replace = TRUE))

df1$gene <- rownames(df1)

# 转换为长格式用于箱线图 ----
df_long <- df1 %>% pivot_longer(!gene, names_to = "id", values_to = "value")
df_long$group <- as.factor(san$group[match(df_long$id, san$id)])

# 绘图
df_long %>%
  filter(gene == "Gene 1") %>%
  ggplot(aes(x = group, y = value)) +
  geom_boxplot()

预期效果

预期效果


解决方案

要在X轴显示缺失的分组,核心是强制指定分组因子的所有可能水平,包括那个不存在数据的分组。

步骤1:修正因子水平设置

你之前的错误是因为factor()函数用法有误,正确写法是将目标分组向量作为第一个参数,所有要显示的分组放在levels参数中。比如要添加分组"e",可以这样处理:

# 定义所有需要显示的分组(包括缺失的"e")
all_groups <- c("a", "b", "c", "d", "e")
# 将df_long的group列转换为因子,指定所有水平
df_long$group <- factor(df_long$group, levels = all_groups)

步骤2:绘制包含空分组的箱线图

此时再绘图,X轴会自动包含所有指定的分组,缺失数据的分组会显示为空的位置:

df_long %>%
  filter(gene == "Gene 1") %>%
  ggplot(aes(x = group, y = value)) +
  geom_boxplot() +
  # 可选:调整X轴标签角度,避免重叠
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

额外优化:动态获取完整分组列表

如果不想手动输入所有分组,可以从转录组数据的分组中提取完整列表,再应用到蛋白质组数据上:

# 假设transcriptome_groups是转录组数据的所有分组向量
transcriptome_groups <- c("a", "b", "c", "d", "e")
# 将蛋白质组数据的group因子水平设置为转录组的完整分组
df_long$group <- factor(df_long$group, levels = transcriptome_groups)

这样就能保证两个图表的X轴分组完全一致,方便上下对比。

内容的提问来源于stack exchange,提问作者Sebastian Hesse

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 14:42:06