实验记录11:scanpy对scRNA-seq数据的聚类分析

R在读取和处理数据的过程中会将所有的变量和占用都储存在RAM当中,这样一来,对于海量的单细胞RNA-seq数据(尤其是超过250k的细胞量),即使在服务器当中运行,Seurat、metacell、monocle这一类的R包的使用还是会产生内存不足的问题。

但是最近我发现了一个基于python的单细胞基因表达分析包scanpy,能够很好地在我这个仅4G内存的小破机上分析378k的细胞,并且功能丰富程度不亚于Seurat。它包含了数据预处理、可视化、聚类、伪时间分析和轨迹推断、差异表达分析。根据官网描述,scanpy能够有效处理超过1,000,000个细胞的数据集。

Scanpy – Single-Cell Analysis in Python:https://scanpy.readthedocs.io/en/latest/


安装与数据下载

安装好python3之后,终端运行:

pip install scanpy

若安装过程出现问题,请参考:
https://scanpy.readthedocs.io/en/latest/installation.html

骨髓单细胞转录组测序数据下载地址:
https://preview.data.humancellatlas.org


Step0, 读取数据

运行python

import numpy as np
import pandas as pd
import scanpy as sc
# 可以直接读取10Xgenomics的.h5格式数据
adata = sc.read_10x_h5("/Users/shinianyike/Desktop/ica_bone_marrow_h5.h5"
               , genome=None, gex_only=True)
adata.var_names_make_unique()

查看数据:

adata
    AnnData object with n_obs × n_vars = 378000 × 33694 
        var: 'gene_ids'

共378000个细胞,33694个基因。


Step1, 数据预处理

这一步目的将数据进行筛选和过滤,一些测序质量差的数据会让后续的分析产生噪音和干扰,因此我们需要将它们去除。

展示在所有的细胞当中表达占比最高的20个基因。

sc.pl.highest_expr_genes(adata, n_top=20)
表达水平前20的基因.png

基础过滤:
去除表达基因200以下的细胞;
去除在3个细胞以下表达的基因。

sc.pp.filter_cells(adata, min_genes=200)   # 去除表达基因200以下的细胞
sc.pp.filter_genes(adata, min_cells=3)     # 去除在3个细胞以下表达的基因
adata
    AnnData object with n_obs × n_vars = 335618 × 24888 
        obs: 'n_genes'
        var: 'gene_ids', 'n_cells'

共335618个细胞,24888个基因。(可以发现细胞跟基因数量都减少了)

质量控制:

在测序后,有很大比例是低质量的细胞,可能是因为细胞破碎造成的胞质RNA流失,由于线粒体比单个的转录分子要大得多,不容易在破碎的细胞膜中泄漏出去,这样一来就导致测序结果显示线粒体基因的比例在细胞内占比异常高。这一步质量控制的目的就是将这些低质量的细胞去除掉。

计算线粒体基因占所有基因的比例:

mito_genes = adata.var_names.str.startswith('MT-')
# for each cell compute fraction of counts in mito genes vs. all genes
# the `.A1` is only necessary as X is sparse (to transform to a dense array after summing)
adata.obs['percent_mito'] = np.sum(
    adata[:, mito_genes].X, axis=1).A1 / np.sum(adata.X, axis=1).A1
# add the total counts per cell as observations-annotation to adata
adata.obs['n_counts'] = adata.X.sum(axis=1).A1

作小提琴图,查看线粒体基因占比分布:

sc.pl.violin(adata, ['n_genes', 'n_counts', 'percent_mito'],
             jitter=0.4, multi_panel=True)
细胞表达的基因种数、基因数、线粒体基因占比

由于数据点实在太多,小提琴已被数据点覆盖,无法显示出来。

这里还可以做一个散点图,也可以直观地显示出一些异常分布的数据点。

sc.pl.scatter(adata, x='n_counts', y='percent_mito')
sc.pl.scatter(adata, x='n_counts', y='n_genes')
adata
    AnnData object with n_obs × n_vars = 335618 × 24888 
        obs: 'n_genes', 'percent_mito', 'n_counts'
        var: 'gene_ids', 'n_cells'

335618个细胞,24888个基因;
下面这一步进行真正的过滤,根据上面做的图,去除基因数目过多(大于等于4000)和线粒体基因占比过多(大于等于0.3)的细胞:

adata = adata[adata.obs['n_genes'] < 4000, :]
adata = adata[adata.obs['percent_mito'] < 0.3, :]

