跳到正文
百沐一下百沐一下
本节目录

用公共数据讲好一个科研故事

跟完这篇,您能把一个具体问题,落成「选数据 → 差异 → 预后 → 免疫 / 机制」的一条逻辑链:知道每一环回答什么、用什么证据、和上一环怎么扣起来,最后写出一段前后自洽、就算没做实验也站得住的结果,并且清楚这类分析的边界在哪。

先想清楚:一个能讲的故事长什么样

零实验的公共数据分析,最怕的不是不会跑,而是跑出一堆图却串不成话——差异分析一张、生存曲线一张、免疫热图一张,各说各的,读者看完不知道您到底想说什么。

一个能讲的故事,本质是一条环环相扣的逻辑链:每一步只回答一个小问题,且它的结论正好是下一步的前提。最常用、也最好复现的一条链是这样:

环节回答的问题主要证据承接上一环
现象我的对象(某基因 / 通路)在病与正常之间真有差别吗差异分析、表达箱线图——
重要性这个差别和临床结局有关吗,值不值得看生存曲线、Cox用「有差异」的对象来分组
机制线索它可能通过什么起作用富集、免疫浸润、相关性解释「为什么预后不同」
收口综合起来能提出什么假设一段自洽的论述把前三环并成一句话

把这张表记住,后面每一节就是在填其中一行。注意:这条链给的是「相关证据 + 合理假设」,不是因果证明——这点决定了结尾该怎么写,本文最后一节会专门讲。

第一步:把问题写成一句可检验的假设

故事的起点不是数据,是一句话。含糊的「我想研究基因 X 在肝癌里的作用」没法照着做;把它收敛成一句带对象、带背景、带方向的假设,才知道下一步要什么数据、跑什么分析。

一句好假设通常含三个要素:

  1. 对象——具体到一个基因、一条通路或一个评分(如 GENEX);
  2. 背景——哪个疾病、哪种组织、和谁比(如「肝癌肿瘤组织 vs 癌旁」);
  3. 方向性主张——您预期看到什么(如「高表达、且与更差的总生存相关」)。

拼起来就是一句可检验的话:

GENEX 在肝癌中相对癌旁高表达,其高表达与更差的总生存相关,且可能与肿瘤免疫浸润的改变有关。

这句话本身就是您整条逻辑链的目录:「高表达」对应差异分析,「更差的总生存」对应预后分析,「免疫浸润」对应机制那一环。写不出这样一句话,往往是问题还没想清楚——先补这一步,别急着下载数据。

第二步:按问题选数据,而不是按数据凑问题

有了假设,才谈得上选数据。顺序千万别反:先有问题、再找匹配的数据,而不是先下一套热门数据、再回头看能凑出什么结论——后者做出来的故事往往牵强,也最容易被审稿人看穿。

对着假设,用一张清单核对候选数据集够不够用:

