分析流程||scanpy单细胞分析流程2-降维聚类及差异基因鉴定

gzh:BBio,欢迎关注

scanpy软件由Theis Lab实验室开发,和Seurat相同都是常用的单细胞数据分析工具。scanpy以anndata数据结构存储的单细胞基因表达数据,包括预处理、可视化、聚类、轨迹推断和差异基因鉴定等功能。基于python实现可以有效处理超过100万个细胞的数据集的强大功能。

以10X官网的3k pbmc数据为例,学习一下scanpy。

参考:

https://scanpy-tutorials.readthedocs.io/en/latest/pbmc3k.html

文章:

SCANPY: large-scale single-cell gene expression data analysis

//使用流程
import numpy as np
import pandas as pd
import scanpy as sc
import re

from matplotlib import pyplot as plt
import matplotlib
matplotlib.use("Agg") #使用非交互式的后端生成图像文件
//读取10X结果,创建AnnData对象
#下载数据
#wget http://cf.10xgenomics.com/samples/cell-exp/1.1.0/pbmc3k/pbmc3k_filtered_gene_bc_matrices.tar.gz -O data/pbmc3k_filtered_gene_bc_matrices.tar.gz

#sc.read_10x_mtx(path, var_names, make_unique=True, cache=False)
adata = sc.read_10x_mtx('data/filtered_gene_bc_matrices/hg19/')
print(adata)
#根据AnnData的数据结果,可以理解为每一行都是一个细胞的数据,每一列都是一个基因的数据
#AnnData object with n_obs × n_vars = 2700 × 32738
#    var: 'gene_ids'

#对于有重复的var_names,添加1、2进行区分
adata.var_names_make_unique()
print(adata.var.head())
//定义绘图函数:sc.pl/scanpy.plotting
def pic(pdf):
    searchObj = re.search( r'(.*).pdf', pdf)
    png = f"{searchObj.group(1)}.png"
    plt.savefig(pdf, bbox_inches="tight")
    plt.savefig(png, bbox_inches="tight", dpi=100)
    plt.close()
//数据预处理:sc.pp/scanpy.preprocessing
#查看高表达基因
sc.pl.highest_expr_genes(adata, n_top=5)
pic("highest_expr_genes.pdf")

#过滤低质量细胞
sc.pp.filter_cells(adata, min_genes=200)
sc.pp.filter_genes(adata, min_cells=3)

#计算线粒体比例
adata.var['mt'] = adata.var_names.str.startswith('MT-')
sc.pp.calculate_qc_metrics(adata, qc_vars=['mt'], percent_top=None, log1p=False, inplace=True)
print(adata)
#AnnData object with n_obs × n_vars = 2700 × 13714
#    obs: 'n_genes', 'n_genes_by_counts', 'total_counts', 'total_counts_mt', #'pct_counts_mt'
#    var: 'gene_ids', 'n_cells', 'mt', 'n_cells_by_counts', 'mean_counts', #'pct_dropout_by_counts', 'total_counts'
print(adata.to_df().head())
#                  AL627309.1  AP006222.2  RP11-206L10.2  RP11-206L10.9  LINC00115  NOC2L # KLHL17  ...  MT-ND6  MT-CYB  AC145212.1  AL592183.1  AL354822.1  PNRC2-1  SRSF10-1
#AAACATACAACCAC-1         0.0         0.0            0.0            0.0        0.0    0.0 #    0.0  ...     0.0     4.0         0.0         0.0         0.0      0.0       0.0
#AAACATTGAGCTAC-1         0.0         0.0            0.0            0.0        0.0    0.0 #    0.0  ...     0.0     8.0         0.0         1.0         0.0      0.0       0.0

#绘图观察数据
#sc.pl.violin(adata, keys, groupby, log=False, use_raw=None, stripplot=True, jitter=True, size=1, order=None, multi_panel=None, xlabel, ylabel, rotation)
sc.pl.violin(adata, ['n_genes_by_counts', 'total_counts', 'pct_counts_mt'],
             jitter=0.4, multi_panel=True)
pic("qc_count.pdf")

sc.pl.scatter(adata, x='total_counts', y='pct_counts_mt')
pic("qc_total_counts_mt.pdf")
sc.pl.scatter(adata, x='total_counts', y='n_genes_by_counts')
pic("qc_total_counts_genes.pdf")

#过滤细胞
adata = adata[adata.obs.n_genes_by_counts < 2500, :]
adata = adata[adata.obs.pct_counts_mt < 5, :]
image-20220210165100782.png
image-20220210165126875.png
//标准化数据
#方法和Seurat中相同
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
print(adata)
//鉴定高变基因
sc.pp.highly_variable_genes(adata, min_mean=0.0125, max_mean=3, min_disp=0.5)
sc.pl.highly_variable_genes(adata)
pic("highly_variable_genes.pdf")
print(adata)
#AnnData object with n_obs × n_vars = 2700 × 13714
#    obs: 'n_genes', 'n_genes_by_counts', 'total_counts', 'total_counts_mt', #'pct_counts_mt'
#    var: 'gene_ids', 'n_cells', 'mt', 'n_cells_by_counts', 'mean_counts', #'pct_dropout_by_counts', 'total_counts', 'highly_variable', 'means', 'dispersions', #'dispersions_norm'
#    uns: 'log1p', 'hvg'
image-20220222092010528.png
//scale
adata.raw = adata
adata = adata[:, adata.var.highly_variable]
sc.pp.regress_out(adata, ['total_counts', 'pct_counts_mt'])
sc.pp.scale(adata, max_value=10)
//降维聚类:sc.tl/scanpy.tools
#pca降维
sc.tl.pca(adata, svd_solver='arpack')
sc.pl.pca(adata, color='CST3')
pic("pca_CST3.pdf")
sc.pl.pca_variance_ratio(adata, log=True)
pic("pca_variance.pdf")
adata.obsm.to_df()[['X_pca1', 'X_pca2']].to_csv('pca.xls')

