# 第 11 章 细胞通讯分析基础：CellChat

> 本章对应脚本：`code/06_cellchat.R`。
> 前置：完成第 8–10 章，手头有一个经过预处理、注释、生态位划分的 Visium 乳腺癌 Seurat 对象 `obj`。

从这一章开始，我们进入全书的核心轨道——细胞通讯（cell-cell communication, CCC）分析。前 10 章回答的是“肿瘤微环境（tumor microenvironment, TME）里有什么、长在哪里”；从本章起要回答“它们之间在说什么”。肿瘤不是一堆细胞的简单集合，而是靠细胞通讯组织起来的“社会”：肿瘤细胞招募血管、驯化免疫细胞，成纤维细胞为肿瘤铺路……这些对话正是肿瘤进展的引擎。本章用 R 包 CellChat v2 作为主工具，讲清楚三件事：为什么需要推断通讯、CellChat 是怎么推断的、跑完流程后怎么读图。

## 本章目标

1. 理解为什么“表达 ≠ 通讯”，以及配体-受体（ligand-receptor, L-R）证据为什么是必需的
2. 用“讲人话”的方式理解 CellChat 原理：L-R 数据库 → 通讯概率 → 排列检验 → 通路聚合
3. 学会安装 CellChat v2，并从 Seurat 对象构建 CellChat 对象（重点：Visium 场景的“细胞类型”从哪来）
4. 掌握完整分析流程（subsetData → computeCommunProb → … → aggregateNet）与 5 种经典可视化
5. 学会“读图说话”，并牢记：通讯推断是计算预测，不是直接测量

## 1 为什么推断细胞通讯：表达 ≠ 通讯

### 1.1 表达矩阵只是“原材料清单”

每个 spot（或单细胞）的表达矩阵，本质是一张“原材料清单”：它告诉我们某个基因在这个位置转录了多少。但“细胞 A 表达了配体基因 X”远不等于“细胞 A 正在跟别人通讯”。想象一场对话：A 说了话（表达配体），但 B 得长着耳朵（表达受体）才听得见；两人还得离得够近（空间邻近），声音才传得到；而且 A 说的可能是“废话”（蛋白没有功能活性，或存在抑制物、诱饵受体）。所以从“表达”到“通讯”，中间隔着至少四道证据关卡：

1. **受体证据**：接收者细胞群必须表达对应的受体；
2. **空间证据**：配体细胞与受体细胞在空间上足够接近（旁分泌需要邻近，近分泌/接触型需要直接接触）；
3. **功能证据**：互作真的发生且产生下游效应（mRNA 水平只是代理指标，蛋白质、翻译后修饰、可溶/膜结合形式都会影响）；
4. **统计证据**：观察到的共表达不是随机碰巧。

### 1.2 配体-受体互作数据库：通讯的“字典”

既然表达矩阵不能直接告诉我们“谁在跟谁说话”，我们就需要外部知识——配体-受体（L-R）互作数据库。它相当于一本经过人工整理的“通讯字典”：条目是“配体 → 受体”（如 CXCL12 → CXCR4、CD274/PD-L1 → PDCD1/PD-1），并注明这条互作属于哪类信号。推断算法的任务，就是拿着表达矩阵去查这本字典：发送者表达配体、接收者表达受体，且统计上显著——就记一条“疑似通讯”。CellChat 用的字典叫 CellChatDB（见 2.1 节）。请注意：查字典只能发现“字典里有的词”，全新或未注释的互作是推断不出来的，这一点在第 7 节还会强调。

## 2 CellChat 原理（讲人话）

### 2.1 CellChatDB：三类互作的数据库

CellChatDB 是 CellChat 自带的 L-R 数据库，互作按生物学类别分为三类：

- **分泌信号（secreted signaling）**：可溶性配体分泌到胞外，作用于邻近或远处细胞的受体，如趋化因子、细胞因子、生长因子；
- **ECM-受体（ECM-receptor）**：细胞外基质（如胶原、纤连蛋白）与细胞表面受体（如整合素）的互作，如 FN1-ITGA5、SPP1-CD44；
- **细胞-细胞接触（cell-cell contact）**：膜结合配体与相邻细胞受体的直接接触，包含共刺激与共抑制分子，如 PD-L1/PD-1、CD86-CTLA4。

