20. 基因集富集和通路分析#

   关键要点

在做通路分析之前,使用标准的 scRNA-seq 归一化方法对数据做归一化,并过滤掉在你的数据中基因覆盖率低的基因集。

数据归一化

注意区分基因集富集(gene set enrichment)与基因集活性推断(gene set activity inference)。GSEA 是单细胞研究中广泛使用的基因集检验;Pagoda 2 被发现优于其他通路活性评分工具。如果你的数据集具有复杂的实验设计,可以考虑做 pseudo-bulk 分析,并使用 limma中实现的基因集检验——因为它们与线性模型框架兼容,还能额外考虑基因间的相关性。

基因集富集分析中的零假设
   环境设置
  1. 安装 conda:

    • 在创建环境之前,请确保 conda 已安装在您的系统中。

  2. 保存 yml 内容:

    • 将 yml 选项卡中的内容复制到名为 environment.yml 的文件中。

  3. 创建环境:

    • 打开终端或命令提示符。

    • 运行以下命令:

      conda env create -f environment.yml
      
  4. 激活环境:

    • 创建好环境后,使用以下命令激活它:

      conda activate <environment_name>
      
    • 替换 <environment_name>,名称就是在 environment.yml 文件中指定的那个。在 yml 文件里,它看起来像这样:

      name: <environment_name>
      
  5. 验证安装:

    • 通过运行以下命令,检查环境是否创建成功:

      conda env list
      
name: pathway
channels:
  - conda-forge
  - bioconda
dependencies:
  - conda-forge::python=3.12.11
  - conda-forge::r-base=4.4.3
  - conda-forge::pip
  - conda-forge::rpy2=3.6
  - conda-forge::scanpy=1.11.5
  - conda-forge::scikit-misc
  - bioconda::bioconductor-singlecellexperiment=1.28.0
  - bioconda::bioconductor-edger=4.4.0
  - bioconda::bioconductor-limma=3.62.1
  - bioconda::anndata2ri=1.1
  - conda-forge::r-statmod
  - conda-forge::cffi
  - pip:
      - decoupler

20.1. 动机#

单细胞 RNA-seq 为我们提供了前所未有的洞察,去了解不同条件、组织类型、物种和个体之间细胞类型的变化。对单细胞数据做差异基因表达分析之后,几乎总会接着进行 基因集富集分析,其目的是根据差异表达(DE)基因,找出那些在某个实验条件下(相比对照或其他条件)过度代表(over-represented)的基因程序,例如生物学过程、基因本体(gene ontology)或调控通路。

为了确定在两种条件之间、以细胞类型特异方式富集的通路,首先要选定一组相关的基因集签名(gene set signature),其中每个基因集定义一个生物学过程(例如上皮-间质转化、代谢等)或一条通路(例如 MAPK 信号通路)。对于集合中的每个基因集,会用基因集中出现的 DE 基因计算一个检验统计量,再用它来评估该基因集的富集程度。视所选富集检验的类型而定,计算检验统计量时可能会、也可能不会用到基因表达的测量值。

在本章中,我们首先概述不同类型的基因集富集检验,介绍一些常用的基因签名集合,并讨论通路富集和功能富集分析的总体最佳实践。最后,我们通过演示三种基因集富集分析的分析方法来结束本章。请注意,本章中我们把通路分析、通路富集分析、基因集富集分析和功能分析这几个术语互换使用。

20.2. 通路与基因集集合#

基因集是一份经整理的基因名称(或基因 ID)列表,这些基因通过以往的研究和/或实验已知参与某个生物学过程。分子签名数据库(MSigDB) [Liberzon et al., 2011, Subramanian et al., 2005] 是最全面的数据库,由 9 个基因集集合组成。一些常用的集合是:C5,即基因本体(GO)集合;C2,来自已发表研究的、经整理的基因签名集合,通常是上下文(如组织、条件)特异的,但也包含 KEGG 和 REACTOME 基因签名。对于癌症研究,常用 Hallmark 集合;对于免疫学研究,C7 集合是常见选择。请注意,这些签名主要来自 Bulk-seq 测量,刻画的是连续表型。最近,随着 scRNA-seq 数据集的广泛普及,又出现了一些数据库,它们提供从已发表单细胞研究中整理出的标记列表,用以定义各种组织和物种中的细胞类型。这些包括 CellMarker [Zhang et al., 2019] 和 PanglaoDB [Franzén et al., 2019]。经整理的标记列表并不限于数据库中提供的那些,也可以自己整理。

20.3. 基因集富集分析中的零假设#

基因集检验可以是 competitiveself-contained (根据 Goeman 和 Bühlmann(2007)的定义) [Goeman and Bühlmann, 2007]。竞争性(competitive)基因集检验,检验的是:相对于不在集合中的基因,集合中的基因在差异表达方面是否排名靠前。这里的抽样单位是基因,因此可以用单个样本来做检验(即单样本 GSEA)。该检验需要不在集合中的基因(即背景基因)。而在自包含(self-contained)基因集检验中,抽样单位是受试对象,因此每组需要多个样本,但不需要有不在集合中的基因。自包含基因集检验检验的是:检验集合中的基因是否差异表达,而不考虑数据集中测量的任何其他基因。这两种零假设之间的区别,会影响对基因集富集结果的解读。注意,在生物学数据中存在基因间相关性,即同一通路中基因的表达是相关的。只有少数检验能够容纳基因间相关性,我们稍后会讨论这些方法。关于各种基因集检验的详细解释见 limma 用户手册

20.4. 基因集检验与通路分析#

在 scRNA-seq 数据分析中,基因集富集通常是在细胞聚类或细胞类型上、一次一个地进行的。在某个聚类或细胞类型中差异表达的基因,被用来从选定的集合中识别过度代表的基因集,使用的是简单的超几何检验或 Fisher 精确检验(如 Enrichr [Chen et al., 2013])等。这类检验不需要实际的基因表达测量值和读数来计算富集统计量,因为它们依赖于检验这样一件事有多显著: \(X\) 即与集合中非 DE 基因的数量相比,集合中差异表达的基因数量(在实验中)有多少。

fgsea [Korotkevich et al., 2021] 是更常用的基因集富集检验工具。fgsea 是对成熟的 基因集富集分析 算法在计算上更快的一种实现 [Subramanian et al., 2005],它根据某种预排序(preranked)的基因级检验统计量来计算富集统计量。fgsea 利用基因集中基因的某种带符号统计量(例如差异表达检验得到的 t 统计量、对数倍数变化(logFC)或 p 值)来计算一个富集分数。再用若干大小相同的随机基因集,为该富集分数计算一个经验(从数据估计得到的)零分布,并计算 p 值以确定富集分数的显著性。随后对这些 p 值做多重假设检验校正。GSVA [Hänzelmann et al., 2013] 也是预排序(preranked)基因集富集方法的另一个例子。我们应注意,预排序基因集检验并不专门针对单细胞数据集,它同样适用于 Bulk-seq 测定。