过滤后查看剩下多少细胞和基因。

adata
    View of AnnData object with n_obs × n_vars = 328435 × 24888 
        obs: 'n_genes', 'percent_mito', 'n_counts'
        var: 'gene_ids', 'n_cells'

328435个细胞,24888个基因。

数据标准化

在绘图之前,还要进行一步数据标准化,将表达量用对数计算一遍,这样有利于绘图和展示。

sc.pp.normalize_per_cell(adata, counts_per_cell_after=1e4)
sc.pp.log1p(adata)
adata.raw = adata # 储存标准化后的AnnaData Object

识别差异表达基因

sc.pp.highly_variable_genes(adata, min_mean=0.0125, max_mean=3, min_disp=0.5)
sc.pl.highly_variable_genes(adata)

将保守的基因去除,留下差异表达的基因用于后续分析。

adata = adata[:, adata.var['highly_variable']]
adata
    View of AnnData object with n_obs × n_vars = 328435 × 1372 
        obs: 'n_genes', 'percent_mito', 'n_counts'
        var: 'gene_ids', 'n_cells', 'highly_variable', 'means', 'dispersions', 'dispersions_norm'

328435个细胞,1372个基因。

回归每个细胞总计数和线粒体基因表达百分比的影响。将数据放缩到方差为1。单细胞数据集可能包含“不感兴趣”的变异来源。这不仅包括技术噪音,还包括批次效应,甚至包括生物变异来源(细胞周期阶段)。正如(Buettner, et al NBT,2015)中所建议的那样,从分析中回归这些信号可以改善下游维数减少和聚类。
这一步高内存需求预警,建议清理电脑缓存,关闭后台不使用的应用。

sc.pp.regress_out(adata, ['n_counts', 'percent_mito'])
    /Users/shinianyike/anaconda3/lib/python3.6/site-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
      from pandas.core import datetools
Scale each gene to unit variance. Clip values exceeding standard deviation 10.
sc.pp.scale(adata, max_value=10)

Step2, 主成分分析

主成分分析是一种将数据降维的分析方法,是考察多个变量间相关性一种多元统计方法,研究如何通过少数几个主成分来揭示多个变量间的内部结构,即从原始变量中导出少数几个主成分,使它们尽可能多地保留原始变量的信息,且彼此间互不相关.通常数学上的处理就是将原来P个指标作线性组合,作为新的综合指标。

sc.tl.pca(adata, svd_solver='arpack') # PCA分析
sc.pl.pca(adata, color='CST3') #绘图

作碎石图,观测主成分的质量。这个图用于选择后续应该使用多少个PC,用于计算细胞间的相邻距离。

sc.pl.pca_variance_ratio(adata, log=True)

在这里先将数据保存,便于后续操作的更改。

adata.write("pca_results.h5ad")

Step3, 聚类分析

计算细胞间的距离:
这里的参数就先按照默认值设定:

sc.pp.neighbors(adata, n_neighbors=10, n_pcs=40)

参数说明:
n_neighbors指的是每个点的邻近点的数量,据评论区@小光amateur 所说neighbors的个数越多,聚类数会越少。
pc的数量依赖于上面所做的碎石图,一般是选在拐点处的的主成分,只需要一个粗略值,不同的pc数量所产生的聚类形状也不同。我后来更改为PC=16,效果比下图要好一些。

将距离嵌入图中:

sc.tl.umap(adata)
sc.pl.umap(adata, color=['CST3', 'NKG7', 'PPBP'])
sc.pl.umap(adata, color=['CST3', 'NKG7', 'PPBP'], use_raw=False)

聚类

sc.tl.louvain(adata)
sc.pl.umap(adata, color=['louvain'])
output_51_0.png

这里得到了29类细胞,每个颜色代表一种。
将数据保存。

adata.write("umap.h5ad")

寻找marker基因

marker基因通常是细胞表面抗原,用于定义出该细胞的细胞类型。
为了定义每个簇属于什么细胞,根据基因的差异表达水平,将每个簇排名前25的基因导出。

sc.tl.rank_genes_groups(adata, 'louvain', method='wilcoxon')
sc.pl.rank_genes_groups(adata, n_genes=25, sharey=False)

下一步的工作是找出每一个簇的marker基因对应的细胞类型,这主要依靠一些数据库或生物学的相关背景知识。


文章已发布到微信公众号:百味科研芝士,欢迎关注。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容