v2 版本大幅扩展了数据库：支持更多物种（人类、小鼠、斑马鱼等）与更多互作条目，并新增了空间转录组分析模式（见 3.3 节）。

### 2.2 通讯概率：质量作用定律的思想

CellChat 估计“细胞群 A 通过配体 L 向细胞群 B 通讯”的概率，核心思想来自化学里的质量作用定律（law of mass action）：反应速率与反应物浓度乘积成正比。类比过来：**通讯概率 ∝ 发送者群中配体的平均表达 × 接收者群中受体的平均表达**。具体实现时还做了几件事：

- 用三均值（triMean，一种去掉两端极端值后的稳健平均）聚合群内细胞的表达，避免个别高表达细胞带偏整个群；
- 考虑“群里有多少比例的细胞表达该基因”（只有少数细胞表达时通讯不可靠）；
- 多亚基配体/受体（如 TGF-β 需要 TGFBR1 与 TGFBR2 两个亚基）按复合体方式合并；
- 乘以细胞群大小比例（population.size）：大细胞群发出/接收的信号总量更大。

### 2.3 排列检验：这个通讯显著吗

表达总是有噪声的，A 表达配体、B 表达受体也可能纯属巧合。CellChat 用排列检验（permutation test）判断显著性：把细胞类型标签随机打乱（保持各类数量不变），重新计算通讯概率，重复约 1000 次，得到“纯靠运气”时的概率分布；把真实观测值放进去，如果它大于 95% 的随机值，就认为显著（p < 0.05）。这一步由 `computeCommunProb` 内置完成，不需要我们手动实现。

### 2.4 通路级聚合：从基因对到通路网络

单条 L-R 对太细碎（人类数据库里有几千对），不利于讲故事。CellChat 提供两级聚合：

- `computeCommunProbPathway`：把属于同一信号通路的多条 L-R 对合并（如 TGFb 通路包含 TGFB1-TGFBR1、TGFB1-TGFBR2 等多对），得到“通路级”通讯概率；
- `aggregateNet`：再把所有通路汇总成一张全网络，得到每个细胞群对之间的显著互作数量（count）与通讯强度（weight）。

所以 CellChat 输出的是一套分层的网络：L-R 对级 → 通路级 → 网络级，我们按需取用。

## 3 安装 CellChat v2 与对象构建

### 3.1 安装

CellChat v2 不在 CRAN，需要从 GitHub 安装（[Jin 2024]；仓库 https://github.com/jinworks/CellChat）。依赖包较多（NMF、ComplexHeatmap 等），Windows 用户请先装好 Rtools（Bioconductor 包必需）。安装只需一次：

```r
# Windows 用户先装 Rtools（https://cran.r-project.org/bin/windows/Rtools/）并配置好 PATH
install.packages("devtools")
# 安装依赖与 CellChat v2（编译需几分钟，耐心等待）
devtools::install_github("jinworks/CellChat")
library(CellChat)
packageVersion("CellChat")   # 本书以 v2.x 为例
```

运行结果解读：若最后一行打印出版本号（如 2.1.x）且没有报错，说明安装成功。常见报错多为缺少系统编译工具（Rtools）或某个依赖包版本过旧，按提示补装即可。

### 3.2 从 Seurat 构建 CellChat 对象

```r
library(Seurat)
# obj 是第 8–10 章的结果：Visium 乳腺癌 Seurat 对象
# group.by 指定"细胞类型"列（第 9 章注释/去卷积得到的 celltype 列）
DefaultAssay(obj) <- "SCT"                       # 使用 SCTransform 归一化后的数据
cellchat <- createCellChat(object = obj, group.by = "celltype")
# 载入人类配体-受体数据库（CellChatDB.human 是包内自带对象）
cellchat@DB <- CellChatDB.human
```

运行结果解读：`createCellChat` 会打印每个细胞群的细胞数，并提示数据读取完成。这里有一个 Visium 场景的关键点需要理解：**每个 spot 是 1–10 个细胞的混合体**（见 00-TECH 第 1 节），所以“细胞类型”列不可能像单细胞数据那样干净。实践中 `celltype` 列通常来自两种做法：一是注释策略（第 9 章），给每个 spot 一个“主要细胞类型”标签；二是去卷积（deconvolution，如 cell2location）后，把丰度最高的细胞类型作为标签，或按丰度比例对通讯概率加权。本书教程采用“主要细胞类型”标签，理解其混合信号局限即可（见第 7 节）。

