从 GEO 下载表达矩阵
跟完这篇,您能从一个 GSE 编号出发,在 GEO 页面里找到并下载正确的原始表达矩阵文件,解压整理成「行是基因、列是样本」的标准矩阵,顺手取到配套的分组表,直接接到下游差异分析。
先认清 GEO 的三个编号
GEO(Gene Expression Omnibus,NCBI 的公共表达数据库)用三种编号组织数据,看懂它们,您才知道自己在下什么:
| 编号 | 代表 | 例子 |
|---|---|---|
| GSE | 一项研究(Series) | GSE12345 |
| GSM | 一个样本(Sample) | GSM123456 |
| GPL | 测序 / 芯片平台 | GPL24676 |
您通常从一个 GSE 编号起步——它往往写在论文的「Data Availability」一节,或者用 在 GEO 里搜数据集 找到。拿到编号,就能拼出详情页地址:
https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE12345
把末尾的 GSE12345 换成您的编号即可。
打开 GSE 详情页,找到 Supplementary file 区
打开上面的地址,页面从上到下大致是这个顺序:
- 标题 · Summary · Overall design:一句话研究背景和实验设计,先扫一眼确认是不是您要的数据。
- Samples:GSM 样本列表,能看到分组、处理条件。
- Platform:测序或芯片平台(GPL)。
- Citation · Submission date 等元信息。
- Supplementary file:页面最底部的一张表格,列着投稿者上传的处理后文件和下载链接。
关键:原始 count 矩阵基本都在最底部的 Supplementary file 区。这是投稿者自己上传的文件,也是您这趟真正要拿的东西。页面另有一个「Download family」入口里的 series_matrix,后面会说它该用来干什么、又不该用来干什么。
认哪些文件:名字带 count / matrix / raw
做 count 起点的差异分析(DESeq2、edgeR),您要的是原始整数 count——每个基因在每个样本里比对上的读段条数,还没做任何归一化。在 Supplementary file 表里,按文件名找这些线索:
count/counts/raw_countsmatrix/count_matrix/gene_counts- 来自常见定量流程的输出:
featureCounts、htseq、STAR 的ReadsPerGene.out.tab、RSEM 的genes.results GSE12345_RAW.tar:把每个样本一个文件打包在一起,解开后逐样本合并
粗略对照,帮您一眼判断:
| 文件名里出现 | 大概是什么 | 能否直接做 count 差异分析 |
|---|---|---|
raw_counts、count_matrix | 原始整数计数矩阵 | 可以 |
featureCounts、htseq、ReadsPerGene | 定量工具的计数输出 | 可以(可能需合并、去汇总行) |
FPKM、TPM、RPKM、CPM | 已归一化的表达值 | 不建议 |
series_matrix | 见下一节 | 不建议 |
为什么非要原始整数 count:DESeq2、edgeR 的统计模型建立在原始计数上,内部自己做归一化,不能直接喂已经归一化的值——这是这两个方法的既定要求,各自官方 vignette 都写明了,属于标准做法而非可选项。
避开哪些:series_matrix 与「算好的结果」
有几类文件很容易顺手下错,认清它们:
series_matrix.txt.gz:对芯片数据,里面的 VALUE 常是投稿者归一化后的值(可能已取 log2);对 RNA-seq,它常常没有数据表、或放的是归一化值。它真正的长处是打包了每个样本的表型 / 分组信息,拿它读「分组表」很方便(下面就会用到)——但别拿它当原始表达矩阵。- 名字带
FPKM/TPM/RPKM/normalized/log2/CPM:已归一化,适合看趋势、画热图、比较样本内相对高低,不适合做 count-based 差异分析。 - 别人「算好的结果」:比如差异基因列表(DEG table)、通路富集结果表——那是分析的终点,不是您的起点。
诚实说一句边界:有些数据集的投稿者只上传了归一化值,压根没放原始 count。遇到这种,要么按论文里的联系方式问作者要,要么从 SRA 取原始测序 reads 自己比对定量——那超出本篇范围,但您得知道有这种情况,别在一个没有原始 count 的数据集上死磕。
下载与解压
拿到目标文件后,两种下法:
方式一 · 页面点击。直接点 Supplementary file 表里对应文件的下载链接((http) 或 (ftp)),存到本地。
方式二 · 命令行。GEO 的补充文件放在固定规律的 FTP 目录下——把 GSE 编号去掉末三位、补上 nnn 作为上级目录:
# GSE12345 -> 上级目录写成 GSE12nnn
wget -r -np -nd \
"https://ftp.ncbi.nlm.nih.gov/geo/series/GSE12nnn/GSE12345/suppl/"
或者用 R 的 GEOquery 包,它会自动算好路径、下到以 GSE 命名的子文件夹里:
library(GEOquery)
getGEOSuppFiles("GSE12345") # 补充文件下到 ./GSE12345/ 下
下下来的文件多是 .gz(单文件压缩)或 .tar(多文件打包)。解压:
gunzip GSE12345_raw_counts.tsv.gz # 解开单个 .gz
tar -xvf GSE12345_RAW.tar # 解开逐样本打包
其实读进 R 时不必先解压——read.delim 与 data.table::fread 都能直接读 .gz。读之前先偷看前几行,心里有底再读:
# 先看前几行,确认分隔符、有没有表头、数值是不是整数
readLines(gzfile("GSE12345_raw_counts.tsv.gz"), n = 3)
counts <- read.delim("GSE12345_raw_counts.tsv.gz",
row.names = 1, check.names = FALSE)
整理成标准矩阵
下游分析要的目标形状很明确:行是基因、列是样本、值是原始整数 count。对照着核一遍:
- 看一眼结构:
dim(counts)和head(counts),确认行确实是基因、列确实是样本、数值是整数而非小数。 - 基因 ID 设为行名:如果第一列是基因 ID(Ensembl 或 symbol),把它设成行名,别留在数据列里。
- 样本名对齐:列名(样本名)要能和您的分组表一一对上,拼写、大小写、顺序都一致。
- 去掉汇总行、确保整数:htseq 的输出末尾常有几行以
__开头的汇总统计,得去掉。
counts <- counts[!grepl("^__", rownames(counts)), ] # 去掉 htseq 汇总行
counts <- round(as.matrix(counts)) # 确保是整数矩阵
重复基因合并、Ensembl 与 symbol 互转、和分组表严格对齐这些更细的清洗,完整做法见 表达矩阵整理——那一步做扎实了,差异分析才不会在中途报错或悄悄错。
顺手拿到分组表
差异分析除了 count 矩阵,还需要一张「哪个样本属于哪一组」的分组表(phenotype)。这张表 series_matrix 里就有,用 GEOquery 一步取出,不用照着网页手抄:
library(GEOquery)
gse <- getGEO("GSE12345", GSEMatrix = TRUE) # 下载并解析 series_matrix
eset <- gse[[1]] # 一个平台对应一个元素,多平台会有多个
pheno <- pData(eset) # 每个样本一行的表型表
分组信息(处理 / 对照、时间点、组织来源等)通常散在这几列里,先挑出来看:
# 常见的分组线索多在这些列
pheno[, grep("characteristics|title|source_name",
colnames(pheno), ignore.case = TRUE)]
两点要核对:
- 样本 ID 对得上:
pheno的行名是 GSM 编号,count 矩阵的列名可能是 GSM,也可能是投稿者自己的样本名。两边要能一一对应,必要时按 GSM 做一次映射。 - 分组列干净可用:把
characteristics_ch1里形如treatment: control的文本,整理成一列清爽的因子(如group,取值control/treated),差异分析里当设计变量用。
严格对齐「count 矩阵的列」与「分组表的行」的完整做法,同样见 表达矩阵整理——顺序一旦错位,后面每个基因的组间比较都会跟着错。
在平台上跑一遍
在百沐一下,这一步不用写代码。把您从 GEO 下的补充文件(哪怕还是 .gz)直接上传,说清楚目的——「这是某研究的 RNA-seq 原始 count 补充文件,帮我整理成行基因、列样本的标准矩阵,并和这份分组表对齐」——平台会识别文件、判断是不是原始计数、把矩阵和分组表整理好交还给您。上传数据、讲清要什么即可:组学智能体使用说明 或直接开始 https://app.baimuyixia.com。