#UMAP降维
sc.pp.neighbors(adata, n_neighbors=10, n_pcs=40)
sc.tl.umap(adata)
sc.tl.tsne(adata, n_pcs=40)
adata.obsm.to_df()[['X_umap1', 'X_umap2']].to_csv('umap.xls')

#help(sc.tl.umap)
#sc.tl.umap(adata, color, use_raw=None, projection='2d', groups=None, legend_loc='on data', legend_fontweight='bold', legend_fontoutline=True, size=None, color_map=None, palette=None, frameon=True, vmin='p1', vmax='p99', add_outline=False, ncols=4, hspace=0.25)
sc.pl.umap(adata, color=['CST3', 'NKG7', 'PPBP'])
pic("umap_feature_raw.pdf")
sc.pl.umap(adata, color=['CST3', 'NKG7', 'PPBP'], use_raw=False)
pic("umap_feature.pdf")

#聚类
sc.tl.leiden(adata)
print(adata)
sc.pl.umap(adata, color=['leiden', 'CST3', 'NKG7'], ncols=2, legend_loc='on data', legend_fontoutline=True, size=2, color_map='PuBuGn', palette=['red', 'black', '#006400', '#FFFF00', '#FFC1C1', '#FF00FF', '#FFA500', '#C1CDC1'], frameon=True, vmin='p1', vmax='p99', add_outline=True)
pic("umap_cluster_feature.pdf")
adata.write('test.h5ad')
image-20220222092046448.png
image-20220222092104878.png
image-20220222092208398.png
image-20220222092224357.png
image-20220222092252885.png
//差异基因鉴定
#help(sc.tl.rank_genes_groups)
#sc.tl.rank_genes_groups(adata, groupby=None, groups='all', reference='rest', n_genes=None, method=['t-test', 'wilcoxon', 'logreg'], corr_method=['benjamini-hochberg', 'bonferroni'], rankby_abs=False, pts=False)
sc.tl.rank_genes_groups(adata, 'leiden', method='t-test')
sc.pl.rank_genes_groups(adata, n_genes=25, sharey=False)
pic("diff_feature.pdf")

df  = sc.get.rank_genes_groups_df(adata, group="0")
df = df.sort_values(by="scores", ascending=False)
df.to_csv('diff_cluster0.xls', index=0, sep='\t')
#names  scores  logfoldchanges  pvals   pvals_adj
#RPS12  29.401457   0.879537    4.1169846518652114e-159 1.1292065503135902e-155
#RPS27  28.020739   0.85751283  1.1950869901189692e-146 2.0486778728114427e-143
#RPS6   26.885033   0.7554096   5.911086827796277e-135  8.106464475639814e-132
#RPS25  25.821676   0.9273434   6.483621820047835e-127  7.409699136678001e-124
#RPS3   25.549692   0.75146854  6.262897557106957e-123  6.134955507011772e-120

sc.tl.rank_genes_groups(adata, 'leiden', groups=['0'], reference='1', method='wilcoxon')
sc.pl.rank_genes_groups(adata, groups=['0'], n_genes=20)
pic("diff_feature_0vs1.pdf")
sc.pl.rank_genes_groups_violin(adata, groups='0', n_genes=8)
pic("diff_feature_n_genes.pdf")

sc.pl.violin(adata, ['CST3', 'NKG7', 'PPBP'], groupby='leiden')
pic("diff_feature_n_genes.pdf")
image-20220222093439786.png
image-20220222093652242.png
image-20220222093749829.png
//细胞类型注释
marker_genes = ['IL7R', 'CD79A', 'MS4A1', 'CD8A', 'CD8B', 'LYZ', 'CD14',
                'LGALS3', 'S100A8', 'GNLY', 'NKG7', 'KLRB1',
                'FCGR3A', 'MS4A7', 'FCER1A', 'CST3', 'PPBP']
sc.pl.dotplot(adata, marker_genes, groupby='leiden')
pic("leiden_marker_dotplot.pdf")
adata = sc.read('test.h5ad')

new_cluster_names = [
    'CD4 T', 'CD4 T', 'CD14 Monocytes',
    'B', 'CD8 T',
    'FCGR3A Monocytes', 'NK',
    'Dendritic', 'Megakaryocytes']
adata.rename_categories('leiden', new_cluster_names)
#ValueError: Categorical categories must be unique
#不支持多个cluster是同一种细胞类型的格式,换一种方式添加细胞类型
new_cluster_names_unique=list(set(new_cluster_names))
new_cluster_names_unique.sort(key=new_cluster_names.index)
celltype = [new_cluster_names[int(i)] for i in adata.obs.leiden.values.tolist()]
adata.obs.leiden = celltype
adata.obs.leiden = adata.obs.leiden.astype('category')
adata.obs.leiden.cat.set_categories(new_cluster_names_unique, inplace=True)

with plt.rc_context({'figure.figsize':(10, 10)}):
    sc.pl.umap(adata, color='leiden', legend_loc='on data', title='', frameon=True, legend_fontsize='x-small')
pic("celltype_umap.pdf")
sc.pl.dotplot(adata, marker_genes, groupby='leiden')
pic("celltype_marker_dotplot.pdf")
sc.pl.stacked_violin(adata, marker_genes, groupby='leiden', rotation=90)
pic("celltype_marker_violin.pdf")
image-20220222094227486.png
image-20220222094517723.png
image-20220222094557107.png
image-20220222111213823.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容