☰
单细胞转录组数据下载与导入:从GEO/10x到Seurat完整指南
2026/10/1 11:35:09 网站建设 项目流程

1. 单细胞新手第一课:数据从哪来、长什么样、怎么进R

要说scRNA-seq新手最容易被卡住的地方,其实不是聚类、不是找marker基因,而是第一步——数据下载与导入。我见过太多人拿着Seurat教程就开始跑,结果第一步Read10X()就把人劝退了:报错、读进来是空的、基因名变成数字、内存直接爆掉。问题的根源几乎都是同一个:对单细胞数据的基本形态没有概念。

这篇帖子我定位为"scRNA-seq新手操作"系列的第一篇,只解决一件事:搞懂单细胞转录组数据到底从哪儿下载、以什么格式存在、怎么正确读进R环境。整个过程我会用Markdown(MD)记录下来,顺便分享一下怎么用MD把这类流程性知识做成自己的操作手册——毕竟生信的学习笔记,光靠收藏网址是没有用的。

先说几个必须建立的基础认知。

第一,绝大多数公开单细胞数据集来自10x Genomics平台,它的官方软件Cell Ranger会把测序下机的FASTQ文件处理成一套标准输出。你在GEO上看到的GSE编号系列,点进去之后,样本层是GSM编号,平台是GPL编号。一个GSM样本对应的单细胞数据,通常就是Cell Ranger处理好的那个结果文件夹或h5文件。这些才是我们真正要下载的核心资产。

第二,单细胞数据不是一张大表,而是"三个文件一套体系"。标准的filtered_feature_bc_matrix目录下有三个文件:barcodes.tsv.gz、features.tsv.gz、matrix.mtx.gz。很多新手第一次见到这三个文件会懵:为什么不是表达矩阵.csv?因为单细胞表达矩阵极其稀疏(绝大多数基因在绝大多数细胞里表达量为0),如果用CSV存,一个10万细胞的数据集轻松超过5GB,而用稀疏矩阵格式存储,可能只有一两百MB。理解这个逻辑,后面你就不容易在导入环节出错。

第三,也是最重要的一点:不要跳过数据来源的确认直接开跑。有的数据集是10x官网提供的示例数据,有的在GEO的supplementary文件里,有的需要去SRA数据库下载原始FASTQ重新跑Cell Ranger。三种来源的下载方式和后续处理流程完全不同,搞混了,后面每一步都是错。

这一篇,我们就从"下载"这个动作之前的决策开始讲,一步步走到Seurat对象在R里构建成功。

2. 公共数据下载:先选源头,再选工具

2.1 四个主要的数据来源,分别是什么场景

我在实际推荐新手的顺序是这样的:

数据来源获取内容适合场景注意点
GEO supplementary文件Cell Ranger输出的矩阵/h5只想快速做下游分析下载最省事,缺点是文件可能过期
10x Genomics官网数据集官方处理好的示例数据练习标准流程数据质量最好,适合新手跟练
Array Express / ENA镜像数据GEO访问慢时的替代与GEO数据实质相同
NCBI SRA原始FASTQ想自己跑上游流程数据量大,动辄几十GB

对第一课来说,优先选择GEO或10x官网已经处理好的矩阵数据,不要一上来就碰SRA原始数据。我见过太多新手下载几十GB的FASTQ,然后卡在跑Cell Ranger这一步,一周时间就没了。上游分析是另一个技能树,先把下游流程跑通再说。

那GEO怎么判断它有没有"处理好的矩阵"?看supplementary file那一栏,如果出现_filtered_feature_bc_matrix.tar.gz、.h5、.mtx之类的东西,就是现成的。举个例子,GSE系列页面的"Supplementary file"列表里,经常能看到GSEXXXXX_RAW.tar,里面就包含了每个样本的矩阵文件。

2.2 实操:用wget和curl从GEO下载

这里给出一个我用着很顺手的下载流程。假设你已经确定了GSE123456这个系列:

# 1. 先创建项目目录,养成好习惯 mkdir -p scRNA_project/01_raw_data cd scRNA_project/01_raw_data # 2. 用curl看GEO页面的supplementary文件列表,或者直接在浏览器里右键复制链接 # 下载tar包(注意替换成实际的URL) wget -c "https://ftp.ncbi.nlm.nih.gov/geo/series/GSE123nnn/GSE123456/suppl/GSE123456_RAW.tar" # 3. 解压(tar的z参数就是解压gzip压缩包) tar -zxvf GSE123456_RAW.tar # 4. 如果里面还嵌套了压缩文件,再逐层解压 gunzip *.gz

