欢迎来到《细胞生物学方向 · 生物信息学课题教程》!这是一份专门为零基础新手设计的完整入门指南。学完这份教程,你将能独立完成一个“用公共数据库做细胞生物学方向生信课题”的完整项目——从选题、下载数据、统计分析、画图,到把它写成一篇可以投稿的论文。
| 你是谁 | 你会得到什么 |
|---|---|
| 生物/医学本科生 | 一套能写进毕业论文或发表成小论文的完整课题流程 |
| 低年级研究生 | 细胞生物学 × 生物信息学交叉研究的第一块敲门砖 |
| 跨专业学习者(计算机/数学背景) | 快速补齐细胞生物学常识,理解生信问题的生物学意义 |
| 想转型生信的实验科研人员 | 一套不需要自己测序、用公共数据就能出成果的路线 |
你不需要:会编程(我们从 R 的第一行命令教起)、懂高深统计(每个概念都用大白话+类比讲透)、有实验数据(全部使用公共数据库)。
我们不讲空洞的理论,而是带着你做一个真实的、可发表的课题:
《基于公共数据库的细胞焦亡相关基因在肝细胞癌中的预后价值与免疫微环境分析》
| 周次 | 内容 | 章节 | 产出 |
|---|---|---|---|
| 第 1 周 | 细胞生物学基础 + 生信知识补充 | 01、02 | 看懂机制图;装好 R/RStudio |
| 第 2 周 | 数据库认知 + 选题定案 + 环境搭建 + 数据下载 | 03、04、05、06 | 确定课题;数据到手 |
| 第 3 周 | 差异表达分析 + 可视化 | 07、08 | 火山图、热图、PCA |
| 第 4 周 | 功能富集 + PPI 网络 | 09、10 | 富集气泡图、hub 基因列表 |
| 第 5 周 | 生存分析 + 风险模型 + 独立验证 | 11、12 | KM 曲线、森林图、ROC、验证结果 |
| 第 6 周 | 论文写作 + 投稿准备 | 13、14、15 | 论文初稿 |
时间弹性:急于出结果的读者可以跳过第 01-02 章直接开跑(遇到概念再回头查); 想扎实打基础的读者可以放慢到 8 周。第 15 章附录的术语表随时可查。
code/
目录有整理好的完整脚本)。教程中的图均为示例图/示意图(用模拟数据绘制,演示图形样式与解读方法)——你用真实数据跑通后会得到属于自己的图。细胞生物学常识(01) 统计与 R 基础(02)
│ │
└──────────┬─────────────────┘
▼
公共数据库(03)── 选题设计(04)── 环境搭建(05)
│
▼
数据获取(06)
│
┌──────────┼──────────┐
▼ ▼ ▼
差异表达(07) 可视化(08) 富集分析(09)
│ │ │
└──────────┼──────────┘
▼
PPI 与 hub 基因(10)
│
▼
生存分析与风险模型(11)
│
▼
独立验证与拓展(12)
│
▼
论文写作与发表(13)+ FAQ(14)+ 附录(15)
准备好了吗?让我们从“细胞生物学”这门看家学问开始,一步步把基因表达的奥秘变成你可以发表的数据故事。
本章为零基础读者补齐“细胞生物学”这层背景知识。目标不是背书,而是让后续章节里“焦亡基因 × 肝癌”的每一个名词都听得懂:细胞、基因表达、细胞死亡、焦亡机制、肿瘤微环境。请带着“这些概念将来会变成哪张数据表”的想法来读。
细胞(cell)是生命的基本单位:所有生物——从细菌到人体——都由细胞构成。细胞内部独立完成新陈代谢(metabolism),储存并传递遗传信息,对外界信号做出反应;多细胞生物的身体,就是无数细胞分工协作的“城市”。人体大约由数十万亿个细胞组成(数量级在 10¹³ 上下,具体数值随估计方法不同有差异,记住数量级即可),其中肝脏主要由肝细胞(hepatocyte)构成——它正是本教程的主角之一。
细胞生物学(cell biology)研究细胞的结构、功能与行为:细胞膜与各种细胞器如何分工(线粒体供能、内质网合成蛋白质、溶酶体降解废物);细胞如何增殖(proliferation)、分化(differentiation)、通讯(即信号转导,signal transduction);以及最重要的——细胞如何决定自己的生死。
“死亡”听起来是终点,但细胞死亡其实是发育、免疫和肿瘤中反复登场的核心角色:胚胎手指间多余的细胞要靠死亡“雕刻”出来;被病毒感染的细胞要靠死亡被清除;而癌细胞恰恰是“拒绝死亡”的细胞。本章后面会看到:细胞“怎么死”“死得是否体面”,会直接决定一个肿瘤的命运。
中心法则(central dogma of molecular biology)是分子生物学的“宪法”:遗传信息从 DNA 流向 RNA(这一步叫转录,transcription),再从 RNA 流向蛋白质(这一步叫翻译,translation)。我们可以这样类比:基因(gene)是 DNA 上的一段功能片段,相当于说明书里的一个“章节”;mRNA(信使 RNA,messenger RNA)是章节的“复印件”;蛋白质则是照着复印件“生产出来、真正干活的人”。
关键问题来了:细胞如何控制某个基因“读得有多勤”?答案就是基因表达(gene expression)的强度——转录出的 mRNA 越多,通常说明该基因越活跃。这里必须严谨地补充一句:mRNA 数量并不严格等于蛋白质数量(还存在转录后调控、翻译效率、蛋白质降解等环节),但在高通量测序的尺度上,mRNA 水平是最常用、最可测的“表达量代理指标”。本教程里说“基因 A 在肿瘤里高表达”,指的就是“基因 A 的 mRNA 在肿瘤样本里更多”。
转录组测序(RNA-seq,即 RNA sequencing)如何测量表达量?流程大致是:从样本中提取总 RNA → 利用 polyA 尾巴富集 mRNA → 逆转录成更稳定的 cDNA → 片段化并加上测序接头(adapter)→ 上机测序得到海量短读段(reads)→ 把 reads 比对(alignment)到参考基因组 → 统计每个基因被“覆盖”了多少次。这个计数就是最原始的“表达量”。整个过程见图 02。
图 02 为教学示意图(模拟绘制,仅演示概念),左侧展示 DNA→mRNA→蛋白质的信息流向,右侧展示 RNA-seq 如何把 mRNA 变成数字读段计数。读者用真实数据跑出的是自己的图。
细胞死亡不是一个词,而是一个“大家族”。粗略可分为两大类:意外死亡(如坏死)与程序性死亡(regulated cell death,受基因精确调控的死亡)。五种最常见的死亡方式对比如下(图 03 为示意图):
| 死亡方式 | 英文 | 核心机制 | 形态特征 | 是否引发炎症 |
|---|---|---|---|---|
| 凋亡 | apoptosis | 半胱天冬酶(caspase)级联,细胞“自我拆解” | 细胞皱缩、膜出泡、形成凋亡小体,被吞噬清除 | 通常不引发(“安静地死”) |
| 坏死 | necrosis | 意外损伤(缺氧、物理/化学损伤)导致膜破裂 | 细胞肿胀、膜破裂、内容物泄漏 | 强烈(“爆炸式死”) |
| 焦亡 | pyroptosis | gasdermin 家族蛋白在细胞膜上打孔 | 膜穿孔、细胞肿胀破裂 | 强烈促炎(“边死边喊救兵”) |
| 铁死亡 | ferroptosis | 铁依赖性脂质过氧化 | 线粒体变小、膜完整性尚存 | 可引发 |
| 自噬性死亡 | autophagic cell death | 自噬(autophagy)过度激活 | 大量自噬体/自噬溶酶体堆积 | 较弱 |
这里有两处需要严谨说明:其一,自噬本身通常是细胞的“自救机制”(把受损的细胞器回收再利用),只有过度或失控的自噬才会导致死亡;其二,凋亡与焦亡虽然都属于程序性死亡,关键区别在于“死法是否安静”——凋亡是拆卸后打包送走,不惊动免疫系统;焦亡是打孔炸开,同时释放促炎因子,相当于“边死边喊救兵”。
图 03 为教学示意图(模拟绘制),仅用于直观对比五种死亡方式的形态与炎症特征,不代表任何真实实验数据。
为什么焦亡近年成为研究热点?主要有三个原因。第一,机制清晰化:2015 年邵峰团队在 Nature 杂志报道 gasdermin D(GSDMD)是焦亡的关键执行蛋白,焦亡从此从“现象”变成“可操作的分子通路”;第二,疾病相关性:焦亡是感染与炎症性疾病的重要推手,也与肿瘤关系密切;第三,转化价值:gasdermin(GSDM)家族蛋白本身成为药物靶点与生物标志物的候选。对肿瘤免疫尤其重要的是:焦亡是一种“免疫原性”很强的死亡方式,理论上可以把“没人理”的冷肿瘤变成“被免疫系统围攻”的热肿瘤——这直接关系到第 5 节的肝癌话题。
焦亡(pyroptosis)的严谨定义:由 gasdermin 家族蛋白介导的、伴随强烈炎症反应的程序性坏死样细胞死亡(lytic cell death)。“坏死样”指细胞最终会破裂(lysis),“程序性”指它由特定蛋白精确执行,而不是意外事故。
经典通路(canonical pathway,图 04 左半),一条“报警→点火→爆破→呼救”的流水线:
非经典通路(non-canonical pathway,图 04 右半):人源的 caspase-4、caspase-5(小鼠中对应为 caspase-11)能直接识别进入胞质的脂多糖(LPS,革兰氏阴性菌外膜成分),被激活后同样裂解 GSDMD 打孔,并间接激活 NLRP3/caspase-1 通路,进一步放大炎症。
图 04 为教学示意图(模拟绘制),仅示意经典与非经典两条通路的骨架,省略了大量辅助蛋白细节(如 ASC 接头蛋白等),教学目的而非完整分子图谱。
GSDM 家族还包括 GSDMA、GSDMB、GSDMC、GSDME 等成员。其中 GSDME 能被“凋亡执行者”caspase-3 裂解——这解释了为什么某些化疗药物会诱导肿瘤细胞发生焦亡样死亡。对初学者而言,先把 GSDMD 这条主线记牢即可。
肝细胞癌(hepatocellular carcinoma, HCC)是最常见的原发性肝癌类型(约占 75%–85%),也是全球癌症相关死亡的主要原因之一。主要危险因素包括:慢性乙型肝炎病毒(HBV)或丙型肝炎病毒(HCV)感染、酒精性肝病、非酒精性脂肪性肝病(NAFLD,现常称代谢相关脂肪性肝病 MASLD)以及黄曲霉毒素暴露。中国是 HBV 相关性肝癌的高发国家,HCC 因此是国内肿瘤研究的热点。
肿瘤并不只是“一堆疯狂增殖的细胞”。著名肿瘤学家 Hanahan 与 Weinberg 提出“癌症的标志”(hallmarks of cancer),包括:持续增殖信号、逃避生长抑制、抵抗细胞死亡、无限复制潜能、诱导血管生成、激活侵袭转移、重编程能量代谢、逃避免疫摧毁等。注意“抵抗细胞死亡”是其中的标志之一——癌细胞的“抗死能力”是它猖獗的根源,这反过来提示:诱导肿瘤细胞“以正确的方式死亡”(比如焦亡),是潜在的治疗思路。
肿瘤微环境(tumor microenvironment, TME)是肿瘤细胞周围的“小社会”:包括免疫细胞(CD8+ T 细胞、调节性 T 细胞、肿瘤相关巨噬细胞 TAM、NK 细胞等)、成纤维细胞(CAF)、血管内皮细胞、细胞外基质与各类细胞因子。打个比方:免疫细胞是“警察”,肿瘤细胞是“罪犯”,TME 就是警匪之间的博弈场。通常,CD8+ T 细胞浸润多、免疫活跃的肿瘤(俗称“热肿瘤”)预后相对较好,对免疫检查点抑制剂(如 PD-1/PD-L1 抗体)的响应率也更高;而免疫细胞稀少、“冷冰冰”的肿瘤(“冷肿瘤”)则更难被免疫系统清除。
为什么“焦亡 × 肝癌”有临床意义?第一,HCC 对传统化疗不敏感,免疫治疗(如 PD-1/PD-L1 抑制剂联合抗血管生成药物)虽已进入一线,但仍有相当比例的患者不响应;第二,焦亡释放损伤相关分子模式(DAMPs,damage-associated molecular patterns)和 IL-1β/IL-18,能招募并激活免疫细胞,有潜力把“冷”肝癌变成“热”肝癌,增强抗肿瘤免疫;第三,焦亡基因的表达水平可以作为生物标志物(biomarker),帮助预测患者预后或免疫治疗响应;第四,也是本教程最实际的——TCGA-LIHC 与 GSE14520 等公共数据库里就有肝癌患者的表达谱与生存数据,“焦亡基因在肝癌中表达是否异常、哪些与预后相关”这个问题可以完全用公开数据回答。这正是本教程示例课题要做的事。
本章为零基础读者补齐“生物信息学”这层知识:生信是什么、RNA-seq 数据长什么样、新手最容易卡住的统计学概念,以及 R 语言的第一行代码。学完本章,你应该能看懂后续章节里“limma 差异分析”“FDR 校正”“KM 生存曲线”“ROC”这些词,并亲手跑出第一个 R 脚本。
把细胞想象成一座图书馆:基因组(genome)是全部藏书——人类基因组约有 30 亿个碱基对(base pair, bp),相当于一套 23 本“巨著”(23 对染色体);基因是书里的“章节”;mRNA 是章节的“复印本”;蛋白质是读者拿走复印本后做出来的“成品”。传统生物学家像“手抄员”,一页一页读;高通量测序(high-throughput sequencing)则像一次性把整座图书馆扫描成电子版——一次实验产生 TB 级(1 TB ≈ 10¹² 字节)的数据,人类不可能逐行阅读。
生物信息学(bioinformatics)就是“海量图书的智能检索与统计”:用计算机与统计学方法,从海量生物学数据中提取规律。它能做的事包括:序列比对与基因组注释、基因表达定量、差异表达分析(找出两组样本中显著变化的基因)、功能富集分析(这些基因属于哪些通路)、生存分析(哪些基因与患者生存相关)、预后模型构建(用多个基因预测患者风险),以及公共数据库挖掘(把别人已发表的数据拿来回答自己的问题)。
本教程走的是最后一种模式——“dry lab”(纯计算实验),不需要自己做湿实验。这正是公共数据库时代给零基础新手打开的大门:你不需要一台测序仪,也能完成一个完整的课题。
RNA-seq 的标准流程:样本(肿瘤/癌旁组织)→ 提取 RNA → 建库(逆转录成 cDNA、加接头)→ 高通量测序产生读段(reads)→ 质控(去除低质量读段与接头)→ 比对(alignment)到参考基因组/转录组 → 定量(统计每个基因被多少读段覆盖)→ 得到表达矩阵。整体见图 02(示意图):左侧是中心法则,右侧是测序把 mRNA 变成数字的过程。
图 02 为教学示意图(模拟绘制),仅演示“中心法则 + 测序定量”的概念流程,不代表任何真实实验数据。
测序得到的原始计数叫 counts(读段计数):每个基因被多少条 read 命中。counts 是整数,但它同时受两个因素干扰:基因越长越容易被命中(长度偏差);测序越深、所有基因的计数一起变高(文库大小偏差)。因此需要归一化(normalization)才能比较:
表达矩阵(expression matrix)长什么样?一张表:行是基因(人类约 2 万个蛋白编码基因),列是样本(TCGA-LIHC 约 371 个肿瘤样本 + 50 个癌旁样本),单元格是表达量数字。示意如下:
| 基因 | TCGA-XX-0001(肿瘤) | TCGA-XX-0002(肿瘤) | … | TCGA-XX-00NN(癌旁) |
|---|---|---|---|---|
| GSDMD | 8.21 | 7.94 | … | 5.12 |
| NLRP3 | 4.05 | 4.66 | … | 2.30 |
第一列通常是基因名(gene symbol,如 GSDMD)或 Ensembl ID,后续每列对应一个样本。之后所有分析(差异、富集、生存)都在这张表上展开。补充一点:TCGA 的 RNA-seq 数据提供 FPKM/FPKM-UQ 等归一化值,而 GEO 中有些队列(如 GSE14520)用的是表达芯片(microarray),单位是荧光信号强度而非读段计数——第 06 章会具体处理。
生信里 90% 的数据都是“表格”,最常见的两种纯文本格式:
两者都可以用 Excel/WPS 打开,但文件很大时强烈建议用 R 或专业文本编辑器处理。三个新手常踩的坑:① 编码用 UTF-8,否则中文注释会乱码;② 缺失值统一记为 NA;③ 列名不要用空格和特殊符号(用下划线代替)。
教程会用到两类核心表格:
GEO 的原始数据包(SOFT/MINiML 格式)和 TCGA 的下载清单会在第 06 章详细介绍;本章先掌握“表格式文件”就够用了。
这一节是本教程的“统计急救包”。每个概念都先给直觉,再给严谨定义,并说明它在示例课题里出现在哪一步。
严谨定义:在原假设(null hypothesis,例如“肿瘤组与癌旁组表达无差异”)为真的前提下,观测到“当前数据或更极端数据”的概率。直觉:如果两组其实没有差异,纯靠随机抽样,得到现在这么大差异的概率有多大?这个概率就是 p 值。
新手最容易犯的两个错误:① p 值不是“两组有差异的概率”,它衡量的是“证据的强度”,而不是“效应的大小”;② p > 0.05 不代表“没有差异”,可能只是样本量太小、检验功效(power)不足。惯例阈值是 p < 0.05,意思是“如果原假设为真,出现这种结果的概率不到 5%”——这只是约定俗成的门槛,不是数学铁律。
差异表达分析一次要检验约 2 万个基因。设想所有基因其实都没有差异:按 p < 0.05 的标准,纯随机也会有约 5% 的基因“碰巧”显著——也就是约 1000 个假阳性(false positive)。检验做得越多,假阳性越泛滥,这就是多重检验问题(multiple testing problem)。
解决办法是校正(adjustment)。我们控制的是 FDR(False Discovery
Rate,错误发现率):“在被判定为显著的基因里,预期有多少比例其实是假阳性”。最常用的校正是
BH 方法(Benjamini–Hochberg 法),校正后的值叫 adjusted p value(记为
adj.P 或
padj)。本教程的差异基因筛选标准统一为:|log2FC| > 1 且 adj.P < 0.05(BH 校正)。
FC 是倍数变化(fold change):处理组均值 ÷ 对照组均值。FC 有一个毛病:上调 2 倍(FC = 2)和下调一半(FC = 0.5)在数值上不对称。取以 2 为底的对数后:log2(2) = 1,log2(0.5) = −1,对称且直观。所以 log2FC(log2 fold change)> 1 表示上调超过 2 倍,< −1 表示下调超过 2 倍。
t 检验(Student’s t-test)比较两组均值是否显著不同,核心思想是:差异(两组均值之差)除以这个差异的“不确定性”(标准误)。差异越大、数据越稳定(标准误越小),t 值越大,p 值越小。
limma 是生信领域差异分析的“事实标准”包:它把每个基因的检验写成一个线性模型(linear model),再用经验贝叶斯(empirical Bayes)方法“借力”——用全基因组所有基因的信息来稳定单个基因的小样本方差估计,避免“样本只有 3 个、方差算不准”的尴尬。对 RNA-seq 的 counts 数据,用 limma-voom 流程(先做 voom 变换再跑 limma)。你现在不需要会推导,只要记住:limma 的本质是“更稳的 t 检验”。
拿到一张差异基因列表后,自然的问题:这些基因是不是“扎堆”出现在某些通路(如焦亡、IL-1β 信号、细胞因子)里?富集分析(enrichment analysis)回答的就是这个问题。
它的统计思想是“抽球问题”:假设全基因组有 N 个基因,其中某通路有 M 个成员;你挑了 n 个差异基因,其中属于该通路的有 k 个。问:如果差异基因是随机挑的,出现“k 个或更多通路基因”的概率是多少?这个概率由超几何分布(hypergeometric distribution)给出;等价的实现方式是 2×2 列联表上的 Fisher 精确检验(Fisher’s exact test)或卡方检验(chi-square test)。概率小,说明差异基因在该通路里“富集”了。常用工具如 clusterProfiler 包(支持 GO 与 KEGG 富集),第 09 章会手把手教。
生存分析(survival analysis)研究“事件发生的时间”——在本课题里事件就是患者死亡。三个核心概念:
当我们用某个指标(如风险评分)预测“患者 3 年内会不会死亡”时,怎么评价预测准不准?ROC 曲线(receiver operating characteristic curve,受试者工作特征曲线)横轴是“1 − 特异度”(假阳性率),纵轴是“灵敏度”(真阳性率),曲线上每个点对应一个判断阈值。AUC(Area Under the Curve)是曲线下面积:AUC = 0.5 相当于瞎猜(纯随机),AUC 越接近 1 预测越准,通常 AUC > 0.7 认为有较好的区分能力。它回答的问题是:“把高风险和低风险患者分开的能力有多强?”
R 是免费开源的统计编程语言,生信圈选它的原因很实在:统计生态最全(t 检验、Cox 回归开箱即用)、有专门的生信包仓库 Bioconductor(limma、DESeq2、clusterProfiler 都在里面)、绘图能力强(ggplot2)、且完全可复现——脚本跑一遍,结果一致,这是论文写作的基本要求。
RStudio 是 R
的“驾驶舱”,界面分四块:左上脚本编辑器(source,写代码的地方,保存为 .R
文件)、左下控制台(console,代码运行与结果显示)、右上环境窗格(environment,显示已创建的变量/数据)、右下文件/绘图/包/帮助窗格(plots
里显示画出的图)。# 开头是注释,不会被运行;Windows 下按
Ctrl+Enter 运行光标所在行。
R 里最常用的两种数据结构:向量(vector,一维数据,用
c() 创建)和数据框(data
frame,二维表格,行 = 观测、列 = 变量)。tidyverse
是一套“数据科学全家桶”(ggplot2、dplyr、readr、tidyr
等),它的精神是整洁数据(tidy
data):每一行是一个观测,每一列是一个变量,每个单元格是一个值。tidyverse
还有一个标志性符号 %>%
管道(读作“然后”):把左边的结果传给右边函数的第一个参数,让代码像流水线一样从左往右读。
# 向量:一维数据
x <- c(1, 2, 3, 4)
# 数据框:二维表格
df <- data.frame(
gene = c("GSDMD", "NLRP3"),
logFC = c(1.2, -0.8)
)
# 三个最常用的"查看"函数
str(df) # 查看结构
head(df) # 查看前几行
dim(df) # 查看维度(行数 × 列数)下面这个脚本是完整的、可运行的(先给“模拟数据”版本,无需任何文件即可跑通;再给“读取真实文件”版本,第
06
章会教你如何得到那个文件)。安装包需要联网,install.packages("tidyverse")
执行一次即可。
# ============ 第一个脚本:表达矩阵 + 散点图 ============
# 0) 安装(联网时执行一次即可,tidyverse 是真实存在的 R 包合集)
# install.packages("tidyverse")
# 1) 加载
library(tidyverse)
# 2) 方式 A:用模拟数据先跑通流程(无需任何外部文件)
set.seed(42) # 固定随机种子,保证每次运行结果一致(可复现)
expr_demo <- tibble(
sample = 1:50,
GSDMD = rnorm(50, mean = 8, sd = 1.5), # 模拟 50 个样本的 GSDMD 表达
NLRP3 = rnorm(50, mean = 8, sd = 1.5), # 模拟 NLRP3 表达
group = rep(c("tumor", "normal"), each = 25) # 前 25 个是肿瘤,后 25 个是癌旁
)
# 3) 画散点图:X = GSDMD,Y = NLRP3,按分组着色
# %>%,读作"然后":把 expr_demo 传给 ggplot 的第一个参数
expr_demo %>%
ggplot(aes(x = GSDMD, y = NLRP3, color = group)) +
geom_point(size = 2, alpha = 0.7) +
labs(title = "GSDMD 与 NLRP3 表达散点图(示例数据)",
x = "GSDMD 表达量", y = "NLRP3 表达量") +
theme_minimal()
# 4) 方式 B:读取真实的表达矩阵(第 06 章会教你如何得到这个文件)
# expr <- read_csv("data/expr_matrix.csv") # 文件存在时取消注释即可运行
# head(expr)
# dim(expr)跑完后,右下角 plots 窗格会出现一张按“肿瘤/癌旁”着色的散点图。如果看到图,恭喜——你已经完成了生信入门的第一公里。后续章节会在这个基础上逐步加入 limma、survival、clusterProfiler 等更专业的包,但“读数据 → 处理 → 画图”这个循环,从现在起会一直陪着你。
%>%
管道让代码像流水线;第一个脚本能画出第一张图。本章属于“Track B:数据基础”,为第 06 章的数据获取做知识准备。建议先读完第 01、02 章再进入本章。
学完本章,你将能够:
说明:上图是教程绘制的示意图,仅用于展示数据库之间的分工关系;图中每个数据库的详细内容以官方页面为准。
数据从哪来? 世界各地的科研机构(尤其是美国国立卫生研究院(NIH)系统资助的大型项目)按“数据共享”要求,把论文背后的数据“上交”到公共数据库。以 TCGA 为例:它收集上万例癌症患者的肿瘤组织,完成测序与临床随访后,把表达矩阵、突变、临床表等公开发布,任何研究者都可下载。
为什么免费? 这些研究主要由纳税人资助,成果属于公共资源;期刊与基金也要求数据共享。你可以免费下载使用,唯一要求是发表论文时正确引用(见第 13 章)。一句话:免费但要用,用了要 cite。
常用数据库按功能分类(对应上图):
本教程的核心数据其实只需要两处:TCGA-LIHC(发现队列)和 GSE14520(验证队列),其余数据库用于辅助分析与验证。
TCGA(The Cancer Genome Atlas,癌症基因组图谱) 由美国国家癌症研究所(NCI)与国家人类基因组研究所(NHGRI)联合发起,自 2006 年起覆盖 33 种癌症类型(以官方发布为准),每种癌症同时提供多组学数据与临床随访信息。
TCGA-LIHC:肝细胞癌(Liver Hepatocellular Carcinoma, LIHC)队列,是肝癌研究中引用最多的公共数据之一。本教程使用的是其 RNA-seq 表达谱与临床随访数据,约 371 例肿瘤组织 + 50 例癌旁正常组织(样本数以 TCGA 官方发布为准)。
TCGA 提供哪些数据类型?
怎么访问? 三个常用入口,用途不同:
注意:TCGA 大部分处理后的数据(表达矩阵、临床表)公开可下载;少数受控数据(部分原始测序文件、部分临床字段)需要向 dbGaP(基因型与表型数据库)提交申请,以 GDC 官方说明为准。
本教程只使用 TCGA-LIHC 的表达与临床两类数据,突变、拷贝数、甲基化等其他类型先了解即可。
GEO(Gene Expression Omnibus,基因表达综合数据库) 由美国国家生物技术信息中心(NCBI)维护,地址:https://www.ncbi.nlm.nih.gov/geo ,是全世界最大的基因表达数据库。芯片时代的绝大多数表达数据以及大量 RNA-seq 数据都存在这里。
GEO 的四级结构(新手最容易混淆,务必记牢):
本教程直接使用 GSE 层级的系列矩阵,不需要用到 GDS。
一个类比:GSE 是一“期杂志”,GSM 是其中的“每篇文章”,GPL 是“印刷用的纸张规格”,GDS 是杂志社编的“精选合集”。
GSE14520:本教程的验证队列。它由复旦大学生物医学研究院等团队提交,是肝细胞癌(HCC)表达谱数据集,包含肿瘤与癌旁样本,并带有生存随访——这正是它能做“生存验证”的原因。其芯片平台为 GPL3921,探针 ID 需映射为基因 Symbol(第 06 章实操)。具体样本数与字段以 GEO 页面为准。
怎么检索? 打开 GEO 主页,在搜索框输入
accession(登录号),如
GSE14520——它是数据集的“身份证号”,比名字可靠。页面底部有
“Series Matrix File(s)” 下载入口;R 的 GEOquery 会自动获取这些文件(第
06 章)。
GEO 页面上会看到什么? 打开 GSE14520 的页面,主要元素包括:标题与摘要(这个研究做了什么)、“Platforms”(平台,如 GPL3921 的链接)、“Samples”(该系列包含的所有 GSM 样本列表)、以及底部的下载文件区(Series Matrix File(s) 和 Supplementary files)。其中 Series Matrix File 就是我们在 R 里用 GEOquery 读取的文件,格式为文本表格。
拿到差异基因列表之后,你想知道“这些基因在做什么”,就需要功能注释数据库。
GO(Gene Ontology,基因本体):https://geneontology.org ,用一套受控词汇描述基因功能,分三个分支:
KEGG(Kyoto Encyclopedia of Genes and Genomes,京都基因与基因组百科全书):https://www.kegg.jp ,把基因映射到代谢与信号通路上,回答“这些基因富集在哪些通路”,如 NF-κB 信号通路、TNF 信号通路等。
一句话记忆:GO 管“功能分类”,KEGG 管“通路”。第 09 章会用 clusterProfiler 自动完成 GO/KEGG 富集分析。
在本课题中,GO/KEGG 的作用是把“焦亡基因集与差异表达基因的交集”放到功能语境里解释:例如这些基因富集在“炎症反应”“NF-κB 信号通路”等条目,就能说明焦亡基因可能通过哪些机制影响 HCC 的进展(第 09 章实操)。
STRING:https://string-db.org ,蛋白-蛋白互作(protein-protein interaction, PPI)数据库。输入基因列表,它综合实验、文献等证据给出互作网络,第 10 章用它找 hub 基因(关键节点)。
HPA(Human Protein Atlas,人类蛋白图谱):https://www.proteinatlas.org ,用免疫组化、质谱等手段展示蛋白在人体组织中的真实表达。它提醒我们:mRNA 表达高 ≠ 蛋白表达高。想验证某个基因在蛋白水平是否真的高表达时,就去查 HPA。
原则:先有科学问题,再选数据库。 下面是一张快速决策表(示意):
| 我想知道…… | 用哪个数据库 | 数据类型 |
|---|---|---|
| 基因在肿瘤 vs 癌旁中的表达差异 | TCGA、GEO、GTEx | 表达矩阵 |
| 基因与患者生存的关系 | TCGA、GEO(带随访) | 表达 + 临床 |
| 基因有哪些突变 | TCGA(GDC / cBioPortal) | 突变 MAF |
| 这些基因参与什么通路 | GO、KEGG | 注释 / 通路 |
| 蛋白之间怎么相互作用 | STRING | PPI 网络 |
| 蛋白水平是否真的高表达 | HPA | 蛋白表达 |
| 免疫细胞浸润情况 | TIMER、GEPIA | 在线分析 |
本教程的选库逻辑:科学问题是“焦亡相关基因在 HCC 中表达是否异常、哪些与预后相关、能否构建预后风险模型”。因此需要:
用两个独立数据集回答同一问题,是生信挖掘论文最常见的证据增强方式(第 12 章会详细讲验证)。
新手常见误区:先下载了一堆数据,再想“能做什么”——这会导致分析方向混乱。正确顺序是先写下你的科学问题,再决定需要什么类型的数据,最后才去下载。数据不是越多越好,够回答问题即可。
选库不是一次性的:分析过程中发现缺数据(比如缺正常组织表达基线),随时回到这张表补选即可。
“一个好的生信课题,一半靠分析,一半靠选题。”——生信圈流传的话
本章教你:什么课题能发表、怎么从零设计一个课题、以及如何把“焦亡 × 肝癌”这个示例课题扩展到属于你自己的版本。
先破除一个迷思:“生信课题 = 跑流程”是错的。能发表的课题,本质上回答了一个具体、有意义、可验证的科学问题,跑流程只是实现手段。
按“科学问题的新颖度 × 工作量”两个维度,新手常见课题可分为三档:
| 档次 | 模式 | 例子 | 发表难度 | 适合谁 |
|---|---|---|---|---|
| 入门档 | 单基因/单机制 × 单癌种挖掘 | “GSDMD 在肝癌中的表达与预后” | 中低(需要讲出新意) | 本科生毕设 |
| 进阶级 | 基因集 × 单癌种 × 预后模型 | “焦亡相关基因构建肝癌预后模型”(本教程示例) | 中(需要独立验证+一定工作量) | 研究生第一篇文章 |
| 挑战级 | 多组学/单细胞/泛癌 × 机制闭环 | “焦亡在泛癌中的免疫微环境重塑 + 实验验证” | 高(需实验或大量计算) | 进阶者 |
本教程选择进阶级:工作量适中、流程完整、有独立验证、有预后模型——这是新手“跳一跳够得着”的最佳平衡点。
诚实提示(写进论文讨论也要用):这类论文的同质化风险在增加,越来越多的期刊开始要求独立验证队列(GEO 验证)甚至简单实验验证(qPCR/WB)。所以我们教程把“独立验证”作为标配步骤(第 12 章),这既是科学严谨,也是发表策略。
把任何想法过一遍这四关,能过三关以上就值得做:
你的课题必须能回答“是/否”: - (是) 可验证:“焦亡相关基因在 HCC 中差异表达,且与预后相关”——能用数据检验; - (否) 不可验证:“焦亡在肝癌发生中起重要作用”——太泛,无法证伪。
医学研究经典的 PICO 框架,生信挖掘同样适用:
| 字母 | 含义 | 本教程示例 |
|---|---|---|
| P | Population 人群/疾病 | 肝细胞癌(HCC)患者 |
| I | Intervention 关注的暴露/因素 | 细胞焦亡相关基因的表达水平 |
| C | Comparison 比较 | 肿瘤 vs 癌旁;高表达组 vs 低表达组 |
| O | Outcome 结局 | 差异表达、富集通路、总生存期(OS)、预后风险 |
把四格填满,课题一句话就出来了:
在肝细胞癌患者中(P),焦亡相关基因的表达(I)相比癌旁组织(C),是否存在差异表达、富集到哪些通路,并与患者总生存期(O)相关?
试试把你自己的想法套进这个框架——比如把“焦亡”换成“铁死亡”、“肝细胞癌”换成“乳腺癌”,你就有了一个新课题的雏形。
| 变量 | 定义 | 数据来源 |
|---|---|---|
| 结局 | 总生存期 OS(月);事件=死亡 | TCGA-LIHC clinical |
| 分组 | Normal / Tumor | TCGA-LIHC 样本类型 |
| 表达 | RNA-seq FPKM(log2 转换) | UCSC Xena / GDC |
| 焦亡基因集 | 文献来源的焦亡基因列表(示例:GSDMD、GSDME、CASP1、IL1B、IL18、NLRP3、AIM2、PYCARD、GSDMA/B/C 等;正式研究需给出确切来源文献与列表) | 文献补充材料 |
关键提醒:焦亡基因集的“出处”必须可追溯。真实研究中应从特定文献的补充材料(Supplementary Table)提取完整列表,并在论文方法中注明来源文献。教程演示使用示例列表跑通流程,正式研究请替换为完整、有出处的列表。
动分析前,写一页纸的 design.md(本教程的项目目录
experiments/ 里就有范例结构):
# 课题设计:焦亡相关基因在 HCC 中的预后价值
## 科学问题
(一句话 PICO 表述)
## 数据
- TCGA-LIHC:表达 + 临床(下载日期、版本)
- GSE14520:验证队列(accession、平台)
## 分析步骤(与参数)
1. ...(limma, |log2FC|>1, adj.P<0.05)
2. ...
## 预期结果 / 备选方案
...
## 时间表
...设计文档的价值:防止分析中“凭感觉改参数”——所有阈值在动手指之前就定好,这是可复现性(reproducibility)和防数据窥探的第一步。
本章属于“Track B:数据基础”。请在第 03 章了解了数据来源之后,先把分析环境搭好,再进入第 06 章的数据获取。
学完本章,你将能够:
install.packages() 与
BiocManager::install() 安装教程所需的全部 R 包;sessionInfo() 记录分析环境,保证结果可复现。本教程的分析用 R 语言完成,配套使用 RStudio(一个更友好的 R 开发界面)。推荐安装 R 4.x(如 4.3.x、4.4.x,以官网当前稳定版为准)。
为什么用 R? 因为生信挖掘——尤其是 GEO 数据下载、差异表达、富集分析、生存分析——的主流工具链是 R:GEOquery、limma、clusterProfiler、survival 等包在 R 生态里最成熟,论文方法学也几乎都用 R 描述。Python 在深度学习、单细胞分析领域更强,但本教程用不到,属于“可选装”:学有余力再装,不影响后续任何章节。
提示:如果电脑上装过旧版 R(如 3.x),建议先卸载再装新版,避免包版本混乱。
第 1 步:安装 R。
C:\Program Files\R\R-4.x.x,不用修改;第 2 步:安装 RStudio。
验证安装:在 RStudio 左下角 Console(控制台)输入:
R.version.string回车后能看到类似 R version 4.4.x (2025-xx-xx)
的输出,即安装成功。
装完常见问题:如果打开 RStudio 提示找不到 R,多半是 R 未安装或安装不完整,重装 R 后重启 RStudio 即可;如果 RStudio 界面是英文,不影响使用(Tools → Global Options 里可改语言,也可不改)。
R 的“包”(package)是别人写好的函数集合。装包有两条命令:
# 从 CRAN(R 官方包仓库)安装
install.packages("ggplot2")
# 从 Bioconductor(生物信息学包仓库)安装
# 第一步:先安装包管理器 BiocManager
install.packages("BiocManager")
# 第二步:用 BiocManager 安装 Bioconductor 的包
BiocManager::install("GEOquery")一次性装齐本教程的核心包(把下面整段复制进 Console,回车执行;首次安装可能需要几分钟到几十分钟,请耐心等待,不要中途关闭):
# 1. 包管理器
install.packages("BiocManager")
# 2. Bioconductor 包
BiocManager::install(c("GEOquery", "limma", "clusterProfiler",
"org.Hs.eg.db", "survival", "survminer"))
# 3. CRAN 包
install.packages(c("glmnet", "pheatmap", "ggplot2", "timeROC", "survivalROC"))提示:Windows 上装包需要联网。个别包在编译时需要 RTools(https://cran.r-project.org/bin/windows/Rtools/ 下载安装即可),但绝大多数包都有预编译的 Windows 二进制版本,不需要 RTools。
装包失败先看报错:最常见的是网络问题(可换国内镜像源,如
install.packages("ggplot2", repos = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))或包名拼写错误。
核心包用途表(本教程会逐章用到,先混个脸熟):
| R 包 | 用途 | 主要出现在 |
|---|---|---|
| GEOquery | 下载并读取 GEO 数据(GSE 系列矩阵) | 第 06 章 |
| limma | 差异表达分析(differential expression analysis, DEA) | 第 07 章 |
| clusterProfiler | GO/KEGG 富集分析、GSEA | 第 09 章 |
| org.Hs.eg.db | 人类基因 ID 注释与转换 | 第 07/09 章 |
| survival | KM 生存曲线、Cox 回归 | 第 11 章 |
| survminer | 生存分析绘图(ggsurvplot) | 第 11 章 |
| glmnet | LASSO 回归,构建预后风险模型 | 第 11 章 |
| pheatmap | 表达热图 | 第 08 章 |
| ggplot2 | 通用绘图(火山图等) | 第 08 章 |
| timeROC / survivalROC | 时间依赖 ROC 曲线(评估模型) | 第 11/12 章 |
使用某个包前要先“加载”:library(包名)。如果
library
报错“没有这个包”,多半是没装成功,重新执行对应的安装命令即可。
补充一个小知识:library(包名)
用于加载包,使其中函数可以直接调用;而
BiocManager::install(...)
这种“包名::函数”的写法表示“调用某包里的某函数”,不先加载也能用。教程中两种写法都会出现。
工作目录(working directory) 是 R
读写文件的默认文件夹。可以用 setwd() 手动设置:
# Windows 路径示例:注意用正斜杠 / 或双反斜杠 \\
setwd("D:/projects/hcc_pyroptosis")
getwd() # 查看当前工作目录新手最常见的坑:文件明明在桌面上,R 却找不到——多半是工作目录不对。强烈建议用 RStudio Project 代替手动 setwd,一劳永逸。
建立 RStudio Project:File → New Project → New
Directory → New Project,填写项目名(如
hcc_pyroptosis),选择存放位置(如
D:/projects/),创建后 RStudio
会自动把工作目录设为项目根目录,下次打开项目时也会自动恢复。
相对路径:使用 RStudio Project 后,脚本里的
data/raw/...
这类路径就是“相对于项目根目录”的路径,换电脑也能用;而
C:/Users/xxx/Desktop/...
这类绝对路径换电脑就要改。本教程一律采用相对路径。
项目内文件夹组织(本教程统一约定,第 06 章会详细说明 data 目录):
hcc_pyroptosis/
├── data/ # 原始数据(下载后只读,不手动改动)
├── scripts/ # R 脚本(01_download.R、02_dea.R ……)
├── results/ # 分析结果(表格、模型输出)
├── figures/ # 图片
└── README.md # 项目说明与数据登记(见第 06 章)
生信分析讲究“可复现”(reproducible):半年后别人(或你自己)重跑脚本,结果应当一致。但 R 包会不断更新,版本不同结果可能不同。这里给出两个由浅入深的办法:
sessionInfo() 会把 R
版本、所有已加载包及其版本完整打印出来。把它保存到 results
目录,作为本次分析的环境快照:writeLines(capture.output(sessionInfo()), "results/sessionInfo.txt")renv::init()
初始化,renv::snapshot()
把当前所有包的精确版本记录到项目里,之后在别的电脑上
renv::restore()
可以一键恢复相同版本。适合需要长期维护的项目。对新手来说,做到第 1 条(记录 sessionInfo)就已经比大多数教程的要求更严谨了。
什么时候用 renv? 项目需要长期维护、多人协作,或投稿前想严格复现时再用 renv;日常练习做到 sessionInfo 记录就足够了。
install.packages()(CRAN)与
BiocManager::install()(Bioconductor);sessionInfo() 记录环境,进阶可用 renv
锁定包版本。install.packages() 和
BiocManager::install() 有什么区别?为什么 Bioconductor
的包一般不能用第一种命令安装?setwd("C:/Users/你的用户名/Desktop")
后,getwd() 会返回什么?为什么教程推荐用 RStudio Project
而不是 setwd?library(ggplot2)。本章属于“Track B:数据基础”。环境搭好(第 05 章)之后,我们正式开始下载本课题的两套核心数据:TCGA-LIHC(发现队列)与 GSE14520(验证队列)。
学完本章,你将能够:
data/
目录(原始数据只读、脚本与结果分开);重要提示:本章所有下载都需要联网,且 TCGA/GEO 文件较大,下载可能较慢;教学演示时也可以只取部分样本(见 6.2 节提示)。
开始前请先做两件事:一是在 data/raw/ 下建好
TCGA-LIHC/ 与 GSE14520/ 两个文件夹(见 6.3
节);二是确认网络稳定——TCGA
表达矩阵文件较大,中途断网可能导致下载不完整,建议在网速较好的时段下载。
TCGA 数据可以从官方 GDC 下载,但对新手来说,UCSC Xena(https://xena.ucsc.edu )更友好:它把 TCGA 整理成“基因 × 样本”的表达矩阵和“样本 × 字段”的临床表,点几下就能下载。
UCSC Xena 网页下载步骤(以当前界面为例;网站界面会更新,以官网为准):
下载到的是什么文件?
TCGA-BC-A10Q-01A,其中 -01
一般代表肿瘤组织、-11 代表癌旁正常组织(TCGA
样本类型编码规则,以官方说明为准);FPKM 还是 Counts? 本教程选用 HTSeq-FPKM:它按基因长度与测序深度做了标准化,适合比较基因之间的表达水平,也是 limma 差异表达分析(第 07 章)的常见输入(通常先做 log2 转换)。HTSeq-Counts 是原始计数,更适合 DESeq2 / edgeR 等专门工具,本教程暂不涉及。
GDC 简述(了解即可):https://portal.gdc.cancer.gov → Repository → 左侧筛选(Cancer Type 选 Liver Hepatocellular Carcinoma;Data Category 选 Transcriptome Profiling;Experimental Strategy 选 RNA-Seq)→ 把符合条件的文件加入购物车 → 下载表达矩阵与临床文件。GDC 更权威,但筛选项多、文件格式多样,新手阶段先用 Xena。
下载后检查:表达矩阵文件通常有几十
MB(解压后更大),临床表只有几百
KB。下载完成后建议先确认文件能正常打开:用记事本或 Excel
打开前几行看看格式(注意:大文件用 Excel 打开会很慢,可用 R 的
read.table 或 data.table::fread
读取)。文件命名建议加上日期,例如
LIHC_HTSeqFPKM_2025-01-15.txt.gz。如果只是想练习完整流程,也可以先用较小的临床表文件熟悉格式。
GSE14520 存放在 GEO 中。GEO 提供了官方 R 包 GEOquery,一条命令即可下载整个数据集。
代码 6-1:下载并读取 GSE14520
# 第 05 章已安装:BiocManager::install("GEOquery")
library(GEOquery)
# 下载 GSE14520 的 Series Matrix 文件(需联网,视网速可能需要数分钟)
gse <- getGEO("GSE14520", GSEMatrix = TRUE)
# gse 是一个列表:一个 GPL 平台对应一个元素
length(gse) # 一般等于该 GSE 使用的平台数量
gse[[1]] # 第一个平台的 ExpressionSet 对象
# 提取表达矩阵:行是探针 ID,列是样本(GSM 编号)
expr <- exprs(gse[[1]])
dim(expr) # 查看维度,例如 2 万余个探针 × 数百个样本
# 提取样本信息(临床 / 分组 / 随访)
pdata <- pData(gse[[1]])
colnames(pdata) # 先看有哪些列,再决定怎么用
head(pdata) # 查看前几行ExpressionSet 是什么? GEOquery
把每个平台的完整数据封装成一个 ExpressionSet
对象,它像一个“文件夹”,里面装了三样东西:表达矩阵(用
exprs() 取出)、样本信息(用 pData()
取出)、探针注释(用 fData()
取出)。理解这个结构后,GEOquery 的日常用法就只剩这三个函数了。
解释几个关键点:
getGEO("GSE14520", GSEMatrix = TRUE) 下载的是 GEO
官方整理的 Series Matrix 文件;返回的 gse
是列表,每个元素对应一个平台(GPL)的 ExpressionSet
对象。同一个 GSE 如果用了不同芯片平台,就会有多个元素,所以我们用
gse[[1]] 取第一个;exprs() 取出表达矩阵(ExpressionSet
的“表达”槽),pData() 取出样本信息(phenotype data
槽)——这是 GEOquery 最常用的两个函数;expr 的列名就是 GSM
编号,pdata 的每一行对应一个 GSM;pdata 的
characteristics_ch1 等列中,例如 tissue: tumor
/ tissue: normal;GSE14520
还带有生存随访字段(这是它能做生存验证的前提)。不同数据集的列名不同,务必先用
colnames(pdata) 查看实际列名,再写代码提取。小提示:getGEO 会把下载的 Series Matrix 文件缓存在当前工作目录,重复运行时直接读取缓存,速度更快。如果下载中断,删除缓存文件后重新运行即可。
教学演示提示:GSE14520 样本数较多,教学时可以先只取部分样本跑通流程:
# 示例:只保留前 20 个样本(教学演示用;正式分析请用全部样本)
expr_sub <- expr[, 1:20]关于临床列:GSE14520 的 pData
中,样本分组列(tumor /
normal)和生存列(生存时间、生存状态)的列名在不同版本中可能不同,常见命名有
characteristics_ch1、survival time、survival status 等。第
11 章做生存分析前,我们会先把这些列整理成统一格式:时间列必须是数值(如
12.5 个月),状态列必须是 0/1(0 = 删失 censored,1 =
事件发生)。如果状态列是文字(如 alive / dead),需要先转换为 0/1。
探针 ID → 基因 Symbol 的映射(平台注释)
GSE14520 使用的芯片平台是 GPL3921(Affymetrix
人类全基因组芯片,具体型号以 GEO 页面为准),表达矩阵的行名是探针
ID(形如 1552777_at),不是基因名。要得到基因
Symbol,需要平台注释。三种常用做法:
方法 A(最简单):Series Matrix 文件本身常带注释列,直接查看:
fData(gse[[1]]) # 探针注释表
colnames(fData(gse[[1]])) # 看看有哪些注释列(如 Gene Symbol)方法 B(从 GEO 下载 GPL 注释表):
gpl <- getGEO("GPL3921") # 下载平台注释
colnames(Table(gpl)) # 查看注释表的列,通常有 ID、Gene Symbol 等
head(Table(gpl)) # 查看前几行示例方法 C(Bioconductor 注释包):GPL3921 这类 Affymetrix
平台一般有对应的注释包(如 hthgu133a.db,具体以 Bioconductor
当前文档为准),可用 mapIds() 做探针→Symbol 的映射。第 07
章预处理时会给出完整映射代码,这里先理解原理:探针 ID
必须靠平台注释变成基因 Symbol,分析才有生物学意义。
无论用哪种方法,最终目的都是得到一张“探针 ID → 基因 Symbol”的对照表,然后把它合并到表达矩阵上,把同一基因对应的多条探针合并(通常取平均值或最大值,第 07 章会给出处理重复基因的完整代码)。这一步是芯片数据分析的关键转折点:从此以后,你的分析对象从“探针”变成了“基因”,后面所有分析(差异表达、富集、生存)都在基因层面进行。
下载到的原始文件不要乱放,按第 05 章的约定组织(这是本教程所有章节的统一约定):
hcc_pyroptosis/
├── data/
│ ├── raw/ # 原始下载文件(只读,永不手动修改)
│ │ ├── TCGA-LIHC/ # Xena 下载的表达矩阵与临床表
│ │ └── GSE14520/ # GEO 下载的系列矩阵文件
│ └── processed/ # 处理后的数据(第 07 章输出)
├── scripts/ # 01_download.R、02_dea.R ……
├── results/ # 分析结果表
└── figures/ # 图片
把 Xena 下载的文件放进 data/raw/TCGA-LIHC/;把 GEOquery
下载的对象保存到本地,避免以后反复联网下载。processed/
目录则留给第 07 章的预处理产物(如探针映射为基因 Symbol、去重、log2
转换后的表达矩阵)——原始文件永远只读,一切处理都在脚本里可重现:
# 保存 GSE14520 原始对象到本地(约几十 MB)
save(gse, file = "data/raw/GSE14520/gse14520_raw.RData")为什么原始数据必须只读? 分析的可信度来自“可追溯”:任何处理都应当通过脚本完成,而不是手动修改原始文件。一旦你在 Excel 里手动改过原始矩阵,别人(包括半年后的你自己)就无法知道你改了什么,结果也就无法复现。记住一句话:原始数据只读,脚本重现一切。
下载完成后先别急着分析,做三件最基础的检查(每件都是 R 一行命令):
# 1. 表达矩阵维度:行数(基因/探针)× 列数(样本)
dim(expr)
# 2. 缺失值数量:缺失太多说明数据质量差,需要处理
sum(is.na(expr))
# 3. 样本分组:看看有哪些组别、每组多少样本
# 注意:先 colnames(pdata) 确认分组列名,再替换下面的列名
table(pdata$characteristics_ch1)这三个检查回答三个问题:数据有多大?缺失多不多?样本怎么分组?
如果缺失值很多(例如数以万计),第 07 章会教你处理(过滤 / 补缺 /
剔除),这里先记录观察即可。把检查结果写进 results/
下的记录文件,作为分析日志的一部分:
# 记录质控结果(示例),供日后核对
writeLines(c(
paste("探针数:", dim(expr)[1], "样本数:", dim(expr)[2]),
paste("缺失值数:", sum(is.na(expr)))
), "results/00_QC_note.txt")两个容易踩的坑:一是表达矩阵的列名(GSM 编号)与
pData
的行名必须一一对应,分组前最好确认顺序一致(all(colnames(expr) == rownames(pdata))
返回 TRUE 才放心);二是分组列里可能有大小写或写法差异(如 tumor 与
Tumor),用 unique() 查看所有取值后再写分组逻辑。
另外,质控的阈值没有统一标准,关键是如实记录并解释你的选择——这本身就是严谨的做法。
做科研要能“说清楚数据从哪来”。建议在 data/README.md(或
data 目录下一个文本文件)里做登记:
# 数据登记表
- TCGA-LIHC:来源 UCSC Xena;表达:HTSeq-FPKM;临床:phenotype;
accession/版本:TCGA-LIHC(以 Xena 页面标注为准);下载日期:2025-XX-XX
- GSE14520:来源 GEO;平台:GPL3921;
accession:GSE14520;下载日期:2025-XX-XX只要记住三要素——accession 编号、下载日期、版本/平台——以后写论文方法学、或被审稿人追问数据来源时,都能答得上来。(一句话登记就够了,但必须记。)
为什么登记很重要? 公共数据库的版本会更新(例如 GEO 偶尔补充样本、Xena 更新注释版本),如果不记录下载日期和版本,以后重跑分析可能得到与论文不一致的结果。另外,审稿人或读者要求“提供数据来源”时,登记表就是你的证据。
getGEO("GSE14520", GSEMatrix = TRUE)
一行下载,exprs() 取表达矩阵、pData()
取临床信息;探针 ID 需用平台注释(GPL3921)映射为基因 Symbol;data/raw/(只读),脚本、结果、图分开存放;dim()、sum(is.na())、table(分组列);pData 的哪一列?getGEO("GSE14520") 返回的 gse
有多个元素,说明什么?用 gse[[2]]
取出来看看与第一个有什么不同。pData(gse[[1]]) 中找一找 GSE14520
的生存相关字段(如生存时间、生存状态),想一想后续 KM
生存分析需要哪两列。学完本章,你将能够:
model.matrix()
构建设计矩阵;|log2FC| > 1 且 adj.P < 0.05
的标准筛选差异基因,能解释为什么不能只看 p 值;在肝细胞癌(hepatocellular carcinoma, HCC)课题中,我们最想知道的一件事是:与癌旁正常组织相比,肿瘤组织里“谁变了”。差异表达分析(differential expression analysis, DEA)就是系统地回答这个问题的统计方法:对每一个基因,比较它在两组样本(如 Normal vs Tumor)中的平均表达水平,检验差异是否显著,并估计变化幅度。
一句话版本:DEA 给每个基因算两个数——变化幅度(fold change, FC)和显著性(p 值/校正后 p 值),然后按统一标准筛选出“变化大且可信”的基因。
打个比方,表达谱像一张“基因点名册”,DEA 就是逐个点名、看谁在两组之间“冒头”或“缩头”。差异基因列表是整个课题的“原材料”,后面的功能分析(第 09 章)、网络分析(第 10 章)和生存分析(第 11 章)都建立在它之上。
DEA 需要两类输入:
本教程课题使用 TCGA-LIHC(肝细胞癌)的 RNA-seq 表达谱,约 371 个肿瘤样本 + 50 个癌旁正常样本(数据下载与整理见第 06 章)。注意:TCGA 的 RNA-seq 原始数据是整数 counts,公开渠道常以 TPM/FPKM 等归一化形式提供。本章教学演示用 log2 转换后的表达量跑通流程;若手头是 counts,建议用 limma 的 voom() 或 limma-trend 处理——新手常踩的坑。
在 R 中,分组信息是一个和表达矩阵列顺序一一对应的因子向量:
group <- factor(c(rep("Normal", 50), rep("Tumor", 371)))limma 需要把分组信息转成设计矩阵(design matrix),它告诉模型“每个样本属于哪个组、我们要比较哪两组”:
design <- model.matrix(~0 + group) # 不设截距,每组一个系数
colnames(design) <- levels(group) # 列名改为 Normal / Tumor新手先记住:model.matrix() 就是把分组因子翻译成一张 0/1
矩阵——行是样本,列是组,某样本属于某组则对应位置为
1。真正要比较的两组之差,再用 makeContrasts()
显式声明:
contrast.matrix <- makeContrasts(Tumor - Normal, levels = design)limma(linear models for microarray data)是 Bioconductor 上最常用的差异分析包。它的核心思想是:对每个基因拟合一个线性模型,再用经验贝叶斯(empirical Bayes)方法借用全基因组信息来稳定单个基因的方差估计。标准流程是“三件套”:
library(limma)
expr_log2 <- log2(expr + 1) # TPM 表达量加 1 再取 log2,避免 log(0)
fit <- lmFit(expr_log2, design) # 第一步:对每个基因拟合线性模型
fit2 <- contrasts.fit(fit, contrast.matrix) # 第二步:取出我们关心的对比 Tumor - Normal
fit2 <- eBayes(fit2) # 第三步:经验贝叶斯方差收缩,得到统计量
res <- topTable(fit2, coef = 1, number = Inf, sort.by = "none")逐步解释:
lmFit():逐基因做线性回归,得到每个基因在每个组系数下的均值估计与标准误;contrasts.fit():把系数组合成我们关心的对比(Tumor 减去
Normal),得到每个基因的 logFC 与标准误;eBayes():把全基因组的信息“借”给每个基因,让方差估计更稳定——这是
limma 相对普通 t 检验的核心优势;topTable():汇总成结果表。number = Inf
表示输出全部基因(默认只输出前 10
个,新手常在这里“丢基因”);sort.by = "none"
保持原始基因顺序,方便和表达矩阵对应。topTable 输出的结果表包含以下关键列:
| 列名 | 含义 |
|---|---|
| logFC | log2 变化倍数:肿瘤相对癌旁的表达倍数(log2 尺度) |
| AveExpr | 该基因在所有样本中的平均表达量 |
| t | 该对比的 t 统计量 |
| P.Value | 未校正的 p 值 |
| adj.P.Val | BH 校正后的 p 值(即 FDR 估计值) |
| B | 该基因“确实有差异”的对数后验优势(log-odds) |
其中 logFC 和 adj.P.Val
是我们筛选差异基因最关心的两列。
本教程采用的筛选标准(也是生信论文最常用的标准):
|log2FC| > 1 且 adj.P < 0.05
|log2FC| > 1:变化倍数超过 2 倍(FC > 2 或 FC
< 0.5)。这保证差异有生物学意义——一个基因只变了 10%
可能不值得关注;adj.P < 0.05:保证差异统计上可信。为什么不能只看 p 值?因为一次要比较成千上万个基因:即使两组完全没差异,按 p < 0.05 的标准,也会有约 5% 的基因“纯靠运气”显著。假设检测 20,000 个基因,就会随机出现约 1,000 个假阳性。这就是多重检验问题(multiple testing)。
解决方法是对 p 值做校正。本教程用
Benjamini–Hochberg(BH)校正:把 p
值从小到大排序、逐级调整,得到
adj.P.Val,它控制的是假发现率(false discovery rate,
FDR)。直观理解:adj.P < 0.05 意味着“被判定为显著的这批基因里,预期约
5% 是假阳性”。R 里的等价写法是
p.adjust(p, method = "BH"),topTable 默认已做这一步。
筛选代码:
deg_idx <- abs(res$logFC) > 1 & res$adj.P.Val < 0.05
deg <- res[deg_idx, ]
table(res$adj.P.Val < 0.05, abs(res$logFC) > 1) # 交叉计数,看两个条件各自筛掉多少拿到差异基因后,先看整体格局:
up <- deg[deg$logFC > 0, ] # 上调:肿瘤中表达升高
down <- deg[deg$logFC < 0, ] # 下调:肿瘤中表达降低
nrow(up); nrow(down) # 分别计数注意方向约定:logFC > 0 表示在 Tumor − Normal
中升高,即肿瘤中上调,反之则下调。
下一步回到课题主题——细胞焦亡。把差异基因与“焦亡基因集”取交集,得到“在 HCC 中异常表达的焦亡基因”,这正是后续生存分析与免疫分析的核心对象:
pyroptosis_genes <- c("GSDMD", "GSDME", "CASP1", "IL1B", "IL18",
"NLRP3", "AIM2", "PYCARD") # 示例列表
intersect(rownames(deg), pyroptosis_genes)重要说明:焦亡基因集的“权威版本”需要从文献(焦亡机制综述或相关生信论文的补充材料)中获取,不同论文收录的基因从十几个到几十个不等。本教程的列表仅为演示用示例;正式课题中请注明基因集来源并核对基因名拼写(如是否收录 GSDMB、GSDMC、CASP4/5 等)。
把结果保存下来,供第 08、09 章继续使用:
dir.create("results", showWarnings = FALSE)
write.csv(res, "results/DEA_TCGA_LIHC_all.csv") # 全部基因的结果表
write.csv(deg, "results/DEA_TCGA_LIHC_DEGs.csv") # 筛选后的差异基因
write.csv(intersect(rownames(deg), pyroptosis_genes),
"results/pyroptosis_DEGs.csv") # 焦亡相关的差异基因保存时务必保留“未筛选”的全基因结果表:第 09 章做 GSEA 时需要对所有基因按 logFC 排序,只用差异基因子集会丢失大量信息。
完整可运行示例:用模拟数据跑通上述全部流程(set.seed
保证可复现;真实分析时把 expr、group 换成第 06
章得到的真实数据即可):
set.seed(2024)
n_gene <- 2000; n_normal <- 30; n_tumor <- 30
expr <- matrix(rnbinom(n_gene * (n_normal + n_tumor), size = 10, mu = 100),
nrow = n_gene)
rownames(expr) <- paste0("Gene", 1:n_gene)
expr[1:200, (n_normal + 1):(n_normal + n_tumor)] <- # 模拟 200 个上调基因(约 4 倍)
expr[1:200, (n_normal + 1):(n_normal + n_tumor)] * 4
group <- factor(c(rep("Normal", n_normal), rep("Tumor", n_tumor)))
# ……随后依次执行第 3 节的 design / limma / 筛选代码即可看到结果……
上图为火山图示例(第 08 章会教怎么画、怎么读):每个点是一个基因,横轴 log2FC,纵轴 −log10(adj.P.Val),越靠左右两侧高处,越是“变化大且显著”的差异基因。下图 PCA 图则从样本层面展示 Normal 与 Tumor 的整体分离,说明分组确实能解释表达差异(两张图均为模拟数据示意,读者用真实数据跑脚本后得到自己的图)。
model.matrix()
转成设计矩阵,用 makeContrasts() 声明比较。lmFit → contrasts.fit →
eBayes,最后 topTable
出表;number = Inf 别忘。|log2FC| > 1 且 adj.P < 0.05:前者保证幅度,后者(BH
校正)控制多重检验下的假阳性,不能只看 p 值。topTable 为什么默认只返回 10
行?number = Inf 和 sort.by = "none"
各解决什么问题?学完本章,你将能够:
R 基础绘图(plot())像“在白纸上直接涂色”,而 ggplot2
像“搭积木”:先告诉它“数据是什么、把数据的哪些列映射到图形的哪些元素”,再一层一层往上叠加几何对象和主题。它的核心是三件事:
aes():把数据列映射到图形属性——x
坐标、y 坐标、颜色、形状、大小;geom_*():决定画什么形状——点
geom_point()、线 geom_line()、柱
geom_col()、箱线 geom_boxplot() 等。新手三步画图法:
# 第一步:准备数据(通常整理成长格式:一列一个变量、一行一个观测)
# 第二步:ggplot(data, aes(x=..., y=...)) 建立画布与映射
# 第三步:+ geom_xxx() 加图层,+ theme_xxx() 调主题,+ ggsave() 存图
ggplot(data, aes(x = xvar, y = yvar, color = group)) +
geom_point() +
theme_bw()两个常见坑:一是 aes()
里写的是数据框的列名而不是外面的向量;二是图层叠加用
+ 号而不是管道符
%>%。记住这两点,ggplot2 就成功了一半。
火山图是差异表达分析的标准配图:每个点是一个基因,横轴 log2FC,纵轴 −log10(adj.P.Val)。纵轴取负对数后,p 值越小点越靠上,所以“显著且差异大”的基因分布在左右两侧高处,整张图呈火山喷发状——因此得名。
最直接的画法(输入是第 07 章的 res 结果表):
library(ggplot2)
res$change <- ifelse(res$adj.P.Val < 0.05 & res$logFC > 1, "up",
ifelse(res$adj.P.Val < 0.05 & res$logFC < -1, "down", "ns"))
ggplot(res, aes(x = logFC, y = -log10(adj.P.Val))) +
geom_point(aes(color = change), size = 0.8) +
scale_color_manual(values = c(up = "#d7191c", down = "#2c7bb6", ns = "grey80"),
labels = c(up = "上调", down = "下调", ns = "不显著")) +
geom_vline(xintercept = c(-1, 1), linetype = "dashed", linewidth = 0.4) +
geom_hline(yintercept = -log10(0.05), linetype = "dashed", linewidth = 0.4) +
labs(x = "log2(fold change)", y = "-log10(adjusted P)",
title = "TCGA-LIHC 肿瘤 vs 癌旁差异表达火山图") +
theme_bw() +
theme(legend.position = "top")
ggsave("figures/fig06_volcano.png", width = 6, height = 5, dpi = 300)怎么读(四象限含义):
想要“论文级”效果,也可以用现成包 EnhancedVolcano(基于 ggplot2,自动标注显著基因名并避开标签重叠):
# BiocManager::install("EnhancedVolcano")
library(EnhancedVolcano)
EnhancedVolcano(res,
lab = rownames(res), # 标注的基因名
x = "logFC", y = "adj.P.Val",
pCutoff = 0.05, FCcutoff = 1,
title = "TCGA-LIHC DEGs",
pointSize = 1.5, labSize = 3)
ggsave("figures/fig06_volcano.png", width = 7, height = 6, dpi = 300)如果只想标注重点基因(比如我们的焦亡基因),用 ggrepel 包只给它们加标签:
res$label <- ifelse(rownames(res) %in% pyroptosis_genes, rownames(res), "")
ggplot(res, aes(x = logFC, y = -log10(adj.P.Val))) +
geom_point(aes(color = change), size = 0.8) +
ggrepel::geom_text_repel(aes(label = label), max.overlaps = 20) +
theme_bw()
热图把“基因 × 样本”的表达量画成颜色矩阵:行是基因、列是样本,颜色深浅代表表达高低。它适合回答“这批基因在不同样本里有没有清晰的分组模式”。用 pheatmap 画差异基因(或焦亡差异基因)的表达热图:
# BiocManager::install("pheatmap")
library(pheatmap)
mat <- expr_log2[rownames(deg), ] # 差异基因子集
mat <- t(scale(t(mat))) # 对每个基因做 z-score 标准化
anno <- data.frame(group = group) # 样本注释数据框
rownames(anno) <- colnames(expr_log2) # 行名必须与样本名一致
png("figures/fig07_heatmap.png", width = 8, height = 6, units = "in", res = 300)
pheatmap(mat,
scale = "row", # 按行(基因)标准化
cluster_rows = TRUE, cluster_cols = TRUE, # 行/列层次聚类
annotation_col = anno, # 顶部画分组注释条
show_rownames = TRUE, show_colnames = FALSE,
color = colorRampPalette(c("navy", "white", "firebrick3"))(100),
main = "差异基因表达热图(示例)")
dev.off()需要理解的三点:
scale = "row"
与 t(scale(t(mat))) 等价,二选一即可。)annotation_col
是一个数据框,行名必须与表达矩阵的列名(样本名)完全一致,列名就是注释项的名称(如
group)。颜色映射可用 annotation_colors 参数自定义。
PCA(主成分分析,principal component analysis)把高维表达数据压缩成少数几个“主成分”,让我们能在二维平面上一眼看出样本的整体关系。注意视角切换:差异分析看基因,PCA 看样本——它回答“肿瘤样本和癌旁样本在整体表达模式上是否分开”。
pca <- prcomp(t(expr_log2), scale. = TRUE) # 注意转置:行=样本、列=基因
pca_sum <- summary(pca)$importance # 各主成分解释的方差比例
pca_df <- data.frame(PC1 = pca$x[, 1], PC2 = pca$x[, 2], group = group)
ggplot(pca_df, aes(x = PC1, y = PC2, color = group)) +
geom_point(size = 2, alpha = 0.8) +
stat_ellipse(level = 0.95) + # 95% 置信椭圆
labs(x = paste0("PC1 (", round(pca_sum[2, 1] * 100, 1), "%)"),
y = paste0("PC2 (", round(pca_sum[2, 2] * 100, 1), "%)")) +
theme_bw()
ggsave("figures/fig08_pca.png", width = 6, height = 5, dpi = 300)要点:
prcomp()
要求行是观测(样本)、列是变量(基因),而表达矩阵是“基因 ×
样本”,所以先 t()。scale. = TRUE:对每个基因标准化,防止高表达基因主导主成分。stat_ellipse(level = 0.95):给每组画 95%
置信椭圆,帮助判断两组是否真的分开。
论文图表和课堂作业图的差距往往在细节:
theme_bw(base_size = 12)),保证缩印后仍可读;图内文字不小于
7 pt。ggsave(..., dpi = 300),这是多数期刊的底线要求;矢量图(PDF/SVG)更好,任意缩放不模糊。aes() 映射 +
geom_*() 图层 + theme_*() 主题,一层层用
+ 叠加。scale = "row" 做
z-score、cluster_rows/cols
聚类、annotation_col 加分组注释条。prcomp(t(expr), scale. = TRUE) +
stat_ellipse(),从样本层面看分离与批次。学完本章,你将能够:
第 07 章我们拿到了几百上千个差异基因,但“这些基因在功能上意味着什么?”——单个基因名看不出名堂。功能富集分析(functional enrichment analysis)回答的正是这个问题:给定一堆基因,看它们是否显著地集中在某些已知的功能类别或通路上。
统计思想用“袋子抽球”类比:想象一个袋子里有 N 个球,代表基因组里所有被测到的基因,其中 M 个是红球,代表“某条通路里的基因”。你随机抽了 n 个球(我们的差异基因),发现里面有 k 个红球:k 这么大是纯属巧合,还是说明这条通路真的和我们的基因列表有关?
这正是超几何分布(hypergeometric distribution)描述的“不放回抽球”概率问题;等价地,也可以用一张 2×2 列联表做费舍尔精确检验(Fisher’s exact test)算出“纯属巧合”的 p 值。富集分析就是逐条通路(或 GO 条目)做这个检验,然后同样用 BH 校正控制多重检验。这一类方法统称 ORA(over-representation analysis,过度代表分析)。
两个容易踩的坑:
GO(Gene Ontology,基因本体)把基因功能分成三个层面:
clusterProfiler 是 Bioconductor 上最主流的富集工具。标准流程如下:
# BiocManager::install("clusterProfiler")
# BiocManager::install("org.Hs.eg.db")
library(clusterProfiler)
library(org.Hs.eg.db)
deg_entrez <- bitr(rownames(deg), fromType = "SYMBOL",
toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
ego <- enrichGO(gene = deg_entrez,
OrgDb = org.Hs.eg.db,
keyType = "ENTREZID", # 输入基因 ID 的类型
ont = "BP", # 可选 BP / CC / MF / ALL
pAdjustMethod = "BH",
pvalueCutoff = 0.05, # 条目自身 p 值阈值
qvalueCutoff = 0.2, # q 值阈值(更严格)
readable = TRUE) # 结果中显示基因符号而非 Entrez ID
head(as.data.frame(ego))关键参数解释:
bitr():ID 转换。enrichGO 默认接受
Entrez
ID,而差异基因通常是基因符号(SYMBOL),需先转换(fromType
/ toType 声明来源与目标类型);keyType:告诉 enrichGO 输入基因的 ID 类型;pvalueCutoff 与 qvalueCutoff:q 值是 p
值经多重检验校正后的版本(同第 07 章 adj.P 的思路)。clusterProfiler
默认
qvalueCutoff = 0.2,较宽松,富集检验通常只要求“信号存在”;readable = TRUE:把结果中的 Entrez ID
换回基因符号,方便阅读。结果表的关键列:ID(GO 条目号)、Description(功能描述)、GeneRatio(差异基因中属于该条目的比例)、BgRatio(背景基因中属于该条目的比例)、pvalue、p.adjust、qvalue、geneID(参与基因)。
KEGG(Kyoto Encyclopedia of Genes and
Genomes,京都基因与基因组百科全书)是通路数据库,它的条目是“通路图”而不是功能词条。KEGG
富集同样基于超几何检验,但基因要用 Entrez ID,并指定物种代码(人类为
hsa):
ekegg <- enrichKEGG(gene = deg_entrez,
organism = "hsa", # 人类
keyType = "kegg",
pvalueCutoff = 0.05,
pAdjustMethod = "BH")
head(as.data.frame(ekegg))如果结果为空(新手常见),先放宽 pvalueCutoff
看有没有信号,再检查基因 ID 是否转换正确。KEGG 通路图可以用
pathview 绘制:它把差异基因的 logFC 着色到通路图上(红
= 上调、绿 = 下调),直观展示基因在通路中的位置:
# BiocManager::install("pathview")
library(pathview)
fc <- setNames(res$logFC, rownames(res))
fc_map <- bitr(names(fc), fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
fc_vec <- fc[fc_map$SYMBOL]; names(fc_vec) <- fc_map$ENTREZID # 重复 ID 可去重,教程略
pathview(gene.data = fc_vec,
pathway.id = "hsa04668", # 示例:TNF 信号通路
species = "hsa", out.suffix = "deg")注意:pathview 需联网从 KEGG 下载通路图;KEGG 有使用条款(学术用途免费),论文中要正确引用。
clusterProfiler 的结果对象自带绘图函数,最常用的是气泡图(dotplot)与柱状图(barplot):
dotplot(ego, showCategory = 15) # 横轴 GeneRatio,点大小 = 基因数,颜色 = q 值
barplot(ego, showCategory = 15) # 柱长 = 基因数/比例,颜色 = 校正 p 值实际论文常把 GO 的 BP/CC/MF 三个层面并排展示,或用
enrichplot::cnetplot()
画“条目—基因”连接网络图。下图是富集结果示例(模拟数据绘制,仅示意样式):
ORA 有一个明显局限:它需要先设阈值筛出差异基因,阈值两端的基因被“一刀切”,且只回答“是否富集”,不回答“富集的方向”。基因集富集分析(gene set enrichment analysis, GSEA)换个思路:不筛基因,而是把所有基因按与表型的关联强度(如 log2FC)从高到低排序,再看某条通路里的基因是整体偏前(激活/上调)还是偏后(抑制/下调)。
两者的区别一句话:ORA 用“取出来的差异基因”,GSEA 用“全部基因的排序”。
GSEA 的核心统计量是富集分数(enrichment score, ES):从排序顶端往下走,遇到通路基因加分、遇到非通路基因减分,累计曲线偏离 0 的最大值就是 ES。ES 为正表示通路基因集中在排序前段(整体上调)。之后用置换检验评估显著性,得到 NES(标准化 ES)和 FDR。
clusterProfiler 中跑 GSEA(以 KEGG 为例):
genelist <- sort(setNames(res$logFC, rownames(res)), decreasing = TRUE) # 全部基因按 logFC 降序
gl_map <- bitr(names(genelist), fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
genelist <- genelist[gl_map$SYMBOL]
names(genelist) <- gl_map$ENTREZID
gsea_res <- gseKEGG(geneList = genelist,
organism = "hsa",
minGSSize = 10, maxGSSize = 500,
pvalueCutoff = 0.25, # GSEA 常用较宽松的阈值
seed = TRUE)
head(as.data.frame(gsea_res))
gseaplot2(gsea_res, geneSetID = 1, title = "示例通路 GSEA 曲线")
ggsave("figures/fig10_gsea.png", width = 7, height = 5, dpi = 300)gseaplot2
的输出包含三部分:顶部是排序基因的位置标记(黑色竖线代表该通路基因);中部是
ES 累积曲线(富集分数随排序位置的变化);底部是排序度量值(如
logFC)。曲线在左侧冲高,说明通路基因整体偏前(上调)。leading
edge(前沿子集)指曲线达到最大偏移之前的那段基因——“驱动富集”的核心基因,值得重点关注。
GO 版本的 GSEA
用法类似:gseGO(geneList = genelist, OrgDb = org.Hs.eg.db, ont = "BP", ...)。fgsea
包是 GSEA 的更快独立实现,进阶可选。GSEA
需要全部基因的排序向量,这正是第 07 章保留全基因结果表的原因。
bitr 转 ID → enrichGO →
dotplot。enrichKEGG(gene, organism = "hsa"),通路图可用
pathview 把 logFC 着色上去。学完本章,你将能够:
先打个比方。想象一个社交网络:每个人是一个点,朋友关系是两点之间的连线。有的人朋友特别多,消息靠他们一传十、十传百,信息流动高度依赖这些人。蛋白质也类似:一个细胞里有成千上万种蛋白质,它们并不是各干各的,而是通过物理结合、共同参与某个通路等方式“打交道”。把“谁和谁存在相互作用”画成图——节点(node)是蛋白质,边(edge)是相互作用——就得到了蛋白质-蛋白质相互作用(protein-protein interaction, PPI)网络。
hub 基因(hub gene)指网络中连线特别多的节点,通常对应在信号传导、细胞命运决定中起枢纽作用的蛋白。肿瘤研究里有一个朴素但常用的假设:hub 基因一旦异常,会通过它的大量互作伙伴把影响“放大”出去,因此更可能是关键基因(candidate key gene)。在我们这个焦亡课题里,PPI 网络的作用是缩小候选范围:第 7 章的差异基因、焦亡基因列表往往有几十上百个,不可能全部做生存分析;优先挑出“网络位置重要”的 hub 基因来检验,既减少多重检验负担,也让故事有逻辑。
需要提醒:hub ≠ 已证实的驱动基因。它只是“网络位置重要”的线索,后续还要靠生存分析、独立验证乃至实验来检验。
STRING(Search Tool for the Retrieval of Interacting Genes/Proteins,string-db.org)是目前最常用的 PPI 数据库之一。它整合了多种证据来源(实验、数据库注释、共表达、文本挖掘等),为每对互作打一个综合分数(combined score,取值 0~1),分数越高越可信。
操作步骤(网页版,全部是鼠标操作,不需要写代码):
两点提醒:第一,STRING 的分数里包含 textmining(文本挖掘)证据——从文献里“共现”扒出来的关联,可能有噪音,解读时要留意;第二,网页上截的网络图只能当示意图,正式分析请用导出的 TSV 数据。
Cytoscape(cytoscape.org)是开源的网络可视化桌面软件(基于 Java,Windows/Mac 都需先装 Java 运行环境),也是 PPI 分析论文里最常见的出图工具。
基本流程:
网络“看着像”还不够,我们需要量化排序。cytoHubba 是 Cytoscape 的插件(App),提供多种节点重要性打分算法。步骤:
经验上 MCC 比单纯 Degree 更稳健(它同时考虑了节点所在的小团体结构),但不同算法结果会有差异,可把两种算法的 top 列表取交集。cytoHubba 的结果可以直接截图,也可以从面板复制基因列表,供下一步生存分析使用。
下图是 PPI 网络与 hub 基因的示例图(模拟数据绘制,仅演示图形样式与 hub 高亮方式;读者用自己数据跑 STRING + Cytoscape 后得到的是自己的图):
如果暂时不想装 Cytoscape,R 包 igraph 可以做最基本的分析——读入 STRING 的 TSV、计算度、画简单网络:
# install.packages("igraph")
library(igraph)
# 读入 STRING 导出的 TSV(含 node1, node2 等列)
ppi <- read.delim("string_interactions.tsv", stringsAsFactors = FALSE)
# 建无向图:每条边连接两个蛋白
g <- graph_from_data_frame(ppi[, c("node1", "node2")], directed = FALSE)
# 度:每个节点连接的边数
deg <- degree(g)
sort(deg, decreasing = TRUE)[1:10] # 连接最多的前 10 个基因
# 简单可视化(教学演示用;正式发表建议用 Cytoscape 精修出图)
V(g)$size <- deg * 2
plot(g, layout = layout_with_fr(g), vertex.label.cex = 0.6)igraph 是“够用但简陋”的替代:能算度、介数(betweenness)等指标,但交互式调整和出图质量不如 Cytoscape。正式分析建议两者结合:igraph 算指标,Cytoscape 出图。
拿到 hub 基因后,核心问题变成:这些“网络里重要”的基因,是否真的与患者预后有关?比如某个 hub 基因高表达的患者是否活得更短?这需要回到带生存随访的数据(TCGA-LIHC 的临床信息里有生存时间 OS.time 与结局 OS),对每个 hub 基因做 KM 生存分析和 Cox 回归——这正是下一章的内容。换句话说,PPI 网络在这里充当“漏斗”:从几十上百个差异/焦亡基因中先筛出 hub 基因,再逐一检验预后价值,最后用 LASSO 把这些基因压缩成一个风险模型。
学完本章,你将能够:
生存分析(survival analysis)处理的是“到某个事件发生还要多久”的数据。在肿瘤队列里,我们关心的是患者从入组到死亡(或复发)的时间。每个患者都有两个关键变量:
难点在删失(censoring):有些患者到研究结束还活着,有些中途失访,还有些死于其他原因——我们只知道“他至少活了这么久”,并不知道确切的事件时间。这类数据不能扔掉:生存分析的价值正在于正确处理删失,删失患者贡献的是“到删失时点为止仍然存活”这条信息。
KM 曲线(Kaplan-Meier curve):把患者按时间排序,逐段估计存活概率,画成阶梯状曲线。把高表达组和低表达组的两条曲线画在一起,可以直观比较两组的生存差异。log-rank 检验(log-rank test):检验两条曲线是否显著不同的非参数方法,输出 p 值——p < 0.05 表示两组生存差异有统计学意义。注意:p 值只回答“有没有差异”,不回答差异多大;效应大小要看曲线分开的程度和后面的 HR。
还有两个常用概念:中位生存时间(median survival)指存活概率降到 50% 所需的时间,可以从 KM 曲线上读取(曲线与 0.5 水平线的交点),是报告生存结果时最常引用的数字之一;随访时间(follow-up time)指队列观察的时长跨度,通常用中位随访时间描述,它大致决定了 KM 曲线能可靠延伸到多远——随访太短,长时点上的曲线就没有数据支撑。
下图是 KM 曲线的示例图(模拟数据绘制,仅演示样式与 p 值标注方式):
基因表达是连续值,而 KM 曲线和 log-rank 需要分组。常用的做法有两种:
survminer::surv_cutpoint
在所有可能的截点里挑一个让两组差异最显著的阈值。方法 2 看似“更聪明”,但有一个重要风险:数据窥探(data snooping)。在同一份数据上“先找最显著的截点、再用它检验”,p 值会被系统性低估,假阳性升高;而且这个截点是针对当前队列量身定做的,换一个队列往往不成立。因此建议:默认用中位数分组;如果要用 surv_cutpoint,就把它当作探索性结果,必须在独立验证队列中确认,并在论文里如实说明截点来源。另外,分组用的表达值应是标准化、可比的值(如 TPM/FPKM 或 log 变换后),原始 count 不宜直接比较。
以 TCGA-LIHC 为例:假设已有表达矩阵 expr(行 = 基因,列
= 样本)和临床信息 clin(含 OS.time 与 OS
列),分析某个焦亡基因(如 GSDME)的代码如下:
# 依赖包:survival, survminer
# install.packages(c("survival", "survminer"))
library(survival)
library(survminer)
# 组装数据:生存时间、结局、目标基因表达(注意样本顺序与 clin 一致)
dat <- data.frame(
time = clin$OS.time, # 生存时间(单位与后续 Cox/ROC 保持一致)
status = clin$OS, # 0 = 删失/存活,1 = 死亡
expr = as.numeric(expr["GSDME", ])
)
# 中位数分组
dat$group <- ifelse(dat$expr > median(dat$expr), "High", "Low")
dat$group <- factor(dat$group, levels = c("Low", "High"))
# KM 拟合 + 绘图(pval = TRUE 显示 log-rank p 值,risk.table 显示风险人数)
fit <- survfit(Surv(time, status) ~ group, data = dat)
ggsurvplot(fit, data = dat, pval = TRUE, risk.table = TRUE,
xlab = "Time (months)", ylab = "Overall survival",
legend.title = "GSDME")结果解读:p < 0.05 说明该基因的表达高低与生存相关;看曲线中段(中位生存时间附近)两组分开的幅度判断方向——高表达组的曲线更低,说明高表达预后更差。对几十个 hub 基因逐个跑一遍,得到一个“候选预后基因”列表。
KM 只能回答“有没有差异”,Cox 回归(Cox proportional hazards regression)能回答“差多少”。它把某一时刻的死亡风险建模为风险比(hazard ratio, HR):HR = 1 表示无差异;HR > 1 表示该变量对应的风险更高(预后更差);HR < 1 相反。报告时给出 95% 置信区间(95% CI),区间不跨越 1 即认为显著。
# 单因素:只看 GSDME
fit1 <- coxph(Surv(time, status) ~ expr, data = dat)
summary(fit1) # 看 coef、exp(coef) = HR、Pr(>|z|)
# 多因素:校正年龄、性别、分期
dat$age <- clin$age
dat$gender <- clin$gender
dat$stage <- clin$stage
fit2 <- coxph(Surv(time, status) ~ expr + age + gender + stage, data = dat)
summary(fit2)
# 森林图(forest plot):一行一个变量,点 = HR 估计,横线 = 95% CI
ggforest(fit2, data = dat)下图是 Cox 森林图的示例图(模拟数据,仅演示样式):
解读要点:森林图每一行一个变量,圆点是 HR 点估计,横线是 95% CI;横线不穿过中间的竖线(HR = 1)表示该变量显著;“基因在多因素校正后仍显著”是论文里最常引用的结论。
还有一个前提需要交代:Cox
模型依赖比例风险假设(proportional hazards
assumption)——各组之间的风险比随时间大致恒定。可以用
cox.zph(fit2) 做检验,p < 0.05
提示假设可能不成立,此时该变量的 HR
解读要谨慎(分层分析或时变系数是进阶处理)。大多数预后论文会报告这个检验,审稿人也常问。
注意:多因素模型需要足够的事件数(即死亡人数)。经验规则是每个预测变量至少约 10 个事件(events per variable, EPV);事件太少而变量太多时,系数估计极不稳定——这正是下一节用 LASSO 压缩变量的动机之一。
逐个基因做单因素分析有两个问题:多重检验(几十个基因各测一次,假阳性累积)和共线性(焦亡基因常共表达,变量冗余)。LASSO(Least Absolute Shrinkage and Selection Operator,glmnet 包)是一种正则化回归:它给系数加 L1 惩罚,把不重要的变量系数直接压到 0,自动完成“选基因”,同时抑制过拟合。模型的形式为:
风险评分(risk score)= Σ(基因系数 × 基因表达量)
构建流程的关键意识是训练集 / 验证集划分:先在训练集上选基因、定系数,再到验证集检验,绝不能把验证集的信息泄漏进建模。
# install.packages("glmnet")
library(glmnet)
# x:候选基因表达矩阵(行 = 样本,列 = 基因;行顺序须与 y 一致)
X <- t(as.matrix(expr[c("GSDME", "GSDMD", "GSDMB", "CASP1", "IL1B", "IL18"), ]))
y <- cbind(time = clin$OS.time, status = clin$OS) # glmnet 的 Cox 族要求两列矩阵
# 7:3 划分训练 / 验证
set.seed(2024) # 固定随机种子,保证可复现
idx <- sample(1:nrow(X), floor(0.7 * nrow(X)))
trainX <- X[idx, ]; trainY <- y[idx, ]
testX <- X[-idx, ]; testY <- y[-idx, ]
# 10 折交叉验证选择最优 lambda(alpha = 1 即 LASSO,family = "cox" 即 Cox 生存模型)
cvfit <- cv.glmnet(trainX, trainY, family = "cox", alpha = 1)
plot(cvfit) # 两条虚线对应 lambda.min(最小偏差)与 lambda.1se(最简模型)
cvfit$lambda.min
# 取出系数非 0 的基因(即被选入模型的基因)
coefs <- coef(cvfit, s = "lambda.min")
genes <- rownames(coefs)[coefs[, 1] != 0]
# 计算风险评分(type = "link" 返回线性预测值,即 Σ 系数×表达)
risk_train <- as.numeric(predict(cvfit, newx = trainX, s = "lambda.min", type = "link"))
risk_test <- as.numeric(predict(cvfit, newx = testX, s = "lambda.min", type = "link"))lambda 的选择:lambda.min
取交叉验证偏差最小的点;lambda.1se
取“偏差在最小值一个标准误以内、但模型更简约(基因更少)”的点。论文常见
lambda.min,追求简约可用
lambda.1se。得到风险评分后,通常再按中位数把患者分成高危 /
低危组,画两组 KM 曲线验证区分度——这一步训练集、验证集都要做。
一个实现细节:glmnet 默认会把每个变量标准化后再计算(standardize = TRUE),因此各基因表达量级的差异(如有的基因 TPM 上百万、有的只有几十)不会直接扭曲系数;但训练集与验证集的预处理必须完全一致。解读风险评分方向时注意系数符号——系数为正的基因高表达会推高风险评分,两者方向要一致,别把“高危”解释反了。
时间依赖 ROC(time-dependent
ROC):生存数据里“结局是否发生”取决于观察时长,不能直接用普通
ROC。timeROC 包可以在指定时间点(如 1、3、5 年)计算
AUC——AUC
表示“随机抽一个患者,风险评分能多大程度区分他在该时间点是否死亡”。0.5 =
纯随机,越接近 1 越好;肿瘤预后模型做到 0.65~0.75 已算不错,不要期待
0.9+。
# install.packages("timeROC")
library(timeROC)
# 教学演示:把训练/验证的风险评分与生存数据拼回全体(真实分析请保持向量对齐)
risk_all <- c(risk_train, risk_test)
t_all <- c(clin$OS.time[idx], clin$OS.time[-idx])
s_all <- c(clin$OS[idx], clin$OS[-idx])
ROC <- timeROC(T = t_all, delta = s_all, marker = risk_all, cause = 1,
weighting = "marginal",
times = c(365, 1095, 1825), # 1/3/5 年(天),单位必须与 T 一致
iid = TRUE)
ROC$AUC
plot(ROC, time = 365, col = "red")诺模图(nomogram,列线图):把 Cox 模型变成可手算的工具——每个变量按取值给分,把分数相加得到总分,再对应到 1/3/5 年生存概率。用 rms 包:
# install.packages("rms")
library(rms)
dd <- datadist(dat); options(datadist = "dd") # rms 需要先设定数据分布
# rms 版 Cox(必须 x = TRUE, y = TRUE, surv = TRUE 才能算生存概率)
fit_cph <- cph(Surv(time, status) ~ expr + age + stage, data = dat,
x = TRUE, y = TRUE, surv = TRUE)
# 1/3/5 年生存概率函数(时间单位与数据一致)
surv <- Survival(fit_cph)
nom <- nomogram(fit_cph,
fun = list(function(x) surv(365, x),
function(x) surv(1095, x),
function(x) surv(1825, x)),
funlabel = c("1-year OS", "3-year OS", "5-year OS"))
plot(nom)下图是 ROC 曲线与诺模图的示例图(模拟数据,仅演示样式):
进阶评估还有:校准曲线(calibration,比较预测概率与实际观察,rms::calibrate)和决策曲线分析(DCA,评估模型在临床决策中的净获益),高分论文常配图。另外建议把训练集与验证集的
AUC 放在一起报告——两者差距过大提示过拟合,差距小且都高于 0.6
才是“模型真的有用”的证据。
surv_cutpoint
在同一数据上“挑最显著截点再检验”会夸大显著性。默认用中位数分组;探索性截点必须在独立队列验证。学完本章,你将能够:
前面几章的所有分析——差异表达、PPI、KM 生存、LASSO 建模——都是在同一份 TCGA-LIHC 数据上完成的。任何统计建模都会“记住”训练数据里的噪声,尤其当候选基因很多、还用了最优截点时,模型在 TCGA 上表现好是“应该的”,说明不了推广价值。这就是过拟合(overfitting)。
独立验证(independent validation)就是用一份从未参与建模的数据(外部队列)检验同样的结论:如果 hub 基因的高低表达分组、风险模型的高低危分组在验证集里依然显著、AUC 依然可观,审稿人才会相信这是真信号而不是数据巧合。在现在的审稿环境里,“只在训练集显著”几乎必然被质疑;而“训练集发现 + 独立队列验证”是最低限度的证据链,也是本章的主题。
GSE14520 是复旦大学中山医院的 HBV 相关肝细胞癌队列(Affymetrix U133A 2.0 芯片,含约 240 例 HCC 患者的肿瘤与癌旁样本),带有随访信息,是 HCC 生信论文最常用的独立验证队列之一。下载方法见第 6 章(需要联网)。
代码思路(教学演示,真实运行需联网下载):
library(GEOquery)
gse <- getGEO("GSE14520", GSEMatrix = TRUE, getGPL = TRUE)[[1]]
expr <- exprs(gse) # 探针 × 样本 的表达矩阵
pdata <- pData(gse) # 样本信息:用 colnames() 查看列名,
# 找到生存时间与结局列(随访信息在 pData 中)拿到数据后按三步验证:
(教学演示说明:上面是思路与关键代码骨架,正式分析还要处理缺失值、样本匹配、时间单位统一等细节。)
mRNA 表达不等于蛋白表达。人类蛋白图谱(Human Protein Atlas,proteinatlas.org,简称 HPA)收录了数万种蛋白在正常组织与多种癌症中的免疫组化(immunohistochemistry, IHC)染色图像,可免费在线查看,是“mRNA 之外再加一层证据”的常用手段。操作步骤:
注意:HPA 每个基因的 HCC 染色样本数有限,IHC 染色只能作为支持性证据(正文或补充材料的一张图),不能替代定量实验。
肿瘤微环境(tumor microenvironment)中浸润的免疫细胞类型与比例,与预后和治疗反应密切相关。细胞焦亡本身就是一种促炎性细胞死亡(见第 1 章),会释放炎症因子、招募免疫细胞,因此“焦亡基因 × 免疫浸润”是这类论文常见的配套分析。两种主流思路:
# BiocManager::install("GSVA")
library(GSVA)
# 免疫细胞标记基因集(例如从文献整理的 marker 列表,元素为基因符号向量)
# gs <- readRDS("immune_markers.rds")
# score <- gsva(expr, gs, method = "ssgsea") # 行 = 样本(新旧版本参数写法略有差异)拿到浸润分数后,可以做的分析有:各免疫细胞在高危/低危组间的差异(wilcoxon 检验 + 箱线图)、浸润分数与风险评分的相关性(cor.test)、焦亡基因表达与免疫浸润的相关热图等。诚实说明:本章只是概念入门;CIBERSORT 的完整流程与免疫结果的解读属于进阶内容,新手应先把“独立验证”做扎实,再决定是否加这一节。
锦上添花的描述性分析:检验 hub 基因表达与临床特征的关系——例如表达在临床分期(stage I–IV)或病理分级(grade)之间是否有差异(多组比较用 Kruskal-Wallis 检验),与性别、HBV 感染等二分类特征的关系(两组比较用 Wilcoxon/Mann-Whitney 检验)。结果用箱线图/小提琴图展示。注意两点:这类分析是描述性的,不能当作因果证据;分组样本量不均衡时结果容易误导,显著性解释要克制。
分析做完了、图有了,但“论文”才是成果的最终形态。这一章把“从结果到可投稿论文”的每一步拆开讲透:结构、写作、图表、投稿、审稿回复。
几乎所有生物医学论文都遵循 IMRaD:Introduction(引言)、Methods(方法)、Results(结果)、and Discussion(讨论),外加 Title/Abstract。生信挖掘论文的每部分装什么:
| 部分 | 字数参考 | 装什么 |
|---|---|---|
| Title 题目 | 1 句 | “Identification and validation of pyroptosis-related genes … in hepatocellular carcinoma” |
| Abstract 摘要 | 200-300 词 | 背景 1 句 → 方法 3-4 句 → 结果 4-5 句 → 结论 1-2 句 |
| Introduction 引言 | 500-800 词 | 疾病负担 → 焦亡机制与研究热度 → 现有缺口 → 本研究假设与工作 |
| Methods 方法 | 600-1000 词 | 数据来源(accession!)→ 每步分析工具+参数 → 统计方法 |
| Results 结果 | 1000-1500 词 | 按 Figure 顺序组织:每段=一个图+一个发现+一个统计数字 |
| Discussion 讨论 | 700-1000 词 | 主要发现重述 → 与文献对比 → 机制解释(推测要标注)→ 局限 → 展望 |
| Conclusion 结论 | 2-3 句 | 一句话收束 |
| 图号 | 内容 | 对应教程章节 | 分析工具 |
|---|---|---|---|
| Figure 1 | 技术路线图 + 研究设计 | 04 | 绘图软件/PPT |
| Figure 2 | 差异表达:火山图 + 热图 + PCA | 07、08 | ggplot2/pheatmap |
| Figure 3 | 功能富集:GO/KEGG 气泡图 + GSEA | 09 | clusterProfiler |
| Figure 4 | PPI 网络 + hub 基因 | 10 | Cytoscape |
| Figure 5 | 生存分析:KM + 森林图 + ROC + 诺模图 | 11 | survminer/rms |
| Figure 6(加分) | 独立验证 + 免疫浸润 | 12 | ggplot2/CIBERSORT |
| Table 1 | 患者临床特征表 | 11 | R 表格 |
| Table 2 | 多因素 Cox 回归结果 | 11 | R 表格 |
本教程的示例图都是教学演示(模拟数据)。你的论文图要用真实数据重新生成,并在
figures/里按 Figure 1-6 编号归档,配analyses/里的生成脚本——图可复现是投稿加分项。
Title 模板(新手直接套):
Identification and validation of [process]-related genes as prognostic biomarkers in [cancer] based on public databases
示例:Identification and validation of pyroptosis-related genes as prognostic biomarkers in hepatocellular carcinoma based on public databases
Abstract 四段式(300 词内): - Background:1-2 句(疾病+焦亡背景+为什么重要); - Methods:数据来源(TCGA-LIHC、GSE14520)+ 分析方法链(一句话); - Results:最关键的 4-5 个数字(多少个差异基因、几个 hub 基因、HR、AUC); - Conclusion:本研究构建了 XX 预后模型,为 XX 提供潜在生物标志物与治疗靶点。
宽:HCC 是全球高发恶性肿瘤,预后差……(引用流行病学数据)
窄:焦亡是一种炎症性程序性细胞死亡,近年发现其在肿瘤发生发展中扮演双重角色……
更窄:然而,焦亡相关基因在 HCC 中的综合表达模式与预后价值尚缺乏系统分析
最窄:因此,本研究基于 TCGA 与 GEO 公共数据,系统评估焦亡相关基因在 HCC 中的
表达、功能与预后价值,并构建预后风险模型。
技巧:每句都有文献支撑([1][2][3]);最后一段明确写出“本研究首次/系统性地……”(要诚实,不要过度宣称)。
可复现是硬标准,逐条写清:
写作公式:“我们用 XX 方法分析了 XX 数据(Figure X)。结果显示……(数字),这表明……(一句解读)”
示例段(配 Figure 2):
我们首先比较了焦亡相关基因在 HCC 肿瘤与癌旁组织中的表达差异(Figure 2A)。结果显示,共有 14 个焦亡相关基因显著差异表达,其中 11 个上调、3 个下调(|log2FC|>1, adj.P<0.05)。热图与 PCA 分析显示肿瘤与癌旁样本可清晰分离(Figure 2B, 2C)。
纪律:结果只陈述“是什么”,不解释“为什么”(那是讨论的事);数字必须与你的分析输出一致(写完用结果表核对一遍)。
生信挖掘类论文的可选期刊(如实介绍,具体以投稿时官网要求为准):
| 期刊类型 | 例子(均为真实存在的期刊) | 特点 |
|---|---|---|
| 生信友好 SCI | Frontiers in Genetics、Frontiers in Oncology、BMC Cancer、PeerJ、Journal of Cancer、Aging、Cancer Cell International | 接受纯生信但越来越多要求独立验证 |
| 综合性期刊 | Scientific Reports、PLOS ONE | 门槛看方法严谨性 |
| 中文核心 | 中华肿瘤防治杂志、中国细胞生物学学报、生物信息学等(按年份以官网目录为准) | 中文写作,适合毕业要求 |
选择步骤: 1. 用你论文的 Title 去 PubMed 搜 3-5 篇最相似的文章,看它们发在哪; 2. 打开目标期刊官网:确认scope(范围)、审稿周期、是否收纯生信、版面费(APC); 3. 看“作者指南”(Author Guidelines)的字数/图表/参考文献格式要求; 4. 备选 3 个期刊,按顺序投(很多期刊拒稿后可转投,但禁止一稿多投)。
准备投稿材料 → 注册期刊投稿系统 → 上传文件(Manuscript + Figures + Tables + Cover letter)
→ 编辑初审(desk reject 高风险期,约 1-2 周)→ 送外审(1-3 个月)
→ 大修/小修(major/minor revision)→ 修回 → 接收(accept)→ 校样(proof)→ 发表
Cover letter 模板(300 词内):
Dear Editor, We submit our manuscript entitled “……” for consideration in [Journal]. [1 段:研究背景与问题] [1 段:我们的发现与意义] [1 句:本文为原创,未一稿多投,无利益冲突,所有作者同意投稿] Sincerely, …
| 拒稿原因 | 如何避免(本教程对应章节) |
|---|---|
| 无新意/复制他人 | 选题加增量(04);文献调研充分(03) |
| 无独立验证 | 第 12 章 GSE14520 验证是标配 |
| 统计方法错误/未校正 | 第 02、07 章(BH 校正等) |
| 图质量差/图注不全 | 第 08 章 + 13.2 |
| 方法不可复现 | 13.3.3(accession、版本、参数全写) |
| 过度解读/无局限 | 13.3.5 局限必写 |
| 语言问题(英文期刊) | 润色(可请人/工具),投稿前通读 |
下一站:写完初稿别急着投——先做一轮自查(第 14 章常见问题),并对照本教程的“自查清单”逐项核对,然后自信地点击”Submit”。
本章覆盖从装环境到投稿最常遇到的 9 类问题,每条按“问题 → 原因 → 解决”展开。遇到报错时,请先读报错信息的第一行与最后几行,再对号入座。
学完本章,你将能够:
问题:install.packages() 或
BiocManager::install() 报错、装不上包。
原因:最常见有三类——① 网络问题:CRAN/Bioconductor
服务器在境外,校园网或公司网络常常很慢甚至连不上;②
包来源搞错:Bioconductor 的包用 install.packages()
装,会提示 “package ‘limma’ is not available for this version of R”;③
依赖缺失:报错尾部写着 “ERROR: dependency ‘xxx’ is not available”;④ R
版本过旧:新包普遍要求 R ≥ 4.x。
解决:
install.packages();Bioconductor 包先
install.packages("BiocManager"),再
BiocManager::install("limma");GitHub 包用
remotes::install_github("用户名/仓库名")。install.packages("ggplot2", repos = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"),或写入
options(repos = c(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))
一劳永逸。问题:getGEO("GSE14520") 转圈半天、报
“Timeout of 60 seconds was reached”,或下载到一半断掉。
原因:GEO 服务器位于美国,跨洋网络不稳定;而 GSE 的 series matrix 文件可能有几十 MB(GSE14520 含 400+ 样本),R 默认约 60 秒的超时很容易不够用。
解决:
options(timeout = 600),下载大文件前必改。getGEO("GSE14520", destdir = "data/"),文件会存到
data/,之后重复读取不再联网。data/,再
getGEO(filename = "data/GSE14520_series_matrix.txt.gz")
离线读取——把“下载”和“分析”分离后,网络问题就不再阻塞分析。问题:表达矩阵行名是 202763_at 这类探针
ID,与基因符号对不上;或一个基因对应多条探针,不知该取哪个。
原因:芯片平台的探针与基因是多对多关系(一条探针可能命中多个转录本,一个基因被多条探针覆盖),映射关系存放在平台(GPL)对应的注释包中;平台错配是“映射结果几乎全 NA”的头号原因。
解决:
!Series_platform_id,确定 GPL
编号(如 GPL3921 = Affymetrix HG-U133A
芯片),安装对应注释包:BiocManager::install("hgu133a.db")。AnnotationDbi::select(hgu133a.db, keys = 探针ID, columns = "SYMBOL", keytype = "PROBEID")
得到探针 → 基因符号的映射。aggregate() 按基因符号取均值(也可取最大信号),先把 NA
过滤掉再聚合。clusterProfiler::bitr() 或 biomaRt 转成 gene symbol。问题:limma 报 “contrasts can be applied only to factors”、结果全是 NA,或倍数变化方向与预期相反。
原因与解决:
factor(group, levels = c("normal", "tumor")) 明确指定,再看
colnames(fit) 确认比较方向后再下结论。str()
检查,as.matrix() 后确认 mode() 为
“numeric”。na.omit()
或补全,再过滤掉全零、全低表达的行。edgeR::DGEList() → calcNormFactors() →
voom() 转换,再进 limma;或直接改用 edgeR/DESeq2。str()
输出贴给搜索引擎,绝大多数是上述五类之一。问题:pheatmap 报错、火山图一片空白、ggplot 报 “Aesthetics must be either length 1 or the same as the data”。
原因与解决:
as.matrix(expr),行名是基因、列名是样本,不要带其他列;行名重复会报错,先
make.unique() 或按基因聚合。str()
确认列名与类型;若取 -log10(adj.P) 时 P 值全为 NA(limma
对某些行无法估计),图自然空白——先过滤 NA 再画。aes()(aes 里只能写数据框的列名)、scale
函数参数拼错。逐行检查映射即可。问题:KM 曲线 P > 0.05,看起来“没戏了”。
原因:样本量小、事件数少(删失比例过高时检验功效不足)、分组方式不佳,或该基因在本队列中确实与预后无关。
规范应对:
survminer::surv_cutpoint() 按数据自动找最佳截点,并在
Methods 里写清楚。问题:enrichGO/enrichKEGG 报 “No gene can be mapped”,或返回 0 条通路、通路少得可怜。
原因:最常见是基因 ID 类型不匹配——clusterProfiler 默认要求 ENTREZID,而你输入的是 gene symbol;其次是差异基因太少、阈值过严;此外 KEGG 收录的通路偏经典代谢与信号通路,免疫相关基因常富集在 GO 条目而 KEGG 通路少,这并不代表分析错了。
解决:
bitr(genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db),再用转换结果做
enrichGO(OrgDb = org.Hs.eg.db, keyType = "ENTREZID")。organism = "hsa"。问题:RStudio 卡死,报 “cannot allocate vector of size …”。
原因:表达矩阵本身不大(371 样本 × 2 万基因仅几十 MB),但中间对象(DGEList、voom 结果、绘图对象)层层复制,叠加浏览器占用就容易撑爆内存。
解决:
rm() 并 gc()。问题:“你只有生信分析,没有实验验证,结论可靠吗?”
回应思路:不是硬杠,而是补证据 + 说实话。
str()
看结构,再谈分析。install.packages("limma") 报错 “package ‘limma’ is
not available”,而同学用 BiocManager::install("limma")
装上了——问题出在哪?下表按分析流程顺序排列,覆盖本教程出现的核心术语;缩写均给出英文全称。
| 中文术语 | 英文 | 一句话解释 |
|---|---|---|
| 转录组 | transcriptome | 细胞或组织在特定状态下全部 RNA 的总和,反映“哪些基因在表达、表达多少”。 |
| 差异表达分析 | differential expression analysis (DEA) | 比较两组(如肿瘤 vs 癌旁)基因表达水平差异是否具有统计学意义。 |
| log2 倍数变化 | log2 fold change (log2FC) | 两组表达均值之比取以 2 为底的对数:log2FC = 1 表示上调 2 倍,-1 表示下调一半。 |
| 校正后 P 值 | adjusted P value (adj.P) | 经多重检验校正后的 P 值,比原始 P 值更保守,用于控制假阳性。 |
| 错误发现率 | false discovery rate (FDR) | 在所有“被判定为显著”的结果中,预期假阳性的比例。 |
| BH 校正 | Benjamini-Hochberg correction | 最常用的 FDR 控制方法,本教程筛选差异基因统一采用(adj.P < 0.05)。 |
| limma | Linear Models for Microarray Data | Bioconductor 经典差异分析包,线性模型 + 经验贝叶斯估计方差;RNA-seq 数据配合 voom 使用。 |
| 富集分析 | enrichment analysis | 检验一组基因(如差异基因)是否在某个功能/通路类别中异常集中。 |
| 基因本体 | Gene Ontology (GO) | 标准化的基因功能注释体系,分生物学过程(BP)、细胞组分(CC)、分子功能(MF)三类。 |
| KEGG | Kyoto Encyclopedia of Genes and Genomes | 收录代谢与信号通路的数据库,enrichKEGG 用于通路富集。 |
| 基因集富集分析 | Gene Set Enrichment Analysis (GSEA) | 不设阈值,用全部基因按表达变化排序,检验某基因集是否整体富集。 |
| 蛋白-蛋白相互作用 | protein-protein interaction (PPI) | 蛋白间直接或间接结合的相互作用关系网络。 |
| hub 基因 | hub gene | PPI 网络中连接度最高、处于网络中心位置的关键基因。 |
| STRING | STRING database | 在线 PPI 数据库,输入基因列表即可构建相互作用网络(string-db.org)。 |
| Cytoscape | Cytoscape | 可视化与分析生物网络的桌面软件,常用于美化 PPI 图。 |
| 生存曲线 | Kaplan-Meier (KM) curve | 以生存概率对时间作图,展示高/低表达组随时间存活差异的曲线。 |
| log-rank 检验 | log-rank test | 比较两条 KM 曲线差异是否显著的非参数检验。 |
| Cox 回归 | Cox proportional hazards regression | 生存分析最常用的回归模型,可纳入多个协变量并输出风险比(HR)。 |
| 风险比 | hazard ratio (HR) | 某因素每变化一个单位(或某组相对参照组)事件风险的倍数,HR > 1 表示风险升高。 |
| LASSO | Least Absolute Shrinkage and Selection Operator | 带 L1 惩罚的回归,自动筛选变量并压缩系数,常用于构建预后风险模型。 |
| 受试者工作特征曲线 | receiver operating characteristic (ROC) | 以假阳性率为横轴、真阳性率为纵轴,评价模型区分能力的曲线。 |
| 曲线下面积 | area under the curve (AUC) | ROC 曲线下的面积,0.5 表示随机猜测,越接近 1 区分能力越强。 |
| 诺模图 | nomogram | 把多因素模型画成“算分表”,用总分预测个体生存概率的可视化工具。 |
| TCGA | The Cancer Genome Atlas | 大型癌症多组学数据库,含 RNA-seq、突变、临床随访(portal.gdc.cancer.gov)。 |
| GEO | Gene Expression Omnibus | NCBI 的基因表达数据库,存储海量芯片与测序数据(ncbi.nlm.nih.gov/geo)。 |
| GSE | GEO Series | GEO 中一个系列编号,代表一项研究/一个数据集(如 GSE14520)。 |
| GSM | GEO Sample | GEO 中单个样本的编号。 |
| GPL | GEO Platform | GEO 中平台的编号(如 GPL3921 = Affymetrix HG-U133A 芯片)。 |
| FPKM | Fragments Per Kilobase per Million | 每百万片段中每千碱基外显子上的片段数,RNA-seq 归一化单位(正逐渐被 TPM 取代)。 |
| TPM | Transcripts Per Million | 每百万转录本中的转录本数,RNA-seq 最常用的归一化单位,跨样本可比。 |
| 原始计数 | counts | 比对到每个基因上的原始读段数,edgeR/DESeq2 直接基于它建模。 |
| 批次效应 | batch effect | 因实验批次(时间、平台、操作者不同)引入的系统性表达差异,可用 limma::removeBatchEffect 等校正。 |
| 删失 | censoring | 生存数据中研究对象在观察期内未发生事件(仍存活或失访),其真实事件时间未知。 |
| 免疫浸润 | immune infiltration | 肿瘤微环境中各类免疫细胞(T 细胞、巨噬细胞等)的组成与丰度。 |
| CIBERSORT | CIBERSORT | 通过反卷积算法从 bulk 转录组估计 22 种免疫细胞相对比例的工具。 |
| 定量 PCR | quantitative PCR (qPCR) | 湿实验定量基因 mRNA 表达的金标准方法,常用于验证生信发现。 |
| 蛋白印迹 | Western blot (WB) | 检测蛋白表达量的经典湿实验方法。 |
| 人类蛋白图谱 | Human Protein Atlas (HPA) | 提供蛋白在组织/细胞中表达与定位的免疫组化数据库(proteinatlas.org)。 |
| GTEx | Genotype-Tissue Expression | 正常人体多组织表达数据库,常与肿瘤数据对照(gtexportal.org)。 |
| cBioPortal | cBioPortal | 交互式探索 TCGA 等肿瘤组学数据的门户(cbioportal.org)。 |
| UCSC Xena | UCSC Xena | 多组学数据可视化平台,可下载整理好的 TCGA/GTEx 表达矩阵(xenabrowser.net)。 |
| Bioconductor | Bioconductor | 面向生信分析的 R 包官方仓库(bioconductor.org)。 |
| BiocManager | BiocManager | 安装 Bioconductor 包的 R
包,用法:BiocManager::install("limma")。 |
| tidyverse | tidyverse | 风格统一的 R 数据科学包集合(ggplot2、dplyr、tidyr 等),本教程数据处理多用它。 |
| 管道符 | pipe operator (%>%) | 把左侧结果传给右侧函数第一个参数的运算符,让代码像流水线一样从左读到右。 |
| 表达矩阵 | expression matrix | 行是基因、列是样本的数值矩阵,是绝大多数下游分析的输入。 |
| 注释包 | annotation package | 存放平台/物种注释关系(探针与基因、ID与功能)的 Bioconductor 包,如 hgu133a.db、org.Hs.eg.db。 |
| 资源 | 类型 | 一句话说明 |
|---|---|---|
| R 官网(r-project.org) | 官方 | R 语言官方发布页与手册,下载 R 与查阅文档。 |
| RStudio / Posit(posit.co) | 官方 | 最常用的 R 集成开发环境(IDE),下载 RStudio Desktop。 |
| Bioconductor(bioconductor.org) | 官方 | 生信 R 包官方仓库,含安装说明与包文档(vignette)。 |
| TCGA GDC 门户(portal.gdc.cancer.gov) | 官方 | TCGA 数据官方下载门户,获取 RNA-seq 表达与临床随访数据。 |
| GEO(ncbi.nlm.nih.gov/geo) | 官方 | NCBI 基因表达数据库,检索与下载 GSE 数据集。 |
| STRING(string-db.org) | 官方 | PPI 网络构建与结果导出的官方站点。 |
| HPA(proteinatlas.org) | 官方 | 蛋白表达与定位数据库,可查 hub 基因的蛋白水平证据。 |
| GTEx(gtexportal.org) | 官方 | 正常组织表达数据库,可作为肿瘤数据的对照。 |
| cBioPortal(cbioportal.org) | 官方 | 探索 TCGA 等数据的交互式门户,适合快速查看单基因概况。 |
| UCSC Xena(xenabrowser.net) | 官方 | 下载整理好的 TCGA/GTEx 表达矩阵,省去自行解析的麻烦。 |
| 资源 | 类型 | 一句话说明 |
|---|---|---|
| R for Data Science(r4ds.hadley.nz;中文版《R 数据科学》) | 教材 | Hadley Wickham 等所著,tidyverse 数据处理与可视化的经典入门书。 |
| Bioconductor 官方工作流(bioconductor.org/help/workflows) | 教程 | 官方维护的端到端分析流程,RNA-seq、差异表达等均有标准做法。 |
| 生信技能树(微信/知乎/B 站搜索“生信技能树”) | 社区资源 | 中文生信社区,提供大量新手教程与答疑;属社区资源,注意甄别时效性。 |
| B 站生信入门系列视频 | 社区资源 | 中文视频课程,搜索“生信入门”“R 语言基础”可找到系列教程(泛称,建议选更新近、口碑好的)。 |
| 《R 语言实战》(R in Action 中文版) | 教材 | 中文 R 入门书,适合零基础通读(按需选用,非必需)。 |
| 资源 | 类型 | 一句话说明 |
|---|---|---|
| 焦亡(pyroptosis)相关综述 | 文献 | 在 PubMed(pubmed.ncbi.nlm.nih.gov)以 “pyroptosis”[Title] AND review 检索最新综述,了解焦亡机制与疾病研究进展;本教程不预设具体文献,请按关键词自行检索最新版本。 |
figures/
目录)均为教学示例图,使用模拟数据绘制,仅用于演示图形样式与解读方法,不代表任何真实研究结果。到这里,本教程的全部内容就结束了:从细胞生物学与生信基础出发,你走过了数据库检索、差异分析、富集分析、PPI 网络、生存模型、独立验证,直到论文写作与投稿。现在,你已经具备完成一个完整生信课题的能力——去创造你的第一个 Figure 1 吧!