### 3.3 v2 的两种空间模式

CellChat v2 针对空间转录组提供两种模式：**细胞群模式（cell groups）**——把同一类型的细胞/spot 合成一组，比较“组与组”之间的通讯，这也是本书主要使用的模式；**细胞-spot 模式（cell-spot）**——保留单个 spot 的身份，利用空间坐标推断 spot 与 spot 之间的通讯（适合高分平台）。当传入的对象自带空间坐标时，v2 会自动启用空间模式，无需额外设置。

## 4 完整分析流程

下面的代码是全书通讯分析的“标准动作”，第 12、13 章会反复使用：

```r
# ---- CellChat 完整流程（每步都解释"为什么"）----
# 1) 只保留数据库中有互作记录的基因，大幅节省内存与时间
cellchat <- subsetData(cellchat)
# 2) 找出每个细胞群中相对其他群"过表达"的基因（判断互作强度的基础）
cellchat <- identifyOverExpressedGenes(cellchat)
# 3) 标记"配体和受体都过表达"的 L-R 对，缩小候选范围
cellchat <- identifyOverExpressedInteractions(cellchat)
# 4) 核心步骤：质量作用定律估计通讯概率 + 内置排列检验（约 1000 次）
#    可选并行加速：future::plan("multisession", workers = 4)
cellchat <- computeCommunProb(cellchat, type = "triMean")
# 5) 过滤：要求每个细胞群至少有 min.cells 个细胞，小群不参与推断
cellchat <- filterCommunication(cellchat, min.cells = 10)
# 6) 通路级聚合：把同一通路的多条 L-R 对合并
cellchat <- computeCommunProbPathway(cellchat)
# 7) 网络级聚合：得到 net$count（显著互作数量）与 net$weight（通讯强度）
cellchat <- aggregateNet(cellchat)
# 8) 保存结果，方便下次直接读取，不必重跑
saveRDS(cellchat, file = "results/cellchat_global.rds")
```

运行结果解读：第 4 步最耗时（几分钟到几十分钟，取决于细胞群数与基因数）。完成后可用 `cellchat@net$count` 查看“群 × 群”的显著互作数量矩阵，`cellchat@net$weight` 查看通讯强度矩阵，`dim(cellchat@netP$prob)` 查看通路级概率数组（第三维是通路名）。此外，`cellchat@net$pval` 保存了每条 L-R 对的排列检验 p 值，第 13 章做差异分析时会用到。

## 5 经典可视化逐个讲解

这一节介绍 5 张最常用的“看图工具”，它们分别回答不同层次的问题：netVisual_circle 看“整体网络长什么样”，netVisual_bubble 看“具体哪对配体-受体在说话”，netVisual_heatmap 看“谁发给谁的整体强度”，rankNet 看“哪些通路是主旋律”，netAnalysis_signalingRole 看“每个细胞群在对话中的角色”。建议的学习顺序：先用 circle 建立整体印象，再用 bubble 与 heatmap 追问细节，最后用 rankNet 与 signalingRole 提炼结论。

### 5.1 netVisual_circle：圆形网络图

```r
# 圆形网络：节点 = 细胞群，边 = 显著通讯；边越粗 = 强度越大
netVisual_circle(cellchat,
                 vertex.weight = table(cellchat@idents),
                 weight.scale = TRUE,
                 label.edge = FALSE,
                 title.name = "通讯数量")
```

解读要点：先看“有哪些边”（哪些细胞群在对话）、再看“边有多粗”（对话有多强）、最后看“节点大小”（通常代表细胞数）。

![图 11-1 三个生态位的通讯网络对比（模拟数据演示）。圆形网络图中每个节点代表一种细胞类型，边代表细胞群之间的显著通讯，边越粗通讯强度越大；图内标注了各生态位最强的配体-受体信号。](figures/fig12_comm_network.png){width=90%}

### 5.2 netVisual_bubble：气泡图

```r
# 气泡图：行 = 指定通路的 L-R 对，列 = "发送者→接收者"
# 气泡大小 = 通讯概率，颜色 = p 值（越红越显著）
netVisual_bubble(cellchat, signaling = c("TGFb", "MIF", "CXCL"))
```