在一组细胞(即聚类或同类型的细胞)中检验基因集富集的另一种方法,是从单细胞构造 pseudo-bulk 样本,并使用为 Bulk RNA-seq 开发的基因集富集方法。有几种自包含和竞争性的基因集富集检验,即 frycamera 已实现于 limma [Ritchie et al., 2015],它们通过线性模型和对检验统计量的经验贝叶斯(Empirical Bayes)压缩,与差异基因表达分析框架兼容 [Smyth, 2005]。线性模型可以通过设计矩阵容纳复杂的实验设计(如受试对象、扰动、批次、嵌套对比、交互作用等)。此外, cameraroast 这两个在 limma 中实现的基因集检验考虑了基因间相关性。而 limma 中的基因集检验也可以应用于(经过适当变换和归一化的)单细胞测量,而无需生成 pseudo-bulk。不过,目前还没有基准测试评估过:当这些方法直接应用于单细胞时,基因集检验结果的准确性如何。

Test

批量或 SC

零假设类型

输入

超几何

两者

竞争性

基因计数

Fisher 精确检验

两者

竞争性

基因计数

GSEA\(^*\)

bulk

竞争性

基因排名

GSVA\(^*\)

bulk

竞争性

基因排名

fgsea

两者

竞争性

基因排名

fry\(^*\)

bulk

自包含

表达矩阵

camera\(^*\)

bulk

竞争性

表达矩阵

roast\(^*\)

bulk

自包含

表达矩阵

表:各基因集检验、适用的测量类型,以及它们所检验的零假设

\(^*\) 这些测试实际上适用于单细胞数据集,尽管其应用于单细胞可能不是常见的做法。

20.4.1. 基因集检验与通路活性推断#

基因集检验,检验的是某条通路在某种条件下相比其他条件是否富集(换句话说,是否过度代表)——例如,在单核细胞群体中,健康供体相比重症 COVID-19 患者。另一种做法是:不检验不同条件之间活性的差异,而是直接在单细胞中、以绝对意义对一条通路或一个基因签名的活性进行评分。一些广泛用于推断单细胞中基因集活性(包括通路活性)的工具包括 VISION [DeTomaso et al., 2019], AUCell [Aibar et al., 2017]、使用 Pagoda2 [Fan et al., 2016, Lake et al., 2018] 进行的通路过离散分析(pathway overdispersion analysis),以及简单的组合 Z 分数 [Lee et al., 2008]

DoRothEA [Garcia-Alonso et al., 2019]PROGENy [Schubert et al., 2018] 属于一类功能分析工具,最初是为在 Bulk RNA 数据中推断转录因子(TF)-靶标活性而开发的。Holland 等人 [Holland et al., 2020] 发现 Bulk RNA-seq 方法 DoRothEAPROGENy 在模拟的 scRNA-seq 数据中具有最佳性能,甚至在单细胞数据存在漏检(drop-out)事件和文库较小的情况下,部分超过了专门为 scRNA-seq 分析设计的工具。Holland 等人还得出结论:通路和 TF 活性推断对基因集的选择比对统计方法更敏感。不过这一观察可能是功能富集分析所特有的,并且可以这样解释:TF-靶标关系是上下文特异的,即某种细胞类型中的 TF-靶标关联,实际上可能不同于另一种细胞类型或组织。

与 Holland 等人相反,Zhang 等人 [Zhang et al., 2020] 发现基于单细胞的工具(具体来说是 Pagoda2)在准确性、稳定性和可扩展性三个方面都优于基于批量的方法。应当指出,通路和基因集活性推断工具本身并不考虑批次效应、或除所关注的生物学变异之外的其他生物学变异。因此,要由数据分析者来确保差异基因表达分析这一步已经正确完成。

此外,虽然这里提到的工具会对单细胞中的每个基因集评分,但它们无法在所有被评分的基因集中,挑选出最具生物学相关性的那些。scDECAF(DavisLaboratory/scDECAF)是一个基因集活性推断工具,它允许以数据驱动的方式选出信息量最大的基因集,从而有助于解析有意义的细胞异质性。

20.5. 技术考虑因素#

20.5.1. 过滤掉基因数较少的基因集#

一个常见的做法是:在预处理步骤中,排除任何只有少数基因与数据(或高变基因 HVG)重叠的基因集。Zhang 等人 [Zhang et al., 2020] 发现,随着基因覆盖率(即通路/基因集中基因的数量)下降,基于单细胞和基于批量的方法性能都会下降。Holland 等人 [Holland et al., 2020] 也发现,规模较小的基因集会对 Bulk-seq 的性能产生不利影响 DoRothEAPROGENy (应用于单细胞数据)。这些报告共同支持:在通路分析中,过滤掉基因数较少的基因集(比如集合中少于 10 或 15 个基因)是有益的。Damian 与 Gorfine(2004) [Damian and Gorfine, 2004] 把这一点归因于:基因数较少的基因集中,基因方差更可能偏大,而较大的基因集中基因方差往往较小。这会影响为检验富集而计算的检验统计量的准确性。Zhang 等人还发现,通路分析对应用于基因表达测量的归一化方法很敏感。

20.5.2. 数据归一化#

单细胞实验中的读数计数,通常在预处理流程的早期就被归一化,以确保不同文库大小的细胞之间测量具有可比性。Zhang 等人 [Zhang et al., 2020] 发现,使用 SCTransform [Hafemeister and Satija, 2019]scran [Lun et al., 2016] 通常能改善基于单细胞和基于批量的通路评分工具的性能。他们发现 AUCell (一种基于排名的方法)和 z-score (变换为零均值、单位标准差)尤其会受到不同归一化方法的影响。

20.6. 案例研究:人类 PBMC 单细胞中的通路富集分析与活性水平评分#

20.6.1. 准备并探索数据#

我们首先下载了 25K PBMC 数据并遵循了标准 scanpy 工作流程,对读数计数做归一化,并在高变基因上取子集。该数据集包含未处理的和 IFN-\(\beta\) 刺激的人类 PBMC 细胞 [Kang et al., 2018]。我们用 4000 个高变基因的 UMAP 表示来探索数据中的变异模式。

from __future__ import annotations

import anndata as ad
import decoupler
import numpy as np
import pandas as pd
import scanpy as sc
import seaborn.objects as so
import session_info
sc.settings.set_figure_params(dpi=200, frameon=False)
sc.set_figure_params(dpi=200)
sc.set_figure_params(figsize=(4, 4))
# Filtering warnings from current version of matplotlib
import warnings

warnings.filterwarnings(
    "ignore", message=".*Parameters 'cmap' will be ignored.*", category=UserWarning
)
warnings.filterwarnings(
    "ignore", message="Tight layout not applied.*", category=UserWarning
)
# Setting up R dependencies
import anndata2ri

%load_ext rpy2.ipython