wget -c里的-c参数是断点续传,下载大文件时一旦网络中断,重新执行就能从断点继续,这个参数我基本每次都加。GEO的FTP走HTTPS协议,国内环境有时候会掉线,断点续传就是救命稻草。

如果你要用curl,注意它默认不支持断点续传,需要加-C -参数:

curl -C - -O "https://ftp.ncbi.nlm.nih.gov/geo/series/GSE123nnn/GSE123456/suppl/GSE123456_RAW.tar"

2.3 校验文件完整性:别让下载坑了你一整晚

下载完了就解压?先别急。NCBI的FTP服务器在维护期间或大流量时期,文件传输损坏的概率并不低。你辛辛苦苦解压完了,读进R发现矩阵残缺,回头看才发现是下载就不完整——这种时间浪费完全可以避免。

Linux环境下用md5sum校验:

# 先看服务器端给的MD5值(GEO下载页通常提供或可以从README中找到) md5sum GSE123456_RAW.tar

Windows用户用PowerShell:

Get-FileHash -Algorithm MD5 .\GSE123456_RAW.tar

提示:如果页面没有明确标注MD5值,可以比对文件大小。GEO页面会显示文件的字节数,ls -l看一下本地文件大小是否一致。大小一致的前提下,解压报错率极低。

下载这块我还想多说一句:千万不要用浏览器直接下载这些tar包。不是不能用,而是浏览器下载不支持自动化、容易中断、也不方便记录命令。生信操作讲究可重现,你的每一步命令都应该能写进脚本、记录在MD笔记里——这也是我坚持用命令行的原因。

3. 三个文件一个h5:把Cell Ranger的输出彻底吃透

3.1 barcodes.tsv.gz——细胞的身份证

barcodes.tsv.gz这个文件里每一行就是一个细胞的barcode序列(通常是16bp的碱基序列,后面可能带-1这样的后缀)。它的行数,就是你这个样本里检测到的细胞总数。

这里有个新手经常困惑的点:为什么barcode也叫"细胞身份证"?因为10x平台的设计逻辑是,每个微滴(GEM)里包裹一个带有独特barcode序列的磁珠,测序之后,所有来自同一个微滴的reads都带有相同的barcode。生信流程按barcode把reads归堆,就能推断每个barcode代表一个细胞。所以这个文件基本上决定了矩阵的列数。

3.2 features.tsv.gz——基因清单

老版本叫genes.tsv.gz,10x后来考虑到非基因特征(比如抗体捕获的蛋白表达)的存在,改名为features。每一行对应一个检测到的特征,通常三列:基因ID(ENSEMBL编号)、基因符号(比如TP53)、特征类型(Gene Expression / Antibody Capture等)。

它的行数决定矩阵的行数。这个文件里的基因顺序,和矩阵文件里的行顺序是严格对应的——这个对应关系特别重要,后面手动导入时你要是打乱了顺序,表达矩阵就全乱了。

3.3 matrix.mtx.gz——表达矩阵的稀疏存储

Matrix Market格式,%%MatrixMarket matrix coordinate integer general开头,前三行注释,然后是行数 列数 非零值个数,接着每行是行索引 列索引 表达量。

关键点:索引都是从1开始的,不是0。而且索引1对应的就是features.tsv.gz里的第一个基因、barcodes.tsv.gz里的第一个细胞。这个格式本质上就是一个稀疏矩阵的存储方案,只记录非零元素的位置和数值。

我用生活化方式解释一下:想象一个班级考勤表,横轴是学生,纵轴是课程,单元格里是出勤次数。大部分学生大部分课程出勤为0,这张表如果全量记录就太浪费了。稀疏格式只记录"谁在哪门课出了几次勤"这几行信息,座位号就是索引。读回程序时,再根据座位号把矩阵还原。

3.4 H5文件——另一种封装

除了三件套,你还会经常见到filtered_feature_bc_matrix.h5。它本质上是把上面三个文件用一个HDF5容器打包起来,内部按组(group)组织,每个数据集(dataset)对应barcodes、features、matrix。好处是传输方便、一个文件搞定;坏处是如果你要"看"里面的内容,不能直接zcat了,得用R/python的专用库。

提示:h5文件内部其实还分matrix和features两组,Seurat的Read10X_h5()会自动处理,但你要是在Python里用h5py手动读,就得自己理清楚组名和键名。新手阶段直接用Read10X_h5()就行。