气泡图适合回答“具体是哪一对配体-受体在说话、说得多响”。

### 5.3 netVisual_heatmap：热图

```r
# 热图：发送者（行）× 接收者（列）的通讯强度，适合全局扫一眼
netVisual_heatmap(cellchat, signaling = "TGFb", type = "heatmap")
```

### 5.4 rankNet：通路排序

```r
# 按"相对贡献"给所有通路排序：哪些通路是这台组织的"主旋律"
rankNet(cellchat)
```

### 5.5 netAnalysis_signalingRole：信号角色

```r
# 每个细胞群作为"发送者（outgoing）/接收者（incoming）"的贡献
# 左图：各群的发送/接收总强度条形图；右图：二维散点定位角色
netAnalysis_signalingRole(cellchat)
```

解读：落在右上角的细胞群是“既爱说又爱听”的中心节点，例如肿瘤核心的内皮细胞往往同时接收 VEGF 信号并分泌趋化因子。

## 6 结果解读示例：读图说话

以图 11-1（模拟数据演示）为例，教大家一套“读图说话”的套路。三张圆形网络并排：侵袭前沿（invasive front）的网络中，肿瘤细胞与 CAF 之间的边最粗，且标注了 TGFb——这说明在肿瘤-基质交界处存在活跃的旁分泌回路；免疫浸润区（immune-infiltrated region）的网络里，B 细胞与 T 细胞之间的边突出（CXCL 相关），提示存在 T-B 免疫互作；肿瘤核心（tumor core）的网络较小但带有 VEGF 信号，指向血管生成。写进论文时可以这样说：“侵袭前沿的通讯网络以肿瘤细胞-CAF 的 TGF-β 回路为特征，免疫浸润区以 T-B 细胞趋化互作为特征，肿瘤核心以血管生成信号为特征，提示不同生态位执行不同的通讯程序。”——注意要加上“这提示……”的措辞，因为一切都还只是计算预测（见第 7 节）。

## 7 注意事项

1. **通讯推断是计算预测，不是直接测量**。CellChat 的依据是 mRNA 表达，而真正的通讯还受蛋白水平、翻译后修饰、空间距离、抑制因子等影响。结论落地前需要空间共定位证据（Squidpy 邻域富集，见第 10 章）、表达证据，必要时做实验验证（抗体中和、基因敲除、类器官共培养）。
2. **spot 混合信号问题**：Visium 的 spot 覆盖 1–10 个细胞，注释标签本身有误差，通讯推断会继承这个误差。解读时不要把“spot 之间的通讯”说成“细胞之间的通讯”。
3. **单样本是探索性的**：一个切片 = n = 1，个体差异无法评估；任何“上调/下调”结论都需要生物学重复支持。
4. **参数透明**：`type`（聚合方式）、`min.cells`、显著性阈值都会影响结果，写作时要把参数写进方法部分。
5. **数据库的边界**：CellChatDB 收录有限，未收录或新型互作不会被发现，阴性结果要谨慎下结论。

## 本章小结

本章把通讯推断从“黑盒”变成了“白盒”：表达只是原材料，通讯需要 L-R 字典 + 统计推断；CellChat 用质量作用定律估计通讯概率、用排列检验控制假阳性、用两级聚合把几千对互作浓缩成通路与网络。我们跑通了完整流程，并学会了 5 种经典可视化的读法。下一章将把这套流程“搬进”每个生态位内部——这正是全书创新点的操作化起点。

## 练习与思考

1. 请列出从“表达”到“通讯”之间缺失的至少 3 个证据环节，并说明 CellChat 只能覆盖其中哪些。
2. 排列检验在 CellChat 中扮演什么角色？如果不做这一步，推断结果会有什么问题？
3. （动手题）用本书示例乳腺癌数据构建 CellChat 对象并跑完第 4 节流程，再用 `netVisual_bubble` 找出免疫浸润区中 T 细胞与 B 细胞之间最强的 5 个 L-R 对。
4. （思考题）如果一个 spot 同时被注释为“肿瘤细胞”和“CAF”（混合信号），它对通讯推断会造成什么偏倚？去卷积方法能改善吗？