anndata2ri.activate()
%%R
suppressPackageStartupMessages({
    library(SingleCellExperiment)
})
adata = sc.read(
    "kang_counts_25k.h5ad", backup_url="https://figshare.com/ndownloader/files/34464122"
)
adata
AnnData object with n_obs × n_vars = 24673 × 15706
    obs: 'nCount_RNA', 'nFeature_RNA', 'tsne1', 'tsne2', 'label', 'cluster', 'cell_type', 'replicate', 'nCount_SCT', 'nFeature_SCT', 'integrated_snn_res.0.4', 'seurat_clusters'
    var: 'name'
    obsm: 'X_pca', 'X_umap'
# Storing the counts for later use
adata.layers["counts"] = adata.X.copy()
# Renaming label to condition
adata.obs = adata.obs.rename({"label": "condition"}, axis=1)

# Normalizing
sc.pp.normalize_total(adata)
sc.pp.log1p(adata)
# Finding highly variable genes using count data
sc.pp.highly_variable_genes(
    adata, n_top_genes=4000, flavor="seurat_v3", subset=False, layer="counts"
)
adata
AnnData object with n_obs × n_vars = 24673 × 15706
    obs: 'nCount_RNA', 'nFeature_RNA', 'tsne1', 'tsne2', 'condition', 'cluster', 'cell_type', 'replicate', 'nCount_SCT', 'nFeature_SCT', 'integrated_snn_res.0.4', 'seurat_clusters'
    var: 'name', 'highly_variable', 'highly_variable_rank', 'means', 'variances', 'variances_norm'
    uns: 'log1p', 'hvg'
    obsm: 'X_pca', 'X_umap'
    layers: 'counts'

虽然当前对象自带 UMAP 和 PCA 嵌入,但它们已经针对刺激条件做过校正,而本次分析并不希望如此。因此,我们将重新计算这些嵌入。

sc.pp.pca(adata)
sc.pp.neighbors(adata)
sc.tl.umap(adata)
/Users/isaac/miniconda3/envs/pathway/lib/python3.9/site-packages/tqdm/auto.py:22: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
sc.pl.umap(
    adata,
    color=["condition", "cell_type"],
    frameon=False,
    ncols=2,
)

我们通常建议按 Differential gene expression 一章所述来确定差异表达基因。为简单起见,这里我们运行一次 t 检验,使用 scanpy 中的 rank_genes_groups,以根据基因的差异表达检验统计量对基因排序:

adata.obs["group"] = adata.obs.condition.astype("string") + "_" + adata.obs.cell_type
# find DE genes by t-test
sc.tl.rank_genes_groups(adata, "group", method="t-test", key_added="t-test")

我们来提取 CD16 单核细胞(FCGR3A+ 单核细胞)聚类中、针对 IFN 刺激而差异表达的基因的排名。我们用这些排名和来自 REACTOME 的基因集,借助 GSEA,找出与所有其他群体相比、在这个细胞群体中富集的基因集,正如 decoupler 中所实现的那样。

celltype_condition = "stim_FCGR3A+ Monocytes"  # 'stimulated_B',  'stimulated_CD8 T', 'stimulated_CD14 Mono'
# extract scores
t_stats = (
    # Get dataframe of DE results for condition vs. rest
    sc.get.rank_genes_groups_df(adata, celltype_condition, key="t-test")
    # Subset to highly variable genes
    .set_index("names")
    .loc[adata.var["highly_variable"]]
    # Sort by absolute score
    .sort_values("scores", key=np.abs, ascending=False)[
        # Format for decoupler
        ["scores"]
    ]
    .rename_axis(["stim_FCGR3A+ Monocytes"], axis=1)
)
t_stats
stim_FCGR3A+ Monocytes scores
names
IFITM3 123.019180
ISG15 119.732079
TYROBP 91.894241
TNFSF10 87.408890
S100A11 85.721817
... ...
NR1D1 -0.005578
PIK3R5 0.004145
FHL2 0.002915
CLECL1 -0.000262
ADCK4 0.000002

4000 rows × 1 columns

20.6.2. decoupler 进行聚类级基因集富集分析#

现在我们用 Python 包 decoupler [Badia-i-Mompel et al., 2022] 对我们的数据进行 GSEA 富集检验。

20.6.2.1. 检索基因集#

下载并读取 gmt 文件,该文件对应 MSigDB 的 C2 集合中注释的 REACTOME 通路。

# Downloading reactome pathways
from pathlib import Path

if not Path("c2.cp.reactome.v7.5.1.symbols.gmt").is_file():
    !wget -O 'c2.cp.reactome.v7.5.1.symbols.gmt' https://figshare.com/ndownloader/files/35233771
def gmt_to_decoupler(pth: Path) -> pd.DataFrame:
    """Parse a gmt file to a decoupler pathway dataframe."""
    from itertools import chain, repeat

    pathways = {}

    with Path(pth).open("r") as f:
        for line in f:
            name, _, *genes = line.strip().split("\t")
            pathways[name] = genes

    return pd.DataFrame.from_records(
        chain.from_iterable(zip(repeat(k), v) for k, v in pathways.items()),
        columns=["geneset", "genesymbol"],
    )
reactome = gmt_to_decoupler("c2.cp.reactome.v7.5.1.symbols.gmt")

或者,我们也可以直接从 omnipath 查询这些资源。

不过,为了让本教程保持稳定,这里我们使用了基因集集合的一个固定版本。

# Retrieving via python
msigdb = decoupler.get_resource("MSigDB")

# Get reactome pathways
reactome = msigdb.query("collection == 'reactome_pathways'")
# Filter duplicates
reactome = reactome[~reactome.duplicated(("geneset", "genesymbol"))]
reactome
geneset genesymbol
0 REACTOME_INTERLEUKIN_6_SIGNALING JAK2
1 REACTOME_INTERLEUKIN_6_SIGNALING TYK2
2 REACTOME_INTERLEUKIN_6_SIGNALING CBL
3 REACTOME_INTERLEUKIN_6_SIGNALING STAT1
4 REACTOME_INTERLEUKIN_6_SIGNALING IL6ST
... ... ...
89471 REACTOME_ION_CHANNEL_TRANSPORT FXYD7
89472 REACTOME_ION_CHANNEL_TRANSPORT UBA52
89473 REACTOME_ION_CHANNEL_TRANSPORT ATP6V1E2
89474 REACTOME_ION_CHANNEL_TRANSPORT ASIC5
89475 REACTOME_ION_CHANNEL_TRANSPORT FXYD1

89476 rows × 2 columns

20.6.2.2. 运行 GSEA#

我们首先准备基因集。默认情况下, decoupler 不会按最大规模过滤基因集,而像 fgsea 这样的软件包则会这么做。相反,我们只是手动过滤基因集,使其至少包含 15 个基因、最多 500 个基因。

# Filtering genesets to match behaviour of fgsea
geneset_size = reactome.groupby("geneset").size()
gsea_genesets = geneset_size.index[(geneset_size > 15) & (geneset_size < 500)]

