当前位置:首页>python>Python 单细胞分析进阶:详细理解 AnnData 数据结构

Python 单细胞分析进阶:详细理解 AnnData 数据结构

  • 2026-10-11 06:27:21
Python 单细胞分析进阶:详细理解 AnnData 数据结构

Python 单细胞分析进阶:详细理解 AnnData 数据结构

单细胞 Python 分析系列第 4 篇前面我们已经学习了 Python 基础语法、条件语句、循环语句、函数以及 pandas 数据框操作。从这一篇开始,我们正式进入 Python 单细胞分析中最重要的数据对象:AnnData。

很多同学刚开始学习 Scanpy 时,最容易卡在这些名字上:

adata.Xadata.obsadata.varadata.layersadata.rawadata.obsmadata.varmadata.unsadata.obspadata.varp

这些名字看起来比较抽象,但只要记住一个核心思想,后面就会清楚很多:

AnnData 不是一个简单的表达矩阵,而是一个用来统一保存表达矩阵、细胞注释、基因注释和分析结果的对象。

如果说 R 语言中 Seurat 对象是单细胞分析的核心,那么在 Python 生态中,AnnData 就是 Scanpy 分析流程中最核心的数据结构。


本文学习目标

读完这一篇,你应该能够理解:

1. 为什么 Python 单细胞分析需要 AnnData;

2. `adata.X`、`adata.obs`、`adata.var` 分别保存什么;

3. `layers`、`raw`、`obsm`、`uns`、`obsp` 这些结构分别有什么用途;

4. 单样本单细胞基础分析流程中,每一步会改变 AnnData 的哪个槽位;