3.5 下载到本地之后,先别急着读R,先用命令看看

这一步是我强推的防呆操作。在正式导入之前,先在命令行里确认文件结构和内容长什么样:

# 查看三个文件是否存在,大小是否合理 ls -lh filtered_feature_bc_matrix/ # 查看barcode数量(去掉压缩直接用zcat,head看前几行) zcat filtered_feature_bc_matrix/barcodes.tsv.gz | head zcat filtered_feature_bc_matrix/barcodes.tsv.gz | wc -l # 查看基因文件前几行 zcat filtered_feature_bc_matrix/features.tsv.gz | head # 查看矩阵的维度声明 zcat filtered_feature_bc_matrix/matrix.mtx.gz | head

matrix.mtx.gz的第四行(前几行注释去掉后)直接告诉你基因数 细胞数 非零值个数。如果细胞数跟barcodes.tsv.gz的行数对不上,文件基本是有问题的。这些检查只需要不到一分钟,能帮你规避后面所有莫名其妙的报错。

4. Seurat导入的三条路,以及背后对数据结构的理解

4.1 三件套目录导入:Read10X的经典姿势

这是最标准的读法。前提是目录结构必须像下面这样组织清楚——注意Read10X()要求传入的是包含三个文件的目录路径,而不是某个文件的路径:

library(Seurat) # 目录结构要求: # filtered_feature_bc_matrix/ # ├── barcodes.tsv.gz # ├── features.tsv.gz # └── matrix.mtx.gz # 读取矩阵 count_matrix <- Read10X(data.dir = "filtered_feature_bc_matrix/") # 查看矩阵结构 dim(count_matrix) # 行列分别是基因数 x 细胞数

Read10X()返回的是一个dgCMatrix类的稀疏矩阵对象。这个dgCMatrix是Matrix包里的压缩稀疏列格式,你可以把它简单理解为"按列分组存储非零值"。单细胞矩阵动辄几万基因几万细胞,用基础R的matrix对象直接存,内存能吃掉几十GB;转成dgCMatrix,往往只需要原来的十分之一甚至更少内存。

4.2 H5文件导入:一条命令搞定

如果你的数据是filtered_feature_bc_matrix.h5:

count_matrix <- Read10X_h5("filtered_feature_bc_matrix.h5") # 如果读出来是列表结构(因为h5里可能包含多个组),取第一个 # 通常就是Gene Expression矩阵 if (is.list(count_matrix)) { count_matrix <- count_matrix$`Gene Expression` }

这里有个我自己踩过的坑:部分由Cell Ranger 7以上版本生成的h5文件,内部结构多了一层group,直接Read10X_h5()返回的可能是list,尤其是还包含Antibody Capture模块时。所以读完之后务必str(count_matrix)看一眼类型,别拿了list去创建Seurat对象,会报一个莫名其妙的错误。

4.3 手动构建表达矩阵:理解数据结构的最短路径

这条路径不打紧所有人都用,但我强烈建议新手至少手动操作一遍,因为你会发现对数据的理解彻底不一样了。

流程是这样的:用data.table::fread读barcodes和features,用Matrix::readMM读矩阵,然后把稀疏矩阵的行名列名贴上:

library(Matrix) library(data.table) # 1. 读三个文件 barcodes <- fread("filtered_feature_bc_matrix/barcodes.tsv.gz", header = FALSE) features <- fread("filtered_feature_bc_matrix/features.tsv.gz", header = FALSE) # 2. 读矩阵:注意readMM读出来的行名列名都是默认数字索引,需要自己贴 count_matrix_sparse <- readMM("filtered_feature_bc_matrix/matrix.mtx.gz") # 3. 给矩阵赋予行列名 rownames(count_matrix_sparse) <- features$V2 # 基因符号 colnames(count_matrix_sparse) <- barcodes$V1 # 细胞barcode # 4. 转换成稀疏格式(readMM返回的可能是dgTMatrix,规范化为dgCMatrix) count_matrix_sparse <- as(count_matrix_sparse, "CsparseMatrix") # 5. 创建Seurat对象 seurat_obj <- CreateSeuratObject(counts = count_matrix_sparse, project = "my_project")

这几行代码你亲手敲一遍,就彻底明白三个文件各自扮演什么角色了。之后遇到行列名对不上、维度报错这类问题,你自己就能秒定位。

4.4 数据导入之后立即做的三个检查