我们将使用 t 检验得到的 t 统计量,对 CD16 单核细胞在 IFN 刺激后的表型相关基因进行排序,并为每条通路计算 p 值。

scores, norm, pvals = decoupler.run_gsea(
    t_stats.T,
    reactome[reactome["geneset"].isin(gsea_genesets)],
    source="geneset",
    target="genesymbol",
)

gsea_results = (
    pd.concat({"score": scores.T, "norm": norm.T, "pval": pvals.T}, axis=1)
    .droplevel(level=1, axis=1)
    .sort_values("pval")
)

我们画一张条形图,展示在受刺激的 CD16 单核细胞中、相比所有其他细胞类型显著富集的前 20 条通路。

(
    so.Plot(
        data=(
            gsea_results.head(20).assign(
                **{"-log10(pval)": lambda x: -np.log10(x["pval"])}
            )
        ),
        x="-log10(pval)",
        y="source",
    ).add(so.Bar())
)

在上图中,通路名称标在 y 轴上。x 轴表示 \(-\log_{10}\)校正后的 p 值。因此,条形越长,该通路就越显著。通路按显著性排序。大多数与干扰素相关的通路确实排在富集程度最高的前 20 条通路之中。一些与 IFN 相关的通路包括:REACTOME_INTERFERON_SIGNALING(排名第 2)、REACTOME_INTERFERON_GAMMA_SIGNALING(排名第 3)和 REACTOME_INTERFERON_ALPHA_BETA_SIGNALING(排名第 4)。总体而言, GSEA 在识别已知与干扰素信号相关的通路方面做得相当不错,尤其考虑到我们事先就知道与 IFN 相关的通路应当是排名最靠前的条目。

我们来看看 decoupler.run_gsea 的原始输出:

gsea_results.head(10)
score norm pval
source
REACTOME_NEUTROPHIL_DEGRANULATION 0.624770 5.587953 2.297617e-08
REACTOME_INTERFERON_SIGNALING 0.844158 5.155074 2.535313e-07
REACTOME_INTERFERON_GAMMA_SIGNALING 0.831962 4.137064 3.517788e-05
REACTOME_INTERFERON_ALPHA_BETA_SIGNALING 0.893431 4.107962 3.991655e-05
REACTOME_SIGNALING_BY_INTERLEUKINS 0.376129 3.535838 4.064833e-04
REACTOME_MHC_CLASS_II_ANTIGEN_PRESENTATION 0.701555 3.378736 7.282002e-04
REACTOME_TRANSLATION -0.628266 -3.277846 1.046026e-03
REACTOME_RRNA_PROCESSING -0.703607 -3.205217 1.349605e-03
REACTOME_PLATELET_ACTIVATION_SIGNALING_AND_AGGREGATION 0.475259 3.162945 1.561817e-03
REACTOME_LEISHMANIA_INFECTION 0.531540 2.964611 3.030663e-03

在上文, pval 是富集检验的 p 值,而 scorenorm 分别是富集分数(enrichment score)和归一化富集分数。注意,富集分数是带符号的。因此,负分表明该通路被下调,正分则表明该通路或基因集中的基因被上调。

20.6.3. 使用 AUCell 进行细胞级通路活性评分#

与前面那种逐聚类(或者说逐细胞类型)评估基因集富集的方法不同,我们可以对每个单独细胞中通路和基因集的活性水平进行评分,它基于该细胞中基因的绝对表达,而与其他细胞中的基因表达无关。我们可以借助活性评分工具来实现这一点,例如 AUCell.

GSEA类似,我们将使用 decoupler 实现的 AUCell.

%%time
decoupler.run_aucell(
    adata,
    reactome,
    source="geneset",
    target="genesymbol",
    use_raw=False,
)
CPU times: user 16min 42s, sys: 5.09 s, total: 16min 47s
Wall time: 1min 9s
adata
AnnData object with n_obs × n_vars = 24673 × 15706
    obs: 'nCount_RNA', 'nFeature_RNA', 'tsne1', 'tsne2', 'condition', 'cluster', 'cell_type', 'replicate', 'nCount_SCT', 'nFeature_SCT', 'integrated_snn_res.0.4', 'seurat_clusters', 'group'
    var: 'name', 'highly_variable', 'highly_variable_rank', 'means', 'variances', 'variances_norm'
    uns: 'log1p', 'hvg', 'pca', 'neighbors', 'umap', 'condition_colors', 'cell_type_colors', 't-test'
    obsm: 'X_pca', 'X_umap', 'aucell_estimate'
    varm: 'PCs'
    layers: 'counts'
    obsp: 'distances', 'connectivities'

现在,我们把与干扰素相关的 REACTOME 通路的分数加到 obs 字段(位于 AnnData 对象中),并在 UMAP 上注释这些通路在每个细胞中的活性水平:

ifn_pathways = [
    "REACTOME_INTERFERON_SIGNALING",
    "REACTOME_INTERFERON_ALPHA_BETA_SIGNALING",
    "REACTOME_INTERFERON_GAMMA_SIGNALING",
]

adata.obs[ifn_pathways] = adata.obsm["aucell_estimate"][ifn_pathways]

在 UMAP 上绘制这些分数

sc.pl.umap(
    adata,
    color=["condition", "cell_type"] + ifn_pathways,
    frameon=False,
    ncols=2,
    wspace=0.3,
)

AUCell 在 IFN 刺激的细胞中,对那些已知与干扰素信号相关的通路给出了较高的分数,而对照条件下的细胞对这些通路的分数通常较低,这表明用 AUCell 进行基因集评分是成功的。还要注意,对于在 GSEA 的基因集富集检验结果中排名较高的条目,其分数通常也更大。由 AUCell得到的通路活性分数,与由 GSEA 得到的基因集富集检验结果之间的一致性令人鼓舞,尤其考虑到我们事先就知道与 IFN 相关的通路应当是排名最靠前的条目。此外,在这个数据集中 IFN 刺激的效应非常大,这也提升了这里这些方法的表现。

20.6.4. 使用 limma-fry 和 pseudo-bulk 对复杂实验设计做基因集富集#

在聚类级 t 检验方法中,差异表达基因是通过把一个聚类与所有其他聚类比较来发现的——在本例中,这既包括对照细胞也包括受刺激细胞。线性模型让我们能够只把受刺激条件下的细胞与对照组细胞比较,从而更准确地识别出对刺激作出响应的基因。事实上,线性模型可以容纳复杂的实验设计,例如,找出在 Cell type A in treatment 1 中相比 Cell type A in treatment 2中更为富集的基因集;也就是说,跨扰动、跨细胞类型的效应,同时校正批次效应、个体间差异、小鼠模型中的性别和品系差异等。

在下一节中,我们演示一个可推广到现实数据分析流程(例如单细胞病例-对照研究)的 limma-fry 工作流程。我们首先为每种细胞类型和条件创建 pseudo-bulk 重复(每个“条件-细胞类型”组合 3 个重复)。然后,我们找出在某种细胞类型中、受刺激相比对照富集的基因集。我们还会评估两个受刺激的细胞类型群体之间的基因集富集,以发现信号通路上的差异。