要核对的为什么重要不满足会怎样
有没有您要的分组差异分析需要「病 vs 正常」或「高 vs 低」立不起「现象」这一环
有没有随访信息(time / event预后分析必须要生存数据做不了 KM / Cox,重要性无从谈起
样本量够不够太小则差异、预后都不稳结论偶然性大,验证集易翻车
有没有配套临床信息分期、年龄用于多因素校正无法排除混杂,说服力打折
平台与注释是否清楚关系到能否和其他集比较合并 / 验证时对不齐

还有一条几乎决定成败的原则:至少准备两套数据——一套发现(discovery),一套验证(validation)。只在一套数据里好看的结论,说服力有限;能在独立数据集上重复出来,故事才真正立得住。公共数据里,常见组合是用一个 TCGA 队列做发现、另一个 GEO 数据集做验证。

数据从哪找、关键词怎么写、怎么判断一个 GEO 数据集能不能用,见 GEO 数据库检索入门。下载后怎么整理成「行基因、列样本」的规范矩阵加分组表,见 表达矩阵与分组表整理规范

第三步:差异分析,立起「现象」这一环

链条第一环,是证明您的对象真的在两组间有差别——这是后面一切的地基。用哪个包取决于数据类型:RNA-seq 的 raw counts 用 DESeq2edgeR,芯片或已经标准化的表达量用 limma

以 DESeq2 为例,核心就几行:

library(DESeq2)

dds <- DESeqDataSetFromMatrix(countData = counts,   # 行基因、列样本的 raw counts
                              colData   = coldata,   # 含分组列 condition
                              design    = ~ condition)
dds <- DESeq(dds)
res <- results(dds, contrast = c("condition", "tumor", "normal"))

deg <- subset(as.data.frame(res),
              padj < 0.05 & abs(log2FoldChange) > 1)   # 阈值是常用惯例,非铁律

padj < 0.05|log2FC| > 1(约 2 倍变化)是最常见的惯例、不是铁律:信号弱或样本少时可放宽到 |log2FC| > 0.585(1.5 倍),要按您的数据和领域调,并如实写出用了什么阈值。方法细节见 DESeq2 差异表达分析怎么做对;用哪个包更合适,见 edgeR、limma-voom、DESeq2 怎么选

对讲故事来说,这一环要盯两件事:

  • 您的目标基因在不在差异表里、方向对不对。如果假设说「高表达」,就该看到它 log2FoldChange > 0padj 显著。对不上,别硬掰,回头修假设。
  • 配一张最直观的图。目标基因在两组的表达箱线图,或整体的火山图,是「现象」这一环最好懂的证据。火山图的标准画法见 火山图:差异基因可视化的标准做法

第四步:预后,回答「这个差别重要吗」

有差异,不等于有意义。第二环要说明:这个差异和临床结局挂钩,所以值得看。做法是把样本按目标基因表达高低分两组,比生存。

分组最常用、也最好复现的切法是按表达量中位数

library(survival)
library(survminer)

clin$group <- ifelse(expr["GENEX", ] > median(expr["GENEX", ]),
                     "high", "low")               # 中位数切:简单、事先确定、易复现

fit <- survfit(Surv(time, event) ~ group, data = clin)
ggsurvplot(fit, data = clin, pval = TRUE, risk.table = TRUE)

几点要留心:

  • 中位数是常用惯例、不是铁律。 它简单、事先确定、不看结局,最好复现。也有人用最佳截断(如 survminer::surv_cutpoint),但那是从结局里挑切点,天生偏向让 p 变小、容易高估显著性,用了务必如实说明并在验证集复核。
  • timeevent 的定义要交代清楚:随访时长的单位、结局是总生存(OS)还是无病生存(DFS)。这些是能不能复现的关键。
  • 想控制混杂,上多因素 Cox:把目标基因和分期、年龄一起放进 coxph,看它是不是独立于这些临床因素仍与预后相关。这一步能显著增强说服力。
cox <- coxph(Surv(time, event) ~ group + stage + age, data = clin)
summary(cox)$coefficients        # 看 group 的 HR 与 p,判断是否独立预后因素

KM 曲线怎么读、log-rank 和中位生存怎么写,见 生存分析:KM 曲线与 log-rank 检验;Cox 的单 / 多因素做法见 Cox 回归:单因素与多因素。如果您的对象不是单个基因而是一组,想压成一个风险评分,见 预后 signature 与风险模型

第五步:机制线索,回答「它可能怎么起作用」

前两环讲清了「有差异、且重要」,读者自然会追问:为什么? 第三环给的是机制线索——注意是「线索」不是「机制」,公共数据能提供的是相关性证据,不是通路被激活的直接证明。

两条最常用的路子,可择一或并用:

一、富集分析,看功能层面。 把样本按目标基因高 / 低表达重新分两组,做一次差异分析,再把差异基因拿去做 GO / KEGG 富集,看「目标基因高的样本」整体上哪些通路被带动:

library(clusterProfiler)
library(org.Hs.eg.db)

ego <- enrichGO(gene    = entrez_of_deg,      # 高低组之间的差异基因(转成 ENTREZID)
                OrgDb   = org.Hs.eg.db,
                ont     = "BP",
                pAdjustMethod = "BH",         # 多重检验校正,BH 最常用
                pvalueCutoff  = 0.05)

ORA 与 GSEA 怎么选、气泡图怎么读、怎么不过度解读,见 富集分析:GO / KEGG / GSEA

二、免疫浸润,看微环境。 如果假设涉及免疫,就估计每个样本的免疫细胞构成(CIBERSORT、ssGSEA 等),再看目标基因表达和某类免疫细胞比例是否相关:

# immune 为免疫细胞浸润矩阵(行样本、列细胞类型),来自 CIBERSORT / ssGSEA
cor.test(as.numeric(expr["GENEX", ]),
         immune[, "T cells CD8"],
         method = "spearman")           # 秩相关,对非正态更稳健

浸润怎么估、CIBERSORT 与 ssGSEA 的区别和坑,见 免疫浸润分析:CIBERSORT / ssGSEA

这一环的措辞要格外克制。 相关只能说「相关」「提示」「可能」,不能写成「GENEX 抑制了 CD8 T 细胞浸润」——那是因果句,公共数据支撑不了。守住这条线,恰恰是让分析站得住的关键。

第六步:把三环扣成一条逻辑链

三环都跑完,最后一步是把它们并成一段自洽的话,而不是把三张图并排一贴。检验故事扣没扣紧,用一张「主张 — 证据 — 图」的对照表过一遍:

环节主张(写进正文的一句)支撑证据对应图
现象GENEX 在肿瘤中显著高表达padjlog2FC火山图 / 箱线图
重要性高表达组总生存显著更差,且独立于分期log-rank p、Cox HRKM 曲线
机制线索高表达组富集于某通路,并与 CD8 T 浸润负相关富集 padj、相关 r 与 p气泡图 / 相关图

每一行的「主张」串起来,就是一段合格的结果论述(数字请换成您自己的真实结果):

在发现队列中,GENEX 于肿瘤组织显著高表达(log2FCpadj 达到阈值);按其表达中位数分组,高表达组总生存显著更差(log-rank p),多因素 Cox 提示该差异独立于肿瘤分期。进一步分析显示,高表达组富集于某通路,且 GENEX 表达与 CD8 T 细胞浸润呈负相关(Spearman rp)。上述结果在独立验证队列中方向一致,提示 GENEX 可能通过影响免疫微环境参与该病的不良预后,值得后续实验验证。

注意结尾落在「提示……值得后续实验验证」,而不是「证明」。这既是学术诚实,也让审稿人挑不出「过度解读」的毛病。

第七步:老实交代边界,故事才真站得住

零实验分析最大的软肋,是容易把「相关」讲成「因果」、把「一套数据好看」当成「普遍成立」。主动把边界写清楚,反而让结论更可信。至少交代四件事:

  1. 相关不是因果。 全篇是观察性、关联性证据,不能推断因果与调控方向,需实验(如敲低 / 过表达)验证。这句话该明明白白写进讨论。
  2. 独立验证是底线。 关键结论——尤其是预后——必须在没参与建模的独立数据集上复核,方向一致才算数。只在发现集里显著的,多半靠不住。
  3. 批次与平台差异。 跨数据集比较、合并前要留意批次效应,否则「差异」可能来自平台而非生物学。见 公共数据常见坑与避雷
  4. 注释与研究偏倚。 热门基因、热门通路注释更全,天然更容易「中」;上榜未必等于在您的体系里最关键。

一句话原则:把公共数据分析当成「生成并支撑一个假设」的工具,而不是「盖章一个结论」的工具。它告诉您往哪看、给出多角度的旁证,真正的因果还得靠后续实验。

在平台上跑一遍

以上从选数据、差异、预后到免疫 / 机制这整条链,在百沐一下都不用写代码:上传表达矩阵、分组表和带 time / event 的临床表,用一句话说清您的假设——例如「先看 GENEX 在肿瘤与癌旁的差异,再按其表达中位数分高低组做 KM 和多因素 Cox,最后看它与免疫浸润的相关性,并在验证集复核」——组学智能体会按标准流程逐环分析、出图,并给出可复现的 R 代码;想换阈值、切点或验证方式,直接在对话里说明即可。上手见 组学智能体 · 使用指南智能统计 · 使用指南

相关