Figure 5a — 差异表达基因数量统计

图件说明

代码直接读取 SupplementalTable16 的两个工作表,分别统计全部显著差异基因和 YNM 中显著差异基因的数量,再用双层横向条形图进行展示。

浅灰色 = 全部显著差异基因;深灰色 = YNM 显著差异基因。

因此,这一图并不依赖重新做原始差异分析,而是基于作者已公开的统计结果进行再汇总和再绘图。

复现代码

Code
library(dplyr)
library(tidyr)
library(readxl)
library(ggplot2)
library(tibble)
library(purrr)

# 读取 SupplementalTable16
tbl16_path <- "data/SupplementalTable16.xls"

read_t16 <- function(sheet_name) {
  readxl::read_excel(
    tbl16_path,
    sheet = sheet_name,
    col_types = "text",
    na = c("", "NA", "N/A")
  )
}

t16_all <- read_t16("a. Significant DE Genes")
t16_ynm <- read_t16("b. YNM DE Genes")

# 数据集定义
dataset_defs <- list(
  tga1tga4 = list(
    logfc = c("tga1tga4.tga1tga4.logFC", "tga1tga4.KNO3.logFC"),
    padj  = c("tga1tga4.adj.P.Val")
  ),
  chl1 = list(
    logfc = c("chl1.9.logFC", "chl1.12.logFC", "chl1.5.logFC"),
    padj  = c("chl1.9.adj.P.Val", "chl1.12.adj.P.Val", "chl1.5.adj.P.Val")
  ),
  anr1 = list(
    logfc = c("anr1.logFC"),
    padj  = c("anr1.adj.P.Val")
  ),
  nia1nia2 = list(
    logfc = c("nia1nia2.logFC"),
    padj  = c("nia1nia2.adj.P.Val")
  ),
  glu1 = list(
    logfc = c("glu1_root.logFC", "glu1_leaf.logFC"),
    padj  = c("glu1_root.adj.P.Val", "glu1_leaf.adj.P.Val")
  ),
  bzip1 = list(
    logfc = c("bzip1.logFC"),
    padj  = c("bzip1.adj.P.Val")
  ),
  nrt2_4 = list(
    logfc = c("nrt2.4.logFC"),
    padj  = c("nrt2.4.adj.P.Val")
  ),
  nin7_1 = list(
    logfc = c("nin7.1.logFC"),
    padj  = c("nin7.1.adj.P.Val")
  ),
  nlp6_sup = list(
    logfc = c("nlp6_sup14.logFC", "nlp6_sup7.logFC"),
    padj  = c("nlp6_sup14.adj.P.Val", "nlp6_sup7.adj.P.Val")
  ),
  nlp6nlp7 = list(
    logfc = c("nlp6nlp7_t10.logFC", "nlp6nlp7_t20.logFC"),
    padj  = c("nlp6nlp7.adj.P.Val")
  ),
  nlp7_1 = list(
    logfc = c("nlp7.1_t10.logFC", "nlp7.1_t20.logFC"),
    padj  = c("nlp7.1.adj.P.Val")
  ),
  nlp7_3 = list(
    logfc = c("nlp7.3_t10.logFC", "nlp7.3_t20.logFC"),
    padj  = c("nlp7.3.adj.P.Val")
  ),
  gdh_triple = list(
    logfc = c("gdh1gdh2gdh3.logFC"),
    padj  = c("gdh1gdh2gdh3.adj.P.Val")
  )
)

dataset_order <- c(
  "tga1tga4", "chl1", "anr1", "nia1nia2", "glu1",
  "bzip1", "nrt2_4", "nin7_1", "nlp6_sup",
  "nlp6nlp7", "nlp7_1", "nlp7_3", "gdh_triple"
)

# 辅助函数
to_num <- function(x) suppressWarnings(as.numeric(x))

build_long_table16 <- function(df, defs) {
  long_list <- purrr::imap(defs, function(def, nm) {
    logfc_m <- sapply(def$logfc, function(cc) to_num(df[[cc]]))
    padj_m  <- sapply(def$padj, function(cc) to_num(df[[cc]]))
    if (is.vector(logfc_m)) logfc_m <- matrix(logfc_m, ncol = 1)
    if (is.vector(padj_m)) padj_m <- matrix(padj_m, ncol = 1)

    tibble::tibble(
      agi = df[["AGI"]],
      gene = ifelse(
        is.na(df[["Gene Name"]]) | df[["Gene Name"]] == "",
        df[["AGI"]],
        df[["Gene Name"]]
      ),
      dataset = nm,
      logFC = apply(logfc_m, 1, function(z) { z <- z[!is.na(z)]; if (length(z)==0) NA_real_ else mean(z) }),
      adj.P.Val = apply(padj_m, 1, function(z) { z <- z[!is.na(z)]; if (length(z)==0) NA_real_ else min(z) })
    )
  })
  dplyr::bind_rows(long_list)
}

all_long <- build_long_table16(t16_all, dataset_defs)
ynm_long <- build_long_table16(t16_ynm, dataset_defs)

count_all <- all_long %>%
  group_by(dataset) %>%
  summarise(n_all = sum(!is.na(adj.P.Val) & adj.P.Val < 0.05), .groups = "drop")

count_ynm <- ynm_long %>%
  group_by(dataset) %>%
  summarise(n_ynm = sum(!is.na(adj.P.Val) & adj.P.Val < 0.05), .groups = "drop")

count_df <- full_join(count_all, count_ynm, by = "dataset") %>%
  mutate(
    n_all = ifelse(is.na(n_all), 0, n_all),
    n_ynm = ifelse(is.na(n_ynm), 0, n_ynm)
  ) %>%
  mutate(dataset = factor(dataset, levels = dataset_order)) %>%
  arrange(desc(n_all))

ggplot(count_df, aes(x = dataset)) +
  geom_col(aes(y = n_all), fill = "grey85", width = 0.75) +
  geom_col(aes(y = n_ynm), fill = "grey35", width = 0.45) +
  coord_flip() +
  theme_bw(base_size = 12) +
  labs(
    title = "不同扰动背景下差异表达基因数量",
    subtitle = "浅灰色 = 全部显著差异基因;深灰色 = YNM 显著差异基因",
    x = NULL,
    y = "基因数量"
  )

Figure 5a-style: 不同扰动背景下差异表达基因数量统计

难度评估:中等

主要难点在于正确理解 SupplementalTable16 中各数据集的 logFC 与 adjusted P value 字段,并保持与原文一致的显著性判定阈值。相对于 Fig. 1a、1b、4a,这一图的复现更偏向数据整理与可视化实现。