20.6.4.1. 创建伪块样本并探索数据#

def subsampled_summation(
    adata: ad.AnnData,
    groupby: str | list[str],
    *,
    n_samples_per_group: int,
    n_cells: int,
    random_state: None | int | np.random.RandomState = None,
    layer: str = None,
) -> ad.AnnData:
    """Sum sample of X per condition.

    Drops conditions which don't have enough samples.

    Parameters
    ----------
    adata
        AnnData to sum expression of
    groupby
        Keys in obs to groupby
    n_samples_per_group
        Number of samples to take per group
    n_cells
        Number of cells to take per sample
    random_state
        Random state to use when sampling cells
    layer
        Which layer of adata to use

    Returns:
    -------
    AnnData with same var as original, obs with columns from groupby, and X.
    """
    from scipy import sparse
    from sklearn.utils import check_random_state

    # Checks
    if isinstance(groupby, str):
        groupby = [groupby]
    random_state = check_random_state(random_state)

    indices = []
    labels = []

    grouped = adata.obs.groupby(groupby)
    for k, inds in grouped.indices.items():
        # Check size of group
        if len(inds) < (n_cells * n_samples_per_group):
            continue

        # Sample from group
        condition_inds = random_state.choice(
            inds, n_cells * n_samples_per_group, replace=False
        )
        for i, sample_condition_inds in enumerate(np.split(condition_inds, 3)):
            if isinstance(k, tuple):
                labels.append((*k, i))
            else:  # only grouping by one variable
                labels.append((k, i))
            indices.append(sample_condition_inds)

    # obs of output AnnData
    new_obs = pd.DataFrame.from_records(
        labels,
        columns=[*groupby, "sample"],
        index=["-".join(map(str, l)) for l in labels],
    )
    n_out = len(labels)

    # Make indicator matrix
    indptr = np.arange(0, (n_out + 1) * n_cells, n_cells)
    indicator = sparse.csr_matrix(
        (
            np.ones(n_out * n_cells, dtype=bool),
            np.concatenate(indices),
            indptr,
        ),
        shape=(len(labels), adata.n_obs),
    )

    return ad.AnnData(
        X=indicator @ sc.get._get_obs_rep(adata, layer=layer),
        obs=new_obs,
        var=adata.var.copy(),
    )
pb_data = subsampled_summation(
    adata, ["cell_type", "condition"], n_cells=75, n_samples_per_group=3, layer="counts"
)
pb_data
AnnData object with n_obs × n_vars = 42 × 15706
    obs: 'cell_type', 'condition', 'sample'
    var: 'name', 'highly_variable', 'highly_variable_rank', 'means', 'variances', 'variances_norm'
# Does PC1 captures a meaningful biological or technical fact?
pb_data.obs["lib_size"] = pb_data.X.sum(1)

我们来把这份数据归一化,并快速看一下。由于样本量大幅减少,这里我们不会使用近邻嵌入。

pb_data.layers["counts"] = pb_data.X.copy()
sc.pp.normalize_total(pb_data)
sc.pp.log1p(pb_data)
sc.pp.pca(pb_data)
sc.pl.pca(pb_data, color=["cell_type", "condition", "lib_size"], ncols=1, size=250)

现在 PC1 捕捉的是淋巴系(T、NK、B)与髓系(Mono、DC)群体之间的差异,而第二个 PC 捕捉的是因施加刺激而产生的变异(即对照与受刺激伪重复之间的差异)。理想情况下,所关注的变异应当能在 pseudo-bulk 数据的前几个 PC 中被检测到。

在这种情况下,由于我们确实关心每种细胞类型的刺激效应,我们就接着做基因集检验。我们再次强调,绘制 PC 的目的是探索数据中的各个变异轴,并发现可能严重影响检验结果的、不需要的变异。如果用户对自己数据中的变异情况满意,就可以继续进行后续分析。

20.6.4.2. 设置 limmafry#

在接下来这部分分析中,我们将使用 Bioconductor 包 limma 和它的方法 fry.

我们首先建立设计矩阵和对比矩阵。提醒一下:设计矩阵是分组归属(即某个样本所属的分组或条件)的数学表示,而对比矩阵是对差异检验中所关注比较的数学表示。

groups = pb_data.obs.condition.astype("string") + "_" + pb_data.obs.cell_type
%%R -i groups
group <-  as.factor(gsub(" |\\+","_", groups))
design <- model.matrix(~ 0 + group)
head(design)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,]    0    0    1    0    0    0    0    0    0     0     0     0     0     0
[2,]    0    0    1    0    0    0    0    0    0     0     0     0     0     0
[3,]    0    0    1    0    0    0    0    0    0     0     0     0     0     0
[4,]    0    0    0    0    0    0    0    0    0     1     0     0     0     0
[5,]    0    0    0    0    0    0    0    0    0     1     0     0     0     0
[6,]    0    0    0    0    0    0    0    0    0     1     0     0     0     0
%%R
colnames(design)
 [1] "groupctrl_B_cells"           "groupctrl_CD14__Monocytes"  
 [3] "groupctrl_CD4_T_cells"       "groupctrl_CD8_T_cells"      
 [5] "groupctrl_Dendritic_cells"   "groupctrl_FCGR3A__Monocytes"
 [7] "groupctrl_NK_cells"          "groupstim_B_cells"          
 [9] "groupstim_CD14__Monocytes"   "groupstim_CD4_T_cells"      
[11] "groupstim_CD8_T_cells"       "groupstim_Dendritic_cells"  
[13] "groupstim_FCGR3A__Monocytes" "groupstim_NK_cells"         
%%R 
kang_pbmc_con <- limma::makeContrasts(
    
    # the effect if stimulus in CD16 Monocyte cells
    groupstim_FCGR3A__Monocytes - groupctrl_FCGR3A__Monocytes,
    
    # the effect of stimulus in CD16 Monocytes compared to CD8 T Cells
    (groupstim_FCGR3A__Monocytes - groupctrl_FCGR3A__Monocytes) - (groupstim_CD8_T_cells - groupctrl_CD8_T_cells), 
    levels = design
)

按如下方式,为数据中每条通路所注释的基因建立索引:

log_norm_X = pb_data.to_df().T
%%R -i log_norm_X -i reactome
# Move pathway info from python to R
pathways = split(reactome$genesymbol, reactome$geneset)
# Map gene names to indices
idx = limma::ids2indices(pathways, rownames(log_norm_X))
/Users/isaac/miniconda3/envs/pathway/lib/python3.9/site-packages/rpy2/robjects/pandas2ri.py:54: FutureWarning: iteritems is deprecated and will be removed in a future version. Use .items instead.
  for name, values in obj.iteritems():