5. 初学者在使用 AnnData 时最容易踩哪些坑。


    01 为什么需要 AnnData?

    单细胞数据并不只是一个表达矩阵。

    一个完整的单细胞分析对象,通常至少包括:

    • 每个细胞的表达矩阵;
    • 每个细胞的 barcode、样本来源、分组、细胞类型等注释信息;
    • 每个基因的 gene symbol、gene id、高变基因标记等信息;
    • PCA、UMAP、tSNE 等降维结果;
    • Leiden / Louvain 聚类结果;
    • 细胞之间的邻接图;
    • 差异基因分析结果;
    • 如果是空间转录组,还包括空间坐标和组织图片。

    如果把这些信息全部分开保存,分析过程会非常混乱。

    例如,你可能需要同时维护:

    表达矩阵.csv细胞注释.csv基因注释.csvUMAP坐标.csv聚类结果.csv差异基因结果.csv

    这样做不仅容易出错,也很难保证不同文件中的细胞顺序、基因顺序完全一致。

    因此,AnnData 的作用就是:

    把单细胞分析中产生的各种信息,统一装进一个对象里。

    这样后续做质控、降维、聚类、可视化和保存结果时,都可以围绕一个对象完成。


    02 什么是类和对象?

    在 Python 中,很多分析结果不是普通的数据框,而是一个“对象”。

    例如:

    import scanpy as scadata = sc.read_h5ad(”learndata.h5ad”)adata

    这里的 adata 就是一个 AnnData 对象。

    它有点类似于 R 语言中的 Seurat 对象,也可以粗略理解为 R 中的 S4 对象。这个对象里面不仅有表达矩阵,还有细胞信息、基因信息、降维结果和分析结果。

    可以简单理解为:

    AnnData 对象 = 表达矩阵 + 细胞信息 + 基因信息 + 分析结果

    查看对象时,通常会看到类似结果:

    AnnData object with n_obs × n_vars = 3000 × 20000 obs: ... var: ... uns: ... obsm: ... layers: ... obsp: ...

    其中:

    n_obs = observation,观察值数量,通常是细胞数或空间 spot 数n_vars = variable,变量数量,通常是基因数

    对于单细胞 RNA-seq:

    obs = cellvar = gene

    对于空间转录组 Visium 数据:

    obs = spotvar = gene

    03 Python 单细胞分析生态:Scverse

    Python 单细胞分析常用的是Scverse生态。

    可以简单类比:

    R 语言单细胞生态:Seurat / BioconductorPython 单细胞生态:Scanpy / AnnData / Scverse

    常见工具包括:

    图 1 可以帮助大家建立一个整体认识:

    AnnData 负责“装数据”,Scanpy 负责“做分析”,MuData / SpatialData / Squidpy / scvi-tools 负责扩展不同应用场景。


    04 AnnData 的整体结构

    AnnData 全称是:

    Annotated Data

    也就是“带注释的数据”。

    它最核心的结构可以理解为:

    adata.X 表达矩阵adata.obs 细胞注释信息adata.var 基因注释信息adata.layers 不同版本表达矩阵adata.raw 原始表达备份adata.obsm 细胞层面的多维结果adata.varm 基因层面的多维结果adata.uns 非结构化结果adata.obsp 细胞-细胞关系矩阵adata.varp 基因-基因关系矩阵

    可以把 AnnData 想象成一个整理好的“数据收纳箱”。不同的信息放在不同的槽位中,后续分析和可视化时,Scanpy 会自动从这些槽位中读取对应内容。


    05 准备环境和读取数据

    本篇使用 Scanpy 作为示例。

    import scanpy as scimport anndata as adimport pandas as pdimport numpy as npimport matplotlib.pyplot as plt

    读取 .h5ad 文件:

    adata = sc.read_h5ad(”learndata.h5ad”)adata

    读取后建议先运行:

    adata.var_names_make_unique()

    这一步的作用是让基因名唯一,避免后续分析中因为重复基因名产生报错或 warning。

    如果你读取的是 10X mtx 格式,可以使用:

    adata = sc.read_10x_mtx( ”filtered_feature_bc_matrix/”, var_names=”gene_symbols”, cache=True)adata.var_names_make_unique()adata

    如果你读取的是 10X h5 格式,可以使用:

    adata = sc.read_10x_h5(”filtered_feature_bc_matrix.h5”)adata.var_names_make_unique()adata

    06 adata.X:表达矩阵

    adata.X 是 AnnData 中最核心的部分,用来保存表达矩阵。

    adata.X

    查看表达矩阵维度:

    adata.X.shape

    AnnData 中表达矩阵的方向是:

    行:细胞 / spot列:基因

    也就是:

    cells × genes

    这一点非常重要。很多 R 语言分析中,我们更常见的是:

    genes × cells

    所以在 Python 单细胞分析中,一定要注意矩阵方向。

    可以查看对象中的细胞数和基因数:

    adata.n_obsadata.n_vars

    也可以查看细胞名和基因名:

    adata.obs_namesadata.var_names

    07 稀疏矩阵和普通矩阵

    单细胞表达矩阵中有大量 0 值,因此通常用稀疏矩阵保存。

    查看:

    adata.X

    如果显示类似:

    Compressed Sparse Row sparse matrix

    说明 adata.X 是稀疏矩阵。

    如果想转成普通矩阵,可以使用:

    dense_matrix = adata.X.toarray()

    如果想转成 pandas 数据框:

    expr_df = adata.to_df()expr_df.head()

    但是要注意:真实单细胞数据往往很大,直接转成普通矩阵可能会占用大量内存。

    不建议随便对大对象运行:

    adata.X.toarray()

    更推荐只提取少量基因:

    adata[:, [”Dusp3”, ”Dusp5”]].to_df()

    如果是人类数据,基因名通常是大写:

    adata[:, [”DUSP3”, ”DUSP5”]].to_df()

    08 adata.obs:细胞注释信息

    adata.obs 相当于 Seurat 对象中的 metadata。

    查看:

    adata.obs.head()

    查看有哪些列:

    adata.obs.columns

    常见内容包括:

    样本来源实验分组细胞类型n_countsn_genes线粒体比例聚类编号批次信息

    例如计算质控指标:

    adata.var[”mt”] = adata.var_names.str.startswith(”mt-”)sc.pp.calculate_qc_metrics( adata, qc_vars=[”mt”], inplace=True)

    运行后,adata.obs 中会增加:

    n_genes_by_countstotal_countstotal_counts_mtpct_counts_mt

    这些都是每个细胞的质控信息。


    09 在 adata.obs 中添加新信息

    adata.obs 本质上是一个 pandas DataFrame,因此可以像操作普通数据框一样添加新列。

    例如标记线粒体比例较高的细胞:

    adata.obs[”high_mt”] = adata.obs[”pct_counts_mt”] > 20

    也可以添加分组信息:

    adata.obs[”group”] = ”sample1”

    如果有多个样本,可以根据样本名映射分组:

    adata.obs[”group”] = adata.obs[”sample”].map({ ”sample1”: ”Control”, ”sample2”: ”Disease”})

    查看细胞名字:

    adata.obs_names

    通常 adata.obs_names 就是每个细胞的 barcode。


    10 adata.var:基因注释信息

    adata.var 保存的是基因层面的信息。

    查看:

    adata.var.head()

    查看基因名:

    adata.var_names

    查看有哪些基因注释列:

    adata.var.columns

    常见内容包括:

    gene_idsfeature_typeshighly_variablemeansdispersionsmt

    比如下面这句:

    adata.var[”mt”] = adata.var_names.str.startswith(”mt-”)

    就是在 adata.var 中添加一列,标记哪些基因是线粒体基因。

    对于人类数据,线粒体基因通常是大写:

    adata.var[”mt”] = adata.var_names.str.startswith(”MT-”)

    对于小鼠数据,线粒体基因通常是小写:

    adata.var[”mt”] = adata.var_names.str.startswith(”mt-”)

    11 修改基因索引时要谨慎

    有些数据读取后,adata.var_names 是 gene symbol,例如:

    ActbGapdhAlb

    而 adata.var["gene_ids"] 是 Ensembl ID,例如:

    ENSMUSG00000029580

    如果确实想把基因名改成 Ensembl ID,建议先保存原来的 gene symbol:

    adata.var[”gene_symbol”] = adata.var_namesadata.var_names = adata.var[”gene_ids”]

    但是对于初学者,我更建议保留 gene symbol 作为 var_names。因为后面画图时使用 gene symbol 更直观:

    sc.pl.umap(adata, color=”Dusp5”)

    12 adata.layers:保存不同版本的表达矩阵

    adata.layers 非常重要。

    在分析过程中,表达矩阵会经历多个版本:

    原始 counts归一化数据log-normalized 数据scale 后的数据

    如果所有步骤都覆盖到 adata.X 中,后面很容易不知道当前的 adata.X 到底是什么。

    因此,推荐使用 layers 保存不同版本的数据。

    在归一化之前保存原始 counts:

    adata.layers[”counts”] = adata.X.copy()

    归一化和 log 转换:

    sc.pp.normalize_total(adata, target_sum=1e4)sc.pp.log1p(adata)adata.layers[”lognorm”] = adata.X.copy()

    查看 layers:

    adata.layers

    使用某一个 layer 画图:

    sc.pl.matrixplot( adata, var_names=[”Dusp3”, ”Dusp5”], groupby=”clusters”, layer=”lognorm”)

    这里建议大家养成一个习惯:

    不要随便覆盖 adata.X,关键步骤前先保存到 layers。


    13 adata.raw:保存原始表达备份

    除了 layers,AnnData 还有一个常用结构叫 raw。

    一般可以在筛选高变基因之前保存:

    adata.raw = adata.copy()

    它的作用是保留一份原始表达信息。例如后面只保留了高变基因,但画图时还想查看其他基因,就可以从 adata.raw 中调用。

    需要注意:adata.raw 通常只是用于保存表达备份,不建议在整个流程中反复修改。


    14 adata.obsm:存储降维坐标

    adata.obsm 用来存储每个细胞对应的多维信息。

    查看:

    adata.obsm.keys()

    常见内容包括:

    X_pcaX_umapX_tsnespatial

    例如 PCA 结果:

    adata.obsm[”X_pca”]

    UMAP 结果通常保存在:

    adata.obsm[”X_umap”]

    所以当我们运行:

    sc.tl.umap(adata)

    Scanpy 实际上是把 UMAP 坐标保存到了:

    adata.obsm[”X_umap”]

    画图时:

    sc.pl.umap(adata, color=”clusters”)

    本质上就是从 adata.obsm["X_umap"] 中取坐标。

    如果是空间转录组,空间坐标通常保存在:

    adata.obsm[”spatial”]

    15 adata.varm:存储基因层面的多维信息

    adata.varm 和 obsm 类似,但它是针对基因的。

    例如 PCA 中每个基因对主成分的贡献,也就是 loading,可能会保存在:

    adata.varm[”PCs”]

    查看:

    adata.varm.keys()

    对于初学者来说,varm 使用频率没有 obsm 高,但需要知道它保存的是基因层面的多维结果。


    16 adata.uns:存储非结构化信息

    adata.uns 是一个字典结构,用来保存各种非结构化结果。

    查看:

    adata.uns

    或者:

    adata.uns_keys()

    注意这里要加括号。

    常见内容包括:

    neighborsumapleidenrank_genes_groupslog1pspatial

    例如运行聚类:

    sc.tl.leiden(adata, key_added=”clusters”)

    聚类结果会保存在:

    adata.obs[”clusters”]

    而聚类颜色等信息可能保存在:

    adata.uns[”clusters_colors”]

    运行差异分析:

    sc.tl.rank_genes_groups( adata, groupby=”clusters”, method=”wilcoxon”)

    差异分析结果会保存在:

    adata.uns[”rank_genes_groups”]

    提取差异基因结果:

    deg = sc.get.rank_genes_groups_df( adata, group=None)deg.head()

    17 adata.obsp:细胞之间的关系矩阵

    adata.obsp 用来存储细胞和细胞之间的关系矩阵。

    查看:

    adata.obsp.keys()

    当我们运行:

    sc.pp.neighbors(adata)

    Scanpy 会构建细胞之间的近邻图,结果通常保存在:

    adata.obsp[”distances”]adata.obsp[”connectivities”]

    其中:

    distances:细胞之间的距离connectivities:细胞之间的连接强度

    后面的 UMAP 和 Leiden 聚类都依赖这个近邻图。

    也就是说,Scanpy 基础流程一般是:

    PCA → neighbors → UMAP / Leiden

    18 adata.varp:基因之间的关系矩阵

    adata.varp 和 obsp 类似,但它保存的是基因与基因之间的关系。

    例如:

    基因相关性矩阵基因共表达网络基因距离矩阵

    在基础单细胞分析中,varp 不一定经常使用,但在基因网络分析、共表达分析中可能会用到。


    19 结合单样本分析流程理解 AnnData 变化

    理解 AnnData 最好的方法,就是把它和单细胞分析流程结合起来。

    下面用一个基础单样本流程,把 AnnData 每一步发生了什么讲清楚。


    19.1 读取数据

    adata = sc.read_h5ad(”learndata.h5ad”)adata.var_names_make_unique()adata

    此时主要有:

    adata.X:表达矩阵adata.obs:细胞信息adata.var:基因信息

    19.2 计算质控指标

    adata.var[”mt”] = adata.var_names.str.startswith(”mt-”)sc.pp.calculate_qc_metrics( adata, qc_vars=[”mt”], inplace=True)

    运行后,adata.obs 会增加质控指标:

    total_countsn_genes_by_countspct_counts_mt

    这一步主要改变的是:

    adata.obsadata.var

    19.3 质控可视化

    质控指标计算完成后,可以先画图观察数据分布:

    fig, axs = plt.subplots(1, 4, figsize=(15, 4))axs[0].hist(adata.obs[”total_counts”], bins=50)axs[0].set_title(”total_counts”)axs[1].hist(adata.obs[”total_counts”][adata.obs[”total_counts”] < 10000], bins=40)axs[1].set_title(”total_counts < 10000”)axs[2].hist(adata.obs[”n_genes_by_counts”], bins=60)axs[2].set_title(”n_genes_by_counts”)axs[3].hist(adata.obs[”pct_counts_mt”], bins=60)axs[3].set_title(”pct_counts_mt”)plt.tight_layout()plt.show()

    这一步不会改变 AnnData 的主要结构,只是帮助我们确定后面的过滤阈值。


    19.4 质控过滤

    sc.pp.filter_cells(adata, min_counts=5000)sc.pp.filter_cells(adata, max_counts=35000)adata = adata[adata.obs[”pct_counts_mt”] < 20].copy()

    这一步会减少细胞数量,也就是:

    adata.n_obs 变少adata.X 行数变少adata.obs 行数变少

    过滤基因:

    sc.pp.filter_genes(adata, min_cells=10)

    这一步会减少基因数量,也就是:

    adata.n_vars 变少adata.X 列数变少adata.var 行数变少

    查看过滤后的细胞数量:

    print(f”#cells after filter: {adata.n_obs}”)

    19.5 保存原始 counts

    在归一化之前,建议保存原始矩阵:

    adata.layers[”counts”] = adata.X.copy()

    此时:

    adata.layers[”counts”] 保存原始 counts

    19.6 归一化和 log 转换

    sc.pp.normalize_total(adata, target_sum=1e4)sc.pp.log1p(adata)adata.layers[”lognorm”] = adata.X.copy()

    这一步会修改:

    adata.X

    因此保存到 layers["lognorm"] 是一个好习惯。


    19.7 高变基因

    sc.pp.highly_variable_genes( adata, flavor=”seurat”, n_top_genes=2000)

    这一步主要在 adata.var 中增加:

    highly_variablemeansdispersionsdispersions_norm

    可以查看高变基因:

    adata.var[adata.var[”highly_variable”]].head()

    也可以画高变基因图:

    sc.pl.highly_variable_genes(adata)

    19.8 PCA 降维

    sc.pp.pca(adata)

    运行后,结果通常保存到:

    adata.obsm[”X_pca”]adata.varm[”PCs”]adata.uns[”pca”]

    也就是说:

    细胞的 PCA 坐标 → obsm基因的 PCA loading → varmPCA 参数和方差信息 → uns

    可以查看 PCA 结果:

    adata.obsm[”X_pca”].shape

    19.9 构建邻接图

    sc.pp.neighbors(adata)

    运行后,会生成:

    adata.obsp[”distances”]adata.obsp[”connectivities”]adata.uns[”neighbors”]

    这一步是后续 UMAP 和聚类的基础。


    19.10 UMAP 降维

    sc.tl.umap(adata)

    运行后,UMAP 坐标保存在:

    adata.obsm[”X_umap”]

    画图:

    sc.pl.umap( adata, color=[”total_counts”, ”n_genes_by_counts”])

    19.11 Leiden 聚类

    sc.tl.leiden( adata, key_added=”clusters”)

    运行后,聚类结果保存在:

    adata.obs[”clusters”]

    画图:

    sc.pl.umap( adata, color=[”clusters”])

    这时 adata.obs 中就有了每个细胞所属的 cluster。


    19.12 marker 基因识别

    基础聚类完成后,可以寻找每个 cluster 的 marker 基因:

    sc.tl.rank_genes_groups( adata, groupby=”clusters”, method=”wilcoxon”)

    结果会保存到:

    adata.uns[”rank_genes_groups”]

    提取成数据框:

    markers = sc.get.rank_genes_groups_df( adata, group=None)markers.head()

    保存结果:

    markers.to_csv(”cluster_markers.csv”, index=False)

    19.13 保存分析结果

    adata.write_h5ad(”single_sample_processed.h5ad”)

    下次可以直接读取:

    adata = sc.read_h5ad(”single_sample_processed.h5ad”)

    20 一个总结表:每一步改变了什么?


    21 完整单样本基础流程代码

    下面放一份相对完整的单样本基础流程代码,适合作为后续练习模板。

    import scanpy as scimport pandas as pdimport numpy as npimport matplotlib.pyplot as plt# 1. 读取数据adata = sc.read_h5ad(”learndata.h5ad”)adata.var_names_make_unique()# 2. 标记线粒体基因# 小鼠数据通常是 mt-,人类数据通常是 MT-adata.var[”mt”] = adata.var_names.str.startswith(”mt-”)# 3. 计算 QC 指标sc.pp.calculate_qc_metrics( adata, qc_vars=[”mt”], inplace=True)# 4. 查看对象print(adata)print(adata.obs.head())print(adata.var.head())# 5. 质控过滤sc.pp.filter_cells(adata, min_counts=5000)sc.pp.filter_cells(adata, max_counts=35000)adata = adata[adata.obs[”pct_counts_mt”] < 20].copy()sc.pp.filter_genes(adata, min_cells=10)print(f”#cells after filter: {adata.n_obs}”)print(f”#genes after filter: {adata.n_vars}”)# 6. 保存原始 countsadata.layers[”counts”] = adata.X.copy()# 7. 标准化和 log 转换sc.pp.normalize_total(adata, target_sum=1e4)sc.pp.log1p(adata)adata.layers[”lognorm”] = adata.X.copy()# 8. 高变基因sc.pp.highly_variable_genes( adata, flavor=”seurat”, n_top_genes=2000)# 9. PCA / 邻接图 / UMAP / 聚类sc.pp.pca(adata)sc.pp.neighbors(adata)sc.tl.umap(adata)sc.tl.leiden(adata, key_added=”clusters”)# 10. 可视化sc.pl.umap( adata, color=[”total_counts”, ”n_genes_by_counts”, ”pct_counts_mt”, ”clusters”], wspace=0.4)# 11. marker 基因sc.tl.rank_genes_groups( adata, groupby=”clusters”, method=”wilcoxon”)markers = sc.get.rank_genes_groups_df( adata, group=None)markers.to_csv(”cluster_markers.csv”, index=False)# 12. 保存对象adata.write_h5ad(”single_sample_processed.h5ad”)

    22 初学者最容易踩的坑

    22.1 重复基因名

    很多公开数据中可能存在重复基因名。读取数据后建议先运行:

    adata.var_names_make_unique()

    否则后续分析可能会出现 warning 或报错。


    22.2 把 .copy 写成 .copy()

    错误写法:

    adata1 = adata.copy

    正确写法:

    adata1 = adata.copy()

    少了括号,adata1 不是复制出来的新对象,而是一个方法本身。


    22.3 切片后忘记 .copy()

    AnnData 中切片后得到的对象可能只是 view,不是真正独立的 copy。

    不推荐:

    adata_sub = adata[adata.obs[”pct_counts_mt”] < 20]

    推荐:

    adata_sub = adata[adata.obs[”pct_counts_mt”] < 20].copy()

    尤其是后面要修改 adata_sub.obs 或 adata_sub.X 时,建议一定加 .copy()。


    22.4 不清楚当前 adata.X 是什么

    分析流程中,adata.X 经常会被修改。因此建议在关键步骤保存不同版本:

    adata.layers[”counts”] = adata.X.copy()sc.pp.normalize_total(adata, target_sum=1e4)sc.pp.log1p(adata)adata.layers[”lognorm”] = adata.X.copy()

    这样后面需要原始 counts 或 lognorm 数据时,就不会混乱。


    22.5 线粒体基因大小写写错

    人类数据:

    adata.var[”mt”] = adata.var_names.str.startswith(”MT-”)

    小鼠数据:

    adata.var[”mt”] = adata.var_names.str.startswith(”mt-”)

    如果大小写写错,pct_counts_mt 可能全部为 0 或计算异常。


    22.6 随意把大矩阵转成普通矩阵

    不推荐对大数据直接运行:

    adata.X.toarray()

    因为这样可能会占用大量内存。

    更推荐:

    adata[:, [”Dusp3”, ”Dusp5”]].to_df()

    23 保存和读取 h5ad 文件

    分析完成后,可以保存:

    adata.write_h5ad(”single_sample_processed.h5ad”)

    下次直接读取:

    adata = sc.read_h5ad(”single_sample_processed.h5ad”)

    .h5ad 的好处是可以把 AnnData 对象中的大多数内容一起保存,包括:

    表达矩阵细胞注释基因注释降维结果聚类结果邻接图差异分析结果

    所以它非常适合作为 Python 单细胞分析的中间结果文件。


    24 AnnData 和 Seurat 对象的简单类比

    对于熟悉 Seurat 的同学,可以用下面这个表帮助理解:

    这个类比并不是完全一一对应,但对于初学者理解 AnnData 很有帮助。


    25 本篇小结

    这一篇主要介绍了 Python 单细胞分析中最核心的数据结构:AnnData。

    可以用一句话总结:

    AnnData 是 Python 单细胞分析中用来统一存储表达矩阵、细胞注释、基因注释和分析结果的核心对象。

    其中最重要的结构包括:

    adata.X 表达矩阵adata.obs 细胞信息adata.var 基因信息adata.layers 多版本表达矩阵adata.obsm 细胞降维结果adata.varm 基因多维结果adata.uns 非结构化分析结果adata.obsp 细胞关系矩阵adata.varp 基因关系矩阵adata.raw 原始表达备份

    对于初学者来说,建议重点掌握:

    X、obs、var、layers、obsm、uns、obsp

    这几个结构理解清楚之后,再看 Scanpy 的单细胞分析流程就会容易很多。


    26 学习五问

    最后留 5 个问题,帮助大家检查自己是否真正理解了 AnnData:

      如果这 5 个问题你都能回答出来,说明你已经理解了 AnnData 的核心结构。


      27 下期预告

      下一篇我们可以继续介绍:

      不同格式单细胞数据的读取方式,以及单细胞基础分析 pipeline。

      包括:

      10X mtx 文件filtered_feature_bc_matrix.h5h5ad 文件loom 文件csv / tsv 表达矩阵空间转录组 Visium 数据

      然后进入完整的单样本基础分析流程:

      读取数据质控过滤标准化高变基因PCA邻接图UMAP聚类marker 基因识别细胞类型注释

      如果你已经读到这里,说明你已经正式从 Python 基础迈入单细胞分析的核心阶段了。


      本篇关键词:Python 单细胞分析、Scanpy、AnnData、adata.X、adata.obs、adata.var、layers、obsm、uns、obsp。

      最新文章

      随机文章