矩阵读进来了,别急着下一步。我每次都会做三个固定检查,这个名字我给它叫"快速体检":

# 1. 维度检查:一般细胞数在几千到几万之间 dim(seurat_obj) # 2. 基因覆盖度:看看有名的marker基因在不在 # 比如人类PBMC数据里,CD3D应该出现在行列信息里 "CD3D" %in% rownames(seurat_obj) # 3. 表达量范围:count矩阵里应该是非负整数 summary(seurat_obj@assays$RNA$counts@x[1:1000])

第三个检查容易被忽略。有些数据源下载的矩阵经过某种标准化(比如CPM、TPM),它不是整数count值。Seurat的下游流程——特别是NormalizeData()里的LogNormalize——在设计时默认输入是raw count。你要是给一个已经标准化的矩阵进去,结果就是下游的差异基因全乱套。

5. 新手导入期最高频的翻车现场与排查链路

5.1 "列名怎么变成了1、2、3?"——版本与自动去重问题

这是Seurat新手最经典的一个报错场景:你用自己的方式手动读了表达矩阵,rownames设成了基因名,可一跑CreateSeuratObject,发现行名变成了1-1-1、1-2-1之类的奇怪字符串。

为什么会这样?因为CreateSeuratObject在遇到重复的基因名时,会调用make.unique()和make.names()自动修正,把重复名字加上序号。如果矩阵的行名列名早就丢失了空值,它就会生成一串编号。

排查链路应该是:先看rownames(count_matrix)是不是NA或空字符串;再看features.tsv.gz的第二列是不是真的非空;确认不是10x新版输出的feature类型里多了第四列导致列偏移。我在手动导入那一节让你直接把第二列作为基因名,就是为了提前规避这种问题。

5.2 "Error: cannot allocate vector of size..."内存不足

这个报错在新手的16G内存笔记本上非常常见。原因通常是:你把一个dgCMatrix对象转成了普通matrix,或者readMM默认读成了全量稠密矩阵。

排查链路:

  • 用object.size(count_matrix)看看矩阵占多少内存
  • 确认用library(Matrix)之后,读入的是稀疏格式,而不是基础R的as.matrix结果
  • Seurat对象本身还会拷贝数据,创建时CreateSeuratObject内部会多存一个counts副本,内存占用大约翻倍

我自己的经验是:如果细胞数超过5万,16G内存就开始紧张了。这时候可以考虑一个取巧方案,先用Read10X读入,然后立刻用subset按基因表达量总量过滤掉低质量细胞,删除稀疏矩阵里全是0的行,确实能省不少内存。

5.3 文件不完整的坑:tar包只解压出一半

前几天还有个朋友问我,解压GSE_RAW.tar之后,filtered_feature_bc_matrix目录是空的。我当时让他先跑了一句:

tar -tf GSE_RAW.tar | head -50

tar -tf是列出压缩包内容的命令,不实际解压。结果显示,tar包里面确实只有部分文件——这说明下载的时候包就不完整,或者GEO在打包时就漏了文件。这种情况别再反复解压了,直接回到GEO页面看原始文件列表,大概率能发现_RAW.tar旁边的单独文件链接,或者去ENA镜像重新下载。

5.4 边读边跑:给Seurat新手的一条忠告

最后说个实操习惯,不算报错但很多人栽过:在控制台里一行行跑代码,而不是把整个脚本一次性source。用RStudio也好、用命令行R也好,导入环节一定要边跑边检查每行的结构输出。如果你是先写好整个脚本再运行,一旦中间某行数据结构不对,后面全乱套,而且报错信息会被淹没在一堆warning里。

比如你运行完Read10X()之后,立刻在控制台敲dim()和class()确认了再往下。这是最朴素也最有效的防错方式。等这一套流程你都验证过一遍了,再把脚本整理进MD笔记,下次就能一个脚本直接跑完。

6. 用Markdown沉淀一套属于自己的单细胞操作手册

6.1 为什么生信学习笔记用MD而不是Word或单纯的收藏夹

我自己的学习习惯是:所有生信流程必须用Markdown记录,而且每个项目一个MD文件。原因很现实:

第一,MD文件是纯文本,体积小、版本管理方便,可以直接用git追踪改动。你今天跑通的代码,明天你改了参数,到底哪里变了?用git diff对比两个版本一目了然,Word做不到。

第二,MD天生支持代码块。写R代码的时候,用三个反引号括起来,语法高亮、复制方便,你回看笔记时直接把代码复制出来就能跑。Word里贴代码经常被自动换行和格式化搅成一团。