/Users/isaac/miniconda3/envs/pathway/lib/python3.9/site-packages/rpy2/robjects/pandas2ri.py:54: FutureWarning: iteritems is deprecated and will be removed in a future version. Use .items instead.
  for name, values in obj.iteritems():

正如在 gsea 方法中那样,我们去除基因少于 15 个的基因集

%%R
keep_gs <- lapply(idx, FUN=function(x) length(x) >= 15)
idx <- idx[unlist(keep_gs)]

现在我们已经建立了设计矩阵和对比矩阵,并为数据中每条通路的基因建立了索引,就可以调用 fry() 来检验我们上面设定的每个对比中富集的通路:

20.6.4.3. 用 fry 检验比较受刺激 vs 对照#

%%R -o fry_results
fry_results <- limma::fry(log_norm_X, index = idx, design = design, contrast = kang_pbmc_con[,1])

看一看排名最靠前的通路,我们会看到一些熟悉的名字:

fry_results.head()
NGenes Direction PValue FDR PValue.Mixed FDR.Mixed
REACTOME_INTERFERON_ALPHA_BETA_SIGNALING 57 Up 3.836198e-24 3.410380e-21 8.018820e-39 9.504975e-38
REACTOME_INTERFERON_SIGNALING 177 Up 5.651011e-18 2.511875e-15 3.888212e-51 1.047461e-49
REACTOME_INTERFERON_GAMMA_SIGNALING 84 Up 6.080234e-13 1.801776e-10 4.268886e-61 2.710743e-59
REACTOME_MRNA_SPLICING_MINOR_PATHWAY 50 Down 8.311795e-11 1.847296e-08 5.137952e-20 2.003351e-19
REACTOME_DDX58_IFIH1_MEDIATED_INDUCTION_OF_INTERFERON_ALPHA_BETA 67 Up 1.555236e-09 2.765210e-07 9.966640e-53 3.055291e-51
(
    so.Plot(
        data=(
            fry_results.head(20)
            .assign(**{"-log10(FDR)": lambda x: -np.log10(x["FDR"])})
            .rename_axis(index="Pathway")
        ),
        x="-log10(FDR)",
        y="Pathway",
    ).add(so.Bar())
)

20.6.4.4. 用 fry 检验比较两种受刺激的细胞类型#

%%R -o fry_results_negative_ctrl
fry_results_negative_ctrl <- limma::fry(log_norm_X, index = idx, design = design, contrast = kang_pbmc_con[,2])
(
    so.Plot(
        data=(
            fry_results_negative_ctrl.head(20)
            .assign(**{"-log10(FDR)": lambda x: -np.log10(x["FDR"])})
            .rename_axis(index="Pathway")
        ),
        x="-log10(FDR)",
        y="Pathway",
    ).add(so.Bar())
)

如上所述,limma-fry 可以为具有复杂实验设计的数据集和研究问题提供基因集富集检验。两者都 gseafry 都能提供关于富集方向的信息(正分或负分见于 gsea ,而 Direction 字段见于 fry)。它们都可以应用于细胞聚类或 pseudo-bulk 样本。然而,与 gsea不同,可以用 fry进行更灵活的检验。此外, fry 能揭示某条通路中的基因是否在实验条件之间发生变化、且变化方向是否一致。基因朝一致方向变化的通路,可以通过 FDR < 0.05 来识别;而基因在条件之间差异表达、但朝不同的、不一致方向变化的通路,则可以在 FDR > 0.05、但 FDR.Mixed < 0.05 处识别(假设 0.05 为期望的显著性水平)。fry 是双向的,适用于任意设计,并且在样本数较少时也表现良好(尽管这在单细胞中可能不是问题)。因此,由以下方法得到的结果 fry 也许在生物学上更有意义。

20.6.4.4.1. 关于过滤低表达基因的效果#

如前所述,理想情况下,所关注的变异应当能在 pseudo-bulk 数据的前几个 PC 中被检测到。我们来去掉数据中表达量低的基因,应用 \(\log_2\)CPM 变换,然后重复绘制 PCA 图:

counts_df = pb_data.to_df(layer="counts").T
%%R -i counts_df
keep <- edgeR::filterByExpr(counts_df) # in real analysis, supply the desig matrix to the function to retain as more genes as possible
counts_df <- counts_df[keep,]
logCPM <- edgeR::cpm(counts_df, log=TRUE, prior.count = 2)
/Users/isaac/miniconda3/envs/pathway/lib/python3.9/site-packages/rpy2/robjects/pandas2ri.py:54: FutureWarning: iteritems is deprecated and will be removed in a future version. Use .items instead.
  for name, values in obj.iteritems():
R[write to console]: No group or design set. Assuming all samples belong to one group.
%%R -o logCPM
logCPM = data.frame(logCPM)
pb_data.uns["logCPM_FLE"] = logCPM.T  # FLE for filter low exprs
pb_data.obsm["logCPM_FLE_pca"] = sc.pp.pca(logCPM.T.to_numpy(), return_info=False)
sc.pl.embedding(pb_data, "logCPM_FLE_pca", color=pb_data.obs, ncols=1, size=250)

这里,“logCPM_FLE”表示先对低表达基因进行过滤,再做 \(\log_2\)CPM 变换。现在我们可以清楚地看到:当去掉低表达基因、并对文库大小差异加以校正后,PC1 捕捉的是细胞类型效应,PC2 捕捉的是处理效应 \(\log_2\)CPM 变换。

由于在本案例研究中我们确实关心每种细胞类型的刺激效应,而这种变异在基因过滤之前保留得更好,因此我们展示的是未过滤数据上的富集检验结果。在实践中,过滤低丰度基因、并通过以下方法计算归一化因子 edgeR::calcNormFactors 是批量 RNA-seq 分析流程的标准环节。如果我们关心的是 IFN 刺激的全局效应,那就应该使用过滤后的数据。此外,可以注意到 design <- model.matrix(~ 0 + lineage + group) 会考虑髓系(myeloid)与淋巴系(lymphoid)谱系之间的差异(即基线表达差异),从而改善 pseudo-bulk 样本按 IFN 刺激的分离,这可能体现在 PC1 上。在本案例研究中,我们关心的是细胞类型特异的效应,因此我们坚持采用这样一个数据模型:PC1 方向上的变异是按细胞类型区分的。设计矩阵的选择必须仔细斟酌,以便与所关注的生物学问题保持一致。

20.6.4.4.2. 关于基因集之间的冗余、以及 preranked 与 fry 基因集检验性能的说明#

一般来说,关系密切的基因集之间可能有很大的重叠。这种重叠会影响基因集在富集结果中的排名,并可能损害最终的解读。例如,Kang 等人研究中的细胞用 IFN-\(\beta\)处理。因此,人们会预期看到 REACTOME_INTERFERON_ALPHA_BETA_SIGNALING 这个条目排名最高。虽然在 fry的输出中这个条目确实排名第一,但在 GSEA 的输出中,REACTOME_INTERFERON_SIGNALING 才是排名第一的条目。这个条目包含的基因数(52)比 REACTOME_INTERFERON_ALPHA_BETA_SIGNALING(24 个基因)更多,而且这些基因大多在两个条目之间共享。这说明了 preranked 基因集检验(例如 GSEAfry)的另一个差异:在防止较大的基因集主导富集结果方面。以下方法之所以表现更好 fry,是因为它对基因表达方差的估计更准确,因而 DE 基因结果更灵敏。

20.7. Quiz#

基因集富集检验与活性评分有什么区别?
基因集富集检验侧重于识别在差异表达基因中过度代表的基因集。活性评分则通过汇总某个集合中基因的表达,评估单个样本内某条通路的活性水平,给出一个反映通路活性的连续分数。
请举例说明应当使用基因集检验的场景。你能否概述通路活性评分方法适用的场景?
当需要比较多组样本、以识别在不同条件之间差异表达的通路时(例如处理组与未处理组),适合使用基因集检验。而通路活性评分方法适合单样本分析,用于确定单个样本内的通路活性水平,在个体化医疗或样本量有限时尤为有用。
基因集富集检验中有哪两类零假设?请解释这两类之间的区别。
竞争性(competitive)零假设:认为集合内的基因与表型的关联并不强于集合外的基因;该检验比较集合内基因与集合外基因的关联程度。自包含(self-contained)零假设:认为集合内没有任何基因与表型相关;该检验独立地评估这个基因集,而不考虑集合外的基因。
通路分析中最重要的预处理步骤是什么?如果这一步做得不当,会有什么后果?
对基因表达数据进行适当的归一化至关重要。归一化不充分可能导致误导性的结果,因为技术性变异可能被误认为生物学差异,从而影响通路分析的准确性。
请各举出一种基因集检验算法和一种基因集活性评分算法,并简要解释。
基因集富集分析(GSEA)评估预先定义的基因集在两种生物学状态之间是否表现出统计上显著且方向一致的差异。单样本 GSEA(ssGSEA)为每一对(样本,基因集)分别计算富集分数,从而把基因表达数据转换成单个样本的通路活性谱。

20.8. 会话信息#

%%R
sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-apple-darwin13.4.0 (64-bit)
Running under: macOS Big Sur 11.6.8

Matrix products: default
LAPACK: /Users/isaac/miniconda3/envs/pathway/lib/libopenblasp-r0.3.21.dylib

locale:
[1] C/UTF-8/C/C/C/C

attached base packages:
[1] stats4    tools     stats     graphics  grDevices utils     datasets 
[8] methods   base     

other attached packages:
 [1] SingleCellExperiment_1.16.0 SummarizedExperiment_1.24.0
 [3] Biobase_2.54.0              GenomicRanges_1.46.1       
 [5] GenomeInfoDb_1.30.1         IRanges_2.28.0             
 [7] S4Vectors_0.32.4            BiocGenerics_0.40.0        
 [9] MatrixGenerics_1.6.0        matrixStats_0.63.0         

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.9             locfit_1.5-9.6         edgeR_3.36.0          
 [4] lattice_0.20-45        bitops_1.0-7           grid_4.1.2            
 [7] zlibbioc_1.40.0        XVector_0.34.0         limma_3.50.1          
[10] Matrix_1.5-3           statmod_1.4.37         RCurl_1.98-1.9        
[13] DelayedArray_0.20.0    compiler_4.1.2         GenomeInfoDbData_1.2.7
session_info.show()
Click to view session information
-----
anndata             0.8.0
anndata2ri          0.0.0
decoupler           1.3.1
numpy               1.23.5
pandas              1.5.2
rpy2                3.5.1
scanpy              1.9.1
seaborn             0.12.1
session_info        1.0.0
-----
Click to view modules imported as dependencies
PIL                         9.2.0
appnope                     0.1.3
asttokens                   NA
backcall                    0.2.0
beta_ufunc                  NA
binom_ufunc                 NA
cffi                        1.15.1
colorama                    0.4.6
cycler                      0.10.0
cython_runtime              NA
dateutil                    2.8.2
debugpy                     1.6.4
decorator                   5.1.1
dunamai                     1.15.0
entrypoints                 0.4
executing                   1.2.0
get_version                 3.5.4
h5py                        3.7.0
hypergeom_ufunc             NA
importlib_metadata          NA
ipykernel                   6.17.1
jedi                        0.18.2
jinja2                      3.1.2
joblib                      1.2.0
kiwisolver                  1.4.4
llvmlite                    0.39.1
markupsafe                  2.1.1
matplotlib                  3.6.2
matplotlib_inline           0.1.6
mpl_toolkits                NA
natsort                     8.2.0
nbinom_ufunc                NA
ncf_ufunc                   NA
numba                       0.56.4
packaging                   21.3
parso                       0.8.3
pexpect                     4.8.0
pickleshare                 0.7.5
pkg_resources               NA
platformdirs                2.5.2
prompt_toolkit              3.0.33
psutil                      5.9.4
ptyprocess                  0.7.0
pure_eval                   0.2.2
pycparser                   2.21
pydev_ipython               NA
pydevconsole                NA
pydevd                      2.9.1
pydevd_file_utils           NA
pydevd_plugins              NA
pydevd_tracing              NA
pygments                    2.13.0
pynndescent                 0.5.8
pyparsing                   3.0.9
pytz                        2022.6
pytz_deprecation_shim       NA
scipy                       1.9.3
setuptools                  65.5.1
six                         1.16.0
sklearn                     1.1.3
skmisc                      0.1.4
stack_data                  0.6.2
statsmodels                 0.13.5
threadpoolctl               3.1.0
tornado                     6.2
tqdm                        4.64.1
traitlets                   5.6.0
typing_extensions           NA
tzlocal                     NA
umap                        0.5.3
wcwidth                     0.2.5
zipp                        NA
zmq                         24.0.1
zoneinfo                    NA
-----
IPython             8.7.0
jupyter_client      7.4.8
jupyter_core        5.1.0
-----
Python 3.9.15 | packaged by conda-forge | (main, Nov 22 2022, 08:55:37) [Clang 14.0.6 ]
macOS-11.6.8-x86_64-i386-64bit
-----
Session information updated at 2022-12-11 20:31

20.9. 参考文献#

[gspaAGonzalezBM+17]

Sara Aibar, Carmen Bravo González-Blas, Thomas Moerman, Vân Anh Huynh-Thu, Hana Imrichova, Gert Hulselmans, Florian Rambow, Jean-Christophe Marine, Pierre Geurts, Jan Aerts, and others. Scenic: single-cell regulatory network inference and clustering. Nature methods, 14(11):1083–1086, 2017.

[gspaBiMVelezSB+22]

Pau Badia-i-Mompel, Jesús Vélez Santiago, Jana Braunger, Celina Geiss, Daniel Dimitrov, Sophia Müller-Dott, Petr Taus, Aurelien Dugourd, Christian H Holland, Ricardo O Ramirez Flores, and others. Decoupler: ensemble of computational methods to infer biological activities from omics data. Bioinformatics Advances, 2(1):vbac016, 2022.