第三,MD可以嵌入公式、表格、图片,完全够记笔记用。生信笔记里你经常要记录矩阵格式、命令参数、表格对比,这些都用得上。

6.2 一个可以直接复制的单细胞项目MD模板

我自己跑scRNA-seq项目的笔记结构是这样的,你可以直接抄:

# 项目名:样本XXX的单细胞转录组分析 ## 1. 项目信息 - 数据集编号(GSE/GSM/E-MTAB...) - 组织/物种 - 10x版本与Cell Ranger版本 - 分析日期 ## 2. 数据下载 ### 2.1 来源 - 数据库链接 - 文件列表 ### 2.2 下载命令 ``Bash wget -c "URL" `` ## 3. 导入与质控 ### 3.1 导入代码 ``R library(Seurat) counts <- Read10X("filtered_feature_bc_matrix/") seurat_obj <- CreateSeuratObject(counts) `` ### 3.2 关键结果 - 细胞数、基因数 - QC指标截图 ## 4. 踩坑记录 - 问题描述 - 报错信息 - 解决方案

这个模板的精髓在于:把踩坑记录放在正文里。很多人笔记只有代码流程,没有坑记录,过一个月再回来遇到同样的问题,又得重新排查一遍,太亏了。

6.3 几个MD语法细节,新手容易踩

根据我自己的使用体验,在MD里记录生信内容有几个细节值得注意:

代码块中的尖括号问题。在MD中,<和>原本可能被识别成HTML标签。你在笔记里写readMM("matrix.mtx.gz")这种代码时没问题,但如果直接在段落里写<script>就会被当作HTML标签吞掉显示不出来。解决办法很简单:敏感的<>内容一律放进代码块(反引号包裹),代码块内部不会触发HTML解析。

图片插入路径。有些MD编辑器支持直接拖拽图片,但生成的路径是本地的绝对路径。这个文件你换一个文件夹打开笔记,图片就断了。更可靠的做法是:在项目里建一个assets/或figures/目录,用相对路径![](./figures/01_qc.png)引用图片。这样整个项目文件夹一起搬运或上传git,图片都能正常显示。

表格语法支持度。MD标准表格语法是| 列1 | 列2 |。绝大多数编辑器支持得很好了,但如果你用Typora或VS Code的MD插件,表格渲染稍有差异,问题不大。真正要注意的是:表格单元格里如果出现竖线|,需要用反斜杠转义,写成\|,否则表格结构会乱掉。

链接和引用格式。记录数据库链接时,建议用[链接文字](URL)的形式,别光贴一个裸URL。否则一长串的GEO链接会撑破排版,而且可读性差。

6.4 记录笔记工具选择:编辑器和导出

如果你没有任何偏好,我推荐两个组合:Windows下用Typora(免费阶段可以找替代),macOS/Linux下用VS Code加Markdown插件,或者直接Obsidian。

Obsidian这类基于本地MD文件的双链笔记工具尤其适合生信笔记——你可以把每个数据集、每个基因、每个分析步骤都做成独立页面,然后用链接关联起来,形成自己的知识网络。比如"CD3D"这个基因页面,可以链接到所有分析过它的数据集笔记里,比传统的文件夹笔记好用得多。

关于"md支持img标签吗"这类细节问题,我的经验是:在MD里直接写HTML的<img>标签能生效,但代价是牺牲了纯文本的可移植性。如果你以后可能把笔记同步到GitHub、博客等不同的平台上,建议优先用标准的![alt文字](路径)语法,而不是HTML标签。

另外一个实用技巧:Typora支持把MD导出成PDF和Word。当你需要把笔记发给不做生信的同事看,导出成PDF是最稳妥的。但记得在导出之前检查代码块有没有被截断——长代码行在PDF里会被折行,最好把代码手动格式化到合适的行长。

末尾补一句

我做完了第一个样本的导入之后,第二个样本的处理速度至少快了一倍,不是因为代码熟练了,而是因为第一份MD笔记把每个步骤的坑都写清楚了。所以这篇不只讲scRNA-seq数据下载与导入本身,我更希望你顺手养成用MD记录流程的习惯。

下一篇可以接着写质控——线粒体基因比例、低质量细胞的过滤阈值,这些才是真正决定下游聚类质量的环节。但前提是,你先把数据正确装进Seurat对象里,这一步稳了,后面自然顺。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询