[gspaCTK+13]

Edward Y Chen, Christopher M Tan, Yan Kou, Qiaonan Duan, Zichen Wang, Gabriela Vaz Meirelles, Neil R Clark, and Avi Ma’ayan. Enrichr: interactive and collaborative html5 gene list enrichment analysis tool. BMC bioinformatics, 14(1):1–14, 2013.

[gspaDG04]

Doris Damian and Malka Gorfine. Statistical concerns about the gsea procedure. Nature genetics, 36(7):663–663, 2004.

[gspaDJS+19]

David DeTomaso, Matthew G Jones, Meena Subramaniam, Tal Ashuach, Chun J Ye, and Nir Yosef. Functional interpretation of single cell similarity maps. Nature communications, 10(1):1–11, 2019.

[gspaFSL+16]

Jean Fan, Neeraj Salathia, Rui Liu, Gwendolyn E Kaeser, Yun C Yung, Joseph L Herman, Fiona Kaper, Jian-Bing Fan, Kun Zhang, Jerold Chun, and others. Characterizing transcriptional heterogeneity through pathway and gene set overdispersion analysis. Nature methods, 13(3):241–244, 2016.

[gspaFranzenGBjorkegren19]

Oscar Franzén, Li-Ming Gan, and Johan LM Björkegren. Panglaodb: a web server for exploration of mouse and human single-cell rna sequencing data. Database, 2019.

[gspaGAHI+19]

Luz Garcia-Alonso, Christian H Holland, Mahmoud M Ibrahim, Denes Turei, and Julio Saez-Rodriguez. Benchmark and integration of resources for the estimation of human transcription factor activities. Genome research, 29(8):1363–1375, 2019.

[gspaGBuhlmann07]

Jelle J Goeman and Peter Bühlmann. Analyzing gene expression data in terms of gene sets: methodological issues. Bioinformatics, 23(8):980–987, 2007.

[gspaHS19]

Christoph Hafemeister and Rahul Satija. Normalization and variance stabilization of single-cell rna-seq data using regularized negative binomial regression. Genome biology, 20(1):1–15, 2019.

[gspaHTPPaton+20] (1,2)

Christian H Holland, Jovan Tanevski, Javier Perales-Patón, Jan Gleixner, Manu P Kumar, Elisabetta Mereu, Brian A Joughin, Oliver Stegle, Douglas A Lauffenburger, Holger Heyn, and others. Robustness and applicability of transcription factor and pathway analysis tools on single-cell rna-seq data. Genome biology, 21(1):1–19, 2020.

[gspaHanzelmannCG13]

Sonja Hänzelmann, Robert Castelo, and Justin Guinney. Gsva: gene set variation analysis for microarray and rna-seq data. BMC bioinformatics, 14(1):1–15, 2013.

[gspaKST+18]

Hyun Min Kang, Meena Subramaniam, Sasha Targ, Michelle Nguyen, Lenka Maliskova, Elizabeth McCarthy, Eunice Wan, Simon Wong, Lauren Byrnes, Cristina M Lanata, and others. Multiplexed droplet single-cell rna-sequencing using natural genetic variation. Nature biotechnology, 36(1):89–94, 2018.

[gspaKSB+21]

Gennady Korotkevich, Vladimir Sukhov, Nikolay Budin, Boris Shpak, Maxim N Artyomov, and Alexey Sergushichev. Fast gene set enrichment analysis. BioRxiv, pages 060012, 2021.

[gspaLCS+18]

Blue B Lake, Song Chen, Brandon C Sos, Jean Fan, Gwendolyn E Kaeser, Yun C Yung, Thu E Duong, Derek Gao, Jerold Chun, Peter V Kharchenko, and others. Integrative single-cell analysis of transcriptional and epigenetic states in the human adult brain. Nature biotechnology, 36(1):70–80, 2018.

[gspaLCK+08]

Eunjung Lee, Han-Yu Chuang, Jong-Won Kim, Trey Ideker, and Doheon Lee. Inferring pathway activity toward precise disease classification. PLoS computational biology, 4(11):e1000217, 2008.

[gspaLSP+11]

Arthur Liberzon, Aravind Subramanian, Reid Pinchback, Helga Thorvaldsdóttir, Pablo Tamayo, and Jill P Mesirov. Molecular signatures database (msigdb) 3.0. Bioinformatics, 27(12):1739–1740, 2011.

[gspaLMM16]

Aaron TL Lun, Davis J McCarthy, and John C Marioni. A step-by-step workflow for low-level analysis of single-cell rna-seq data with bioconductor. F1000Research, 2016.

[gspaRPW+15]

Matthew E Ritchie, Belinda Phipson, DI Wu, Yifang Hu, Charity W Law, Wei Shi, and Gordon K Smyth. Limma powers differential expression analyses for rna-sequencing and microarray studies. Nucleic acids research, 43(7):e47–e47, 2015.

[gspaSKKlunemann+18]

Michael Schubert, Bertram Klinger, Martina Klünemann, Anja Sieber, Florian Uhlitz, Sascha Sauer, Mathew J Garnett, Nils Blüthgen, and Julio Saez-Rodriguez. Perturbation-response genes reveal signaling footprints in cancer gene expression. Nature communications, 9(1):1–11, 2018.

[gspaSmy05]

Gordon K Smyth. Limma: linear models for microarray data. In Bioinformatics and computational biology solutions using R and Bioconductor, pages 397–420. Springer, 2005.

[gspaSTM+05] (1,2)

Aravind Subramanian, Pablo Tamayo, Vamsi K Mootha, Sayan Mukherjee, Benjamin L Ebert, Michael A Gillette, Amanda Paulovich, Scott L Pomeroy, Todd R Golub, Eric S Lander, and others. Gene set enrichment analysis: a knowledge-based approach for interpreting genome-wide expression profiles. Proceedings of the National Academy of Sciences, 102(43):15545–15550, 2005.

[gspaZLX+19]

Xinxin Zhang, Yujia Lan, Jinyuan Xu, Fei Quan, Erjie Zhao, Chunyu Deng, Tao Luo, Liwen Xu, Gaoming Liao, Min Yan, and others. Cellmarker: a manually curated resource of cell markers in human and mouse. Nucleic acids research, 47(D1):D721–D728, 2019.

[gspaZMH+20] (1,2,3)

Yaru Zhang, Yunlong Ma, Yukuan Huang, Yan Zhang, Qi Jiang, Meng Zhou, and Jianzhong Su. Benchmarking algorithms for pathway activity transformation of single-cell rna-seq data. Computational and structural biotechnology journal, 18:2953–2961, 2020.

20.10. 贡献者#

我们衷心感谢以下人员的贡献:

20.10.1. 作者#

  • Lukas Heumos

  • Anastasia Litinetskaya

  • Soroor Hediyeh-Zadeh

20.10.2. 审阅者#