先确认版本
CellChat 的仓库从 sqjin/CellChat 迁到 jinworks/CellChat。当前 GitHub main 是 2.2.0.9001(2026-03-04 最后提交),最后一个 release 标签是 v2.1.2。网上标着“v3”的是独立的 SpatialCellChat 包,只用于空间转录组;单细胞数据继续用 CellChat v2。
写论文方法部分时记录 packageVersion("CellChat") 和安装日期。GitHub main 在两次 release 之间也在变化,例如 2026-02-19 合入的 PR #438 改变了并行行为,2026-03-04 修改了 rankNet。
| 项目 | v1 时期教程(2021–2023) | 当前 v2 | 照抄旧写法的后果 |
|---|---|---|---|
| 数据库规模 | CellChatDB.human 约 1,939 对 | 3,233 对:v1 来源 1,920 对,v2 新增 1,313 对(994 对 Non-protein Signaling、233 对 Cell-Cell Contact、83 对 Secreted);mouse 3,379 对 | 直接用全库会把代谢物和神经递质信号混进来 |
| 过表达基因检验 | Seurat 风格 Wilcoxon | 默认 do.fast = TRUE 调用 presto;未装 presto 直接报错 | PBMC 3k 同一数据:presto 得到 400 个过表达信号基因,do.fast = FALSE 得到 744 个,v1 与 v2 的结果不能直接对比 |
| PPI 平滑 | projectData(cellchat, PPI.human) | 改名 smoothData,必须写 adj = PPI.human | 报 is(adj, "matrix") || is(adj, "sparseMatrix") is not TRUE(GitHub #185) |
| 对象槽位 | data.project | data.smooth | 旧对象报 no slot of name "data.smooth";维护者未修复,用户的做法是 obj@data.smooth <- matrix(nrow = 0, ncol = 0)(GitHub #202) |
| meta | 只需标签列 | 还需要 samples 列;缺失时自动设为 sample1 并给警告 | 多样本合并后无法用 min.samples 过滤 |
| 并行 | plan("multiprocess") | future 已删除 multiprocess 后端 | 报 No such backend for futures: 'multiprocess' |
| 空间转录组 | v1.6 起支持 Visium | v2 支持多种空间技术;单细胞分辨率空转用 SpatialCellChat(v3) | — |
第 1 步
CellChat 只能从 GitHub 安装,包含 C++ 代码,需要编译器。依赖中最容易出问题的是 NMF(CRAN,需要 Biobase)、ComplexHeatmap 与 BiocNeighbors(Bioconductor)、presto(GitHub)。本页用 conda 装好其余依赖后,NMF、presto、CellChat 三个包编译安装共 2.5 分钟,没有报错。Nature Protocols 给出的最低配置是双核 CPU、16 GB 内存。
# 方案 A:conda 装依赖(本页实测,macOS arm64,约 4 分钟 + 编译 2.5 分钟)
micromamba create -y -n cellchat -c conda-forge -c bioconda \
r-base=4.5 r-seurat r-remotes r-rcppeigen c-compiler cxx-compiler fortran-compiler make \
r-future r-future.apply r-pbapply r-irlba r-ggalluvial r-svglite r-ggrepel r-circlize \
bioconductor-complexheatmap bioconductor-biocneighbors bioconductor-biobase \
r-rspectra r-reticulate r-sna r-fnn r-shape r-ggpubr r-ggnetwork r-plotly r-shiny r-bslib \
r-collapse r-pkgmaker r-registry r-rngtools r-gridbase r-doparallel r-cowplot r-uwot
micromamba run -n cellchat Rscript -e '
options(repos = c(CRAN = "https://cloud.r-project.org"))
install.packages("NMF") # conda-forge 没有 r-nmf
remotes::install_github("immunogenomics/presto", upgrade = "never")
remotes::install_github("jinworks/CellChat", upgrade = "never")
packageVersion("CellChat")'
# 方案 B:已有 R 4.4 以上
# install.packages(c("BiocManager", "remotes", "NMF"))
# BiocManager::install(c("ComplexHeatmap", "BiocNeighbors", "Biobase"))
# remotes::install_github(c("immunogenomics/presto", "jinworks/CellChat"), upgrade = "never")| 报错或现象 | 原因 | 解决 |
|---|---|---|
| Skipping 3 packages not available: Biobase, BiocNeighbors, BiocGenerics | remotes 不会自动装 Bioconductor 包 | 先 BiocManager::install(c("Biobase", "BiocNeighbors", "BiocGenerics", "ComplexHeatmap")) |
| Failed to connect to github.com / 下载超时 | 国内访问 GitHub 不稳定 | conda 或 Bioconductor 镜像装好依赖,只剩 presto 与 CellChat 两个 GitHub 包;仍失败时下载源码 zip 后 R CMD INSTALL |
| installation of package ... had non-zero exit status(macOS) | Xcode 命令行工具缺失或损坏 | 重新安装 Xcode 命令行工具(GitHub #226 两位用户确认),或用 conda 的 c-compiler、cxx-compiler |
| no member named 'Rlog1p' in namespace 'std' | Apple 芯片上旧版 R 与编译器的组合问题 | export PKG_CPPFLAGS="-DHAVE_WORKING_LOG1P" 后重装(中文经验帖,2023) |
| CMake was not found on the PATH | 某个依赖需要 CMake | conda install cmake |
| dependencies 'RSpectra', 'RcppEigen', 'ggpubr', 'BiocNeighbors' are not available | CRAN 与 Bioconductor 依赖未装全 | BiocManager::install() 补装,或用 conda-forge 的 r-* 包 |
| For a faster implementation of the Wilcoxon Test, please install the presto package | v2 默认用 presto | remotes::install_github("immunogenomics/presto");装不上时 identifyOverExpressedGenes(do.fast = FALSE),但结果与 presto 不同 |
第 2 步
CellChat 需要两样东西:log 归一化的表达矩阵(基因为行、细胞为列)和每个细胞的分组标签。下面的写法在 Seurat 5.5.1 上验证过,注释说明了每一行防止的错误。
library(Seurat)
library(CellChat)
seu <- readRDS("pbmc3k_annot.rds") # 已注释的 Seurat v5 对象
seu <- JoinLayers(seu) # 多样本对象先合并 layer,否则只取到第一层
seu$celltype <- droplevels(factor(seu$celltype))
stopifnot(!anyNA(seu$celltype)) # 标签不能有 NA
data.input <- LayerData(seu, assay = "RNA", layer = "data") # log 归一化值,不是 counts
stopifnot(min(data.input) >= 0) # 不能用 scale.data 或 integrated
meta <- data.frame(
labels = seu$celltype,
samples = factor(seu$orig.ident), # v2 需要 samples 列
row.names = colnames(seu)
)
# 数字聚类号要加前缀,CellChat 不接受标签 "0"
# meta$labels <- factor(paste0("C", seu$seurat_clusters))
cellchat <- createCellChat(object = data.input, meta = meta, group.by = "labels")
table(cellchat@idents)为什么用归一化数据
CellChat 先把矩阵除以全局最大值,再代入 Hill 函数(Kh = 0.5)计算概率。用 counts 时最大值是几百,缩放后几乎所有值接近 0。本页实测:PBMC 3k 用 counts 不报错,通讯 170 条(正确输入 152 条),通路相同,总强度只有正确值的约 1/800。强度在组间和数据集间的比较因此失效。
scale.data 和 integrated 都不能用
直接传 Seurat 对象时 createCellChat 会检查负值并报错;传矩阵时不检查。本页把 scale.data(2,000 个高变基因、含负值)当矩阵传入,流程跑完且得到 201 条通讯,没有任何提示。integrated assay 只有部分基因且经过校正,CellChat 会给警告。SCT assay 的 data 层是 log1p 后的校正计数,可以使用。
拆分 layer 的对象
Seurat v5 多样本对象在 IntegrateLayers 前后可能处于拆分状态(data.A、data.B)。本页实测:直接传对象报 invalid 'row.names' length;LayerData(layer = "data") 只给警告,返回第一层的 1,319 个细胞(共 2,638 个)。先 JoinLayers。
标签的四条要求
不能含 NA;因子不能有未使用的水平;不能是数字 0(Seurat 聚类号直接用会报 Cell labels cannot contain `0`!);每个群建议多于 10 个细胞。前两条的报错相同:Please check `unique(object@idents)` and ensure that the factor levels are correct!
标签粒度:大类还是亚群
CellChat 在群与群之间计算,群内异质性会被平均掉。Nature Protocols 把这列为局限,建议需要时先做亚聚类再运行。代价是群数增加后运行时间和图的复杂度上升:GitHub #167 中一位用户 133 个群、1.1 万个细胞运行超过 11 小时。常见做法是先用大类得到全局网络,再对关心的大类拆分亚群单独运行。没有找到维护者给出的具体群数建议。
多样本数据怎么组织
维护者 sqjin 在 GitHub #62 的建议是把同一条件的所有样本合并成一个对象运行,与整合后聚类的思路一致。为减少只在单个样本中出现的通讯,meta 中写 samples 列,再用 filterCommunication(min.samples = 2) 要求通讯至少在 2 个样本中出现(v2.1.2 起)。用户在同一 issue 中报告,合并运行比逐样本运行多出 4–5% 的独有通讯。
空间转录组的额外输入
createCellChat(datatype = "spatial", coordinates = ..., spatial.factors = data.frame(ratio = ..., tol = ...)):coordinates 是全分辨率图像的像素坐标,ratio 是像素到微米的换算(Visium 为 65 / spot_diameter_fullres),tol 取 spot 直径的一半(32.5)。computeCommunProb 中 interaction.range = 250、Visium 的 contact.range = 100;单细胞分辨率技术的 contact.range 约 10。单细胞分辨率空转用 SpatialCellChat。
第 3 步
CellChatDB 把配体-受体对分为四类。官方教程示例只用 Secreted Signaling,但这只是示例;子集的选择对结果数量的影响大于任何算法参数。
只用 Secreted Signaling 的利弊
好处是结果少、图清楚、与早期文献可比。代价是免疫细胞之间最主要的接触型信号(MHC-I/II、CD45、ICAM、SELPLG 等)全部缺失:PBMC 3k 上加入 Cell-Cell Contact 后通路从 13 条增加到 34 条。研究免疫突触、T 细胞与 APC 相互作用、肿瘤免疫检查点时,用 subsetDB(CellChatDB)。
Non-protein Signaling 默认不用
官方教程写明不建议直接使用整个 CellChatDB。这一类的配体量由合成酶和转运体基因推断,单细胞数据中代谢物本身不可测。神经系统研究需要神经递质信号时单独加入,并在结果中与蛋白类信号分开解读。
物种与基因名
人用 CellChatDB.human,小鼠用 CellChatDB.mouse,另有 CellChatDB.zebrafish。基因名必须是官方 symbol:Ensembl ID 或人鼠混用时 subsetData 后几乎没有信号基因,下游报 data.use[RsubunitsV, ] 等错误。其他物种先做同源基因转换。
增加自定义配受体对
用 updateCellChatDB() 合并自己整理的 interaction、complex、cofactor、geneInfo 表(官方 Update-CellChatDB 教程)。新增的对没有通路归属时,通路层面的图不会显示它们。
| 类别 | human 对数 | 说明 | PBMC 3k 实测(triMean / truncatedMean 0.1) |
|---|---|---|---|
| Secreted Signaling | 1,280 | 分泌型旁分泌、自分泌信号 | 152 / 241 条,6 / 13 条通路 |
| ECM-Receptor | 424 | 细胞外基质-受体,组织样本中重要,血液样本中少 | — |
| Cell-Cell Contact | 535 | 需要细胞直接接触,如 MHC、ICAM、CD86 | 前三类合计(subsetDB(CellChatDB)):437 / 967 条,14 / 34 条通路 |
| Non-protein Signaling | 994 | 代谢物与神经递质,由合成酶和转运体表达推断配体量 | 全库:445 / 1,055 条,其中 Non-protein 8 / 88 条 |
第 4 步
下面是在 PBMC 3k 上跑通的核心流程。参数的含义与取值依据见代码后的表格,改动后的实测影响见下一节。
CellChatDB <- CellChatDB.human # 小鼠用 CellChatDB.mouse
cellchat@DB <- subsetDB(CellChatDB) # 去掉 Non-protein Signaling 的全部蛋白类配受体
# cellchat@DB <- subsetDB(CellChatDB, search = "Secreted Signaling", key = "annotation")
future::plan("sequential") # 小数据集顺序执行更快
cellchat <- subsetData(cellchat)
cellchat <- identifyOverExpressedGenes(cellchat) # 默认用 presto 做 Wilcoxon
cellchat <- identifyOverExpressedInteractions(cellchat)
cellchat <- computeCommunProb(cellchat,
type = "truncatedMean", trim = 0.1, # trim 只在 truncatedMean 下生效
population.size = FALSE) # 未分选样本可设 TRUE
cellchat <- filterCommunication(cellchat, min.cells = 10)
cellchat <- computeCommunProbPathway(cellchat)
cellchat <- aggregateNet(cellchat)
df.net <- subsetCommunication(cellchat) # 配体-受体层面
df.netP <- subsetCommunication(cellchat, slot.name = "netP") # 通路层面
nrow(df.net); cellchat@netP$pathways
saveRDS(cellchat, "cellchat_pbmc3k.rds")| 参数 | 默认 | 作用与取值依据 |
|---|---|---|
| identifyOverExpressedGenes 的 thresh.p | 0.05 | 用未校正 p 值筛每群过表达的信号基因;thresh.fc = 0、thresh.pc = 0。只要配体或受体之一过表达,这对就进入计算 |
| computeCommunProb 的 type | "triMean" | triMean 是 Q1、Q2、Q2、Q3 四个分位数的均值:表达细胞比例低于 25% 时组平均为 0,25%–50% 时只剩 Q3/4。结果少、偏强信号 |
| type = "truncatedMean" 的 trim | 0.1 | 两端各去掉 trim 比例后求均值:表达比例低于 trim 时组平均为 0。0.1 对应 10% 门槛,0.05 对应 5%。trim 只在 truncatedMean(以及未写进教程的 thresholdedMean)下生效。Nature Protocols 的建议:一般用 trim = 0.1;研究体系中公认的信号没有出现时,再降低 trim |
| computeAveExpr(features = , type = , trim = ) | — | 在定 trim 之前查看关心的配体、受体在各群中的组平均值;某基因在 triMean 下为 0、在 trim = 0.1 下不为 0,说明它的表达比例在 10%–25% 之间(Nature Protocols 推荐的做法) |
| population.size | FALSE | TRUE 时概率乘以两群细胞比例,适合未分选样本;分选或按细胞类型富集的样本用 FALSE |
| nboot | 100 | 置换检验次数,p 值精度为 1/nboot。实测 20 次 4.3 秒、938 条,100 次 22.6 秒、967 条,1,000 次 493 秒、972 条 |
| filterCommunication 的 min.cells | 10 | 删除细胞数小于等于 min.cells 的群(源码用 <=),恰好 10 个细胞的群也会被删 |
| raw.use | TRUE | FALSE 时使用 smoothData 平滑后的表达,用于浅测序数据补偿亚基缺失,代价是可能引入假阳性 |
参数实测
本页实测:CellChat 2.2.0.9001,Seurat 官方 PBMC 3k 流程得到的 2,638 个细胞、9 个群(血小板 13 个、DC 32 个),nboot = 100。表中“通讯”是 subsetCommunication 返回的行数(来源群-目标群-配受体对)。Nature Protocols 在特应性皮炎皮肤数据(5,011 个细胞、12 个群)上比较 triMean、trim 0.1、trim 0.05,方向相同:trim 越小,配受体对和通路越多,新增的多为弱信号。
triMean 在浅测序数据上会漏掉已知信号
PBMC 3k(Cell Ranger 1.1,每细胞中位 817 个基因)用 triMean 时 CCL、CXCL、IFN-II 三条通路都没有。改为 trim = 0.1 后出现 NK→CD14 单核、NK→FCGR3A 单核、NK→DC 的 IFNG–IFNGR1/IFNGR2,与 NK 细胞分泌 IFN-γ 的已知生物学一致。深测序数据上两种方法的差距会小一些。
trim 越小,假阳性越多
trim = 0.1 时 CCL5–CCR1 的来源包括 B 细胞和初始 CD4 T 细胞,这些群只有少量细胞表达 CCL5。置换检验的显著性是相对于随机打乱标签而言的,表达比例刚过门槛的配体也能显著。trim = 0.05 的结果适合探索,写进论文的结论建议在 trim = 0.1 和 triMean 下都成立。
population.size 改变排名,不改变列表
truncatedMean 0.1 下,TRUE 与 FALSE 的显著通讯逐行一致(241 条),总强度从 5.71 降到 0.058。发送强度排名:FALSE 时 DC 第一,TRUE 时 Memory CD4 T 第一、DC 降到第七。DC 只有 32 个细胞,这个参数决定了“小群强信号”能否排在前面。
min.cells 主要影响小群
血小板 13 个细胞:min.cells = 10 保留,trim = 0.05 时有 45 条通讯涉及血小板;min.cells = 20 全部删除。identifyOverExpressedGenes 也有 min.cells = 10 的参数,只影响差异检验。
| 数据库 | type / trim | 通讯 | 配受体对 | 通路 | 涉及血小板(min.cells = 10) | min.cells = 20 时通讯 |
|---|---|---|---|---|---|---|
| Secreted | triMean | 152 | 10 | 6 | 1 | 151 |
| Secreted | truncatedMean 0.25 | 151 | 10 | 6 | 3 | 148 |
| Secreted | truncatedMean 0.1 | 241 | 19 | 13 | 13 | 228 |
| Secreted | truncatedMean 0.05 | 402 | 37 | 23 | 45 | 357 |
| 去掉 Non-protein | triMean | 437 | 41 | 14 | 36 | 401 |
| 去掉 Non-protein | truncatedMean 0.1 | 967 | 79 | 34 | 98 | 869 |
| 去掉 Non-protein | truncatedMean 0.05 | 1,375 | 116 | 51 | 186 | 1,189 |
| 全库 | truncatedMean 0.05 | 1,527 | 130 | 57 | 203 | 1,324 |
第 5 步
aggregateNet 产生两个矩阵:net$count 是两群之间显著配受体对的个数,net$weight 是这些对的通讯概率之和。数量反映“有多少种信号”,强度反映“信号总量”,两者的排名经常不同。
groupSize <- as.numeric(table(cellchat@idents))
par(mfrow = c(1, 2), xpd = TRUE)
netVisual_circle(cellchat@net$count, vertex.weight = groupSize, weight.scale = TRUE,
label.edge = FALSE, title.name = "Number of interactions")
netVisual_circle(cellchat@net$weight, vertex.weight = groupSize, weight.scale = TRUE,
label.edge = FALSE, title.name = "Interaction strength")
pathways.show <- "MIF" # 先确认它在 cellchat@netP$pathways 里
netVisual_aggregate(cellchat, signaling = pathways.show, layout = "chord")
netVisual_heatmap(cellchat, signaling = pathways.show, color.heatmap = "Reds")
netVisual_bubble(cellchat, sources.use = c("CD14 Mono", "FCGR3A Mono"),
targets.use = c("CD8 T", "NK", "B"), remove.isolate = FALSE)
cellchat <- netAnalysis_computeCentrality(cellchat, slot.name = "netP")
netAnalysis_signalingRole_scatter(cellchat)
netAnalysis_signalingRole_heatmap(cellchat, pattern = "outgoing") +
netAnalysis_signalingRole_heatmap(cellchat, pattern = "incoming")
library(NMF); library(ggalluvial)
selectK(cellchat, pattern = "outgoing", k.range = 2:6, nrun = 10) # 默认 2:10、nrun = 30 很慢
cellchat <- identifyCommunicationPatterns(cellchat, pattern = "outgoing", k = 3)
netAnalysis_river(cellchat, pattern = "outgoing")总强度主要来自少数通路
PBMC 3k(trim = 0.1)中 MIF、GALECTIN、CypA 三条通路占总强度的 88%。全局圆图上的“最强发送者”基本反映这三条通路。解读全局网络前先看 netP 中各通路的强度,必要时用 signaling.exclude 或只画关心的通路。
信号角色分析
netAnalysis_computeCentrality 在每条通路的网络上计算出度(发送)、入度(接收)、流介数(中介)和信息中心性(影响者)。2D 散点图的横轴是发出强度、纵轴是接收强度,点大小是连接数,适合一句话概括“哪个群主要在发信号”。
模式识别与 selectK
identifyCommunicationPatterns 用 NMF 把群与通路分解为 k 个模式。selectK 默认 k = 2:10、每个 k 跑 30 次,本页 13 条通路、9 个群用了 78 秒;k = 2:6、nrun = 5 用 34 秒。通路达到 50 条以上、群达到 20 个以上时 selectK 需要数十分钟到数小时。官方解释是选 Cophenetic 和 Silhouette 开始明显下降前的 k;通路很少(少于 10 条)时模式分析信息量很低,可以跳过。
概率值本身没有绝对意义
通讯概率依赖于全局最大表达值、Hill 函数参数和平均方法。同一数据换 type 或 trim,概率会整体变化;只有参数和归一化方式相同时,数据集之间的概率才可比较。
| 图 | 函数 | 回答的问题 | 注意 |
|---|---|---|---|
| 圆图(全局) | netVisual_circle(net$count 或 net$weight) | 哪些群之间通讯多、哪个群是主要发送者 | 比较两个数据集时用 edge.weight.max 统一尺度 |
| 单通路圆图、和弦图、层级图 | netVisual_aggregate(signaling = , layout = ) | 某条通路由谁发、谁收 | 通路不显著时报 There is no significant communication of XXX;先查 cellchat@netP$pathways |
| 热图 | netVisual_heatmap(signaling = ) | 某条通路在所有群对之间的强度矩阵 | 颜色按该通路内部缩放,不能跨通路比较颜色 |
| 气泡图 | netVisual_bubble(sources.use, targets.use) | 指定群之间具体是哪些配受体对、概率和 p 值 | 最适合放进论文正文;群可以用名称或序号指定 |
| 配受体和弦图 | netVisual_chord_gene | 某个群发出或收到的全部配受体对 | 对太多时字重叠,调 small.gap 或限定 signaling |
| 贡献图 | netAnalysis_contribution | 某条通路中哪个配受体对贡献最大 | — |
| 信号角色 | netAnalysis_signalingRole_scatter / _heatmap / _network | 每个群是发送者、接收者、中介还是影响者 | 先运行 netAnalysis_computeCentrality;热图按行缩放 |
第 6 步
CellChat 的比较流程是每组单独运行、再合并。前提是:两组用同一套注释(同一列、同样的名称)、同样的数据库子集和参数;两组的细胞类型集合一致,不一致时先 liftCellChat。
run_cellchat <- function(obj) {
meta <- data.frame(labels = droplevels(obj$celltype), # 本组没有的类型必须去掉
samples = factor(obj$sample), row.names = colnames(obj))
cc <- createCellChat(LayerData(obj, assay = "RNA", layer = "data"), meta = meta, group.by = "labels")
cc@DB <- subsetDB(CellChatDB.human, search = "Secreted Signaling", key = "annotation")
cc <- subsetData(cc)
cc <- identifyOverExpressedGenes(cc)
cc <- identifyOverExpressedInteractions(cc)
cc <- computeCommunProb(cc, type = "truncatedMean", trim = 0.1) # 两组参数必须相同
cc <- filterCommunication(cc, min.cells = 10)
cc <- computeCommunProbPathway(cc)
cc <- aggregateNet(cc)
netAnalysis_computeCentrality(cc, slot.name = "netP")
}
# 两组使用同一套标签(同一列注释、同样的写法)
seu$celltype <- factor(seu$celltype)
cc.ctrl <- run_cellchat(subset(seu, stim == "CTRL"))
cc.stim <- run_cellchat(subset(seu, stim == "STIM"))
# 某组缺少某个细胞类型时,先补齐到同一组标签
grp <- union(levels(cc.ctrl@idents), levels(cc.stim@idents))
if (!identical(levels(cc.ctrl@idents), levels(cc.stim@idents))) {
cc.ctrl <- liftCellChat(cc.ctrl, group.new = grp)
cc.stim <- liftCellChat(cc.stim, group.new = grp)
}
object.list <- list(CTRL = cc.ctrl, STIM = cc.stim)
cellchat <- mergeCellChat(object.list, add.names = names(object.list))
compareInteractions(cellchat, show.legend = FALSE, group = c(1, 2)) +
compareInteractions(cellchat, show.legend = FALSE, group = c(1, 2), measure = "weight")
netVisual_diffInteraction(cellchat, weight.scale = TRUE, measure = "weight") # 红色 = STIM 增强
rankNet(cellchat, mode = "comparison", measure = "weight", stacked = TRUE, do.stat = TRUE)
netVisual_bubble(cellchat, sources.use = "CD14 Mono", comparison = c(1, 2),
max.dataset = 2, title.name = "Increased in STIM", angle.x = 45, remove.isolate = TRUE)因子水平:每组 droplevels,再 lift
常见做法是给两组设同样的因子水平,以保证顺序一致。当某组缺少某个细胞类型时,这会让 computeCommunProb 报 factor levels 错误。正确顺序是每组单独 droplevels,计算完成后用 liftCellChat(group.new = union(...)) 补齐。不 lift 直接合并,mergeCellChat 本身不报错,后续 netVisual_diffInteraction 报 non-conformable arrays。
本页两组实测
Kang 2018 数据(CTRL 6,548 个细胞,STIM 7,451 个,13 类),Secreted、trim = 0.1:CTRL 421 条通讯、13 条通路,STIM 542 条、14 条;总强度 4.30 到 10.79。CD14 单核发出的增强配受体对包括 CXCL10/CXCL11–CXCR3、CCL8–CCR1、CCL7–CCR1,符合干扰素诱导趋化因子的预期。每组计算 26–43 秒,两组流程峰值内存 3.3–3.6 GB。
两种“差异”的区别
netVisual_bubble(comparison, max.dataset) 和 rankNet 比较的是通讯概率;netMappingDEG 按条件间差异表达筛选配体或受体上调的对。v2 用 presto 计算的 logFC 比 v1 小,官方把 thresh.fc 从 0.1 改为 0.05。同一配受体对可能同时出现在上调和下调结果中,原因是差异分析在每个细胞群内分别进行;需要忽略细胞群时设 group.DE.combined = TRUE。
统计检验的单位
rankNet(do.stat = TRUE) 的配对 Wilcoxon 检验以群对为单位,不考虑生物学重复。每组只有一个合并样本时,“显著上调的通路”只能说明这次测序中的差异。有多个样本时,用 min.samples 过滤,或改用以样本为单位建模的 MultiNicheNet、LIANA+ 做补充。
组成差异大的数据集
例如胚胎皮肤与成年伤口:netVisual_diffInteraction 和功能相似性(computeNetSimilarityPairwise(type = "functional"))不再适用,结构相似性(type = "structural")和各自的圆图仍可用。
作图时统一尺度
分别画两组的圆图时,用 getMaxWeight(object.list, attribute = c("idents", "count")) 取两组的最大值,传给 edge.weight.max 和 vertex.weight.max;否则两张图各自归一化,线宽不能比较。
排错
下表的报错原文来自本页复现或 GitHub issue,按出现的步骤排列。
并行:本页在 2,638 个细胞上实测,future::plan("multisession", workers = 4) 让 identifyOverExpressedGenes 从 0.1 秒变成 25.1 秒,computeCommunProb 从 5.8 秒变成 26.3 秒。GitHub #357 中多位用户报告相同现象(Ubuntu 上从 0.9 秒变成 368 秒)。PR #438(2026-02-19 合入)把置换检验循环改为并行,PR 作者报告 4 万个细胞、64 核从约 46 小时降到 5.2 小时。因此一万个细胞以下用 plan("sequential");大数据先确认安装的是 2026-02-19 之后的 main,再用 multisession,并设置 options(future.globals.maxSize = 4e9)。来源之间存在分歧:Nature Protocols 报告约 30 万个细胞的皮肤图谱推断约 15 分钟,而 GitHub 上多位用户报告数万细胞需要数小时,差异来自群数、数据库子集、nboot、版本和并行设置。另一位用户的经验是 9 万个细胞、6 个群、单核 500 GB 内存时,computeCommunProb 之前的步骤约 4 小时完成(GitHub #167)。
大数据还可以先降采样:Seurat 的 subset(obj, downsample = 500) 或 CellChat 的 sketchData,对大群抽样、小群全保留。降采样后显著通讯的列表通常稳定,强度会变化。
| 报错原文 | 原因 | 处理 |
|---|---|---|
| Cell labels cannot contain `0`! | 直接用 Seurat 聚类号作标签 | factor(paste0("C", seurat_clusters)) |
| Please check `unique(object@idents)` and ensure that the factor levels are correct! | 标签有 NA,或因子有未使用水平(subset 后最常见) | 删除 NA 细胞;meta$labels <- droplevels(meta$labels) |
| invalid 'row.names' length(Seurat 对象输入) | Seurat v5 layer 处于拆分状态 | JoinLayers(obj) 后再创建 |
| Error in if (sum(P1) == 0) : missing value where TRUE/FALSE needed | 输入含负值或 NA,例如 scale.data、integrated 或 Python 端标准化后的矩阵(GitHub #79) | 换成 log 归一化的 data 层 |
| Error in integer(n) : invalid 'length' argument | 2023 年 11 月以前的 v2 用全库时 LTE4-DPEP1 复合物导致(GitHub #1);Seurat 也有同名的 subsetData | 更新 CellChat;调用写成 CellChat::subsetData(cellchat) |
| There is no significant communication of XXX | 该通路在本数据中不显著 | 从 cellchat@netP$pathways 中选择通路 |
| netVisual_circle: need finite 'xlim' values | net$count 全为 0:没有显著通讯 | 查 subsetCommunication(cellchat) 行数;检查物种数据库、基因名、标签;放宽 type 或 trim |
| 某组 aggregateNet 后某个群没有任何通讯 | 该群细胞数 ≤ min.cells 被过滤,或该群确实无显著信号 | table(cellchat@idents) 确认细胞数;比较时用 liftCellChat 保持群一致 |
| The input `color.use` should be a named vector! | 自定义颜色未命名或数量与群不一致 | color.use 用 setNames(颜色, levels(cellchat@idents)) |
| Length of new attribute value...(netVisual_circle) | igraph 1.4.0 的兼容问题(Nature Protocols 表 1) | igraph 降到 1.3.5,或 updateCellChat(),或重装 CellChat |
| 合并对象上 netAnalysis_computeCentrality 报错 | 该函数要在每个单独对象上运行(Nature Protocols 表 1) | 对 object.list 中每个对象先运行 netAnalysis_computeCentrality,再 mergeCellChat |
| 多核设置后运行变慢数倍 | multisession 的进程间传输开销;2026-02 以前的版本只并行了一小部分计算 | 见下一段 |
工具选择
Dimitrov 等(Nature Communications 2022)比较了 16 个数据库和 7 种方法,结论是方法和数据库的选择都会显著改变预测结果。Liu 等(Genome Biology 2022)用空间转录组作参照评估 16 种方法,CellChat、CellPhoneDB、NicheNet、ICELLNET 整体表现较好,作者建议至少用两种方法交叉验证。
| 工具 | 语言 | 回答的问题 | 适合 | 不适合 |
|---|---|---|---|---|
| CellChat v2 | R | 群与群之间哪些配受体对、哪些通路显著,网络角色和模式 | Seurat 用户;需要大量现成图和两组比较 | 多样本、多条件的统计建模 |
| CellPhoneDB v5 | Python | 哪些配受体对在特定群对中特异,考虑多亚基复合物 | 人类数据;需要与 Vento-Tormo 实验室的图谱和空间微环境方法对接 | 小鼠数据(需同源转换) |
| NicheNet / MultiNicheNet | R | 哪个配体能解释接收细胞中的下游基因变化 | 已有处理组与对照组的差异基因,想找上游配体;MultiNicheNet 支持多样本多条件 | 没有对照组时的探索性描述 |
| LIANA+ | Python(另有 R 版 liana) | 多种方法与数据库的共识排名;多样本可接 Tensor-cell2cell、MOFA | Scanpy 用户;想同时得到 CellChat、CellPhoneDB 等方法的打分 | 只需要 CellChat 风格图表时 |
- CellChat 的结果来自 mRNA 表达和先验数据库,表示“表达上具备通讯条件”,不能证明蛋白层面的相互作用发生。
- 单细胞数据丢失了空间位置。两个群表达配体与受体,并不意味着它们在组织中相邻;空间数据或原位实验可以补上这一环。
- 数据库之外的配受体对不会出现在结果中,CellChatDB 偏向文献中研究较多的信号。
- 强度数值依赖参数与归一化,只在同一参数下比较。论文中应写清数据库子集、type、trim、population.size、min.cells 和版本。
- CellChat 的跨条件分析以两两比较为主,多条件、时间序列的变化分析需要自己组织(Nature Protocols 列出的局限)。
- 后续验证常用配体或受体的 RNAscope、免疫荧光共定位、受体阻断或中和抗体实验。
本页实测
本页实测:macOS arm64(Apple M2,8 核,16 GB),R 4.5.3、Seurat 5.5.1、CellChat 2.2.0.9001、presto 1.1.0、NMF 0.28、ComplexHeatmap 2.26.1、future 1.76.0。测试时同一台机器还在运行其他任务,耗时只用来看量级。
| 项目 | PBMC 3k | Kang 2018 两组 |
|---|---|---|
| 细胞与分群 | 2,638 个细胞,9 群 | CTRL 6,548 / STIM 7,451 个细胞,13 类 |
| 默认流程(Secreted、triMean) | 152 条通讯、6 条通路;computeCommunProb 9.6 秒;峰值内存 1.28 GB | CTRL 158 条 / STIM 254 条 |
| truncatedMean 0.1 | 241 条、13 条通路 | CTRL 421 条 / STIM 542 条;每组 26–43 秒 |
| 本页代码块全流程 | 去掉 Non-protein + trim 0.1:967 条、34 条通路;含作图 56 秒,1.49 GB | 两组比较 73 秒,3.30 GB |
| selectK | 默认 78 秒;k = 2:6、nrun = 5 为 34 秒 | 未运行 |
- 本页复现的报错:标签含 0、标签含 NA、未使用因子水平、拆分 layer、两组因子水平相同时缺类型、未 lift 合并后作图。
- 静默错误:counts 输入、scale.data 作为矩阵输入、LayerData 在拆分 layer 上只返回第一层,三者都不报错。
- 空间转录组(datatype = "spatial"、SpatialCellChat)、smoothData、CellPhoneDB、NicheNet、LIANA+ 未在本机运行,只核对了文档中的函数与参数名。
国内经验
以下来自腾讯云开发者社区转载的公众号文章,只收录带报错原文或作者实测、且与官方文档或本页实测一致的内容。
聚类号 0 不能做标签
生信补给站(2023 年 11 月)在 Visium 数据上把 0–9 号聚类改为 C0–C9 后才跑通。本页复现的报错原文是 Cell labels cannot contain `0`!,维护者在 GitHub #16 的回复中也提到标签不能是 "0"。
“未使用的因子”实际是 NA
天意生信云(2025 年 3 月)遇到 factor levels 报错,检查发现每个水平都有细胞,真正原因是注释列里有 NA,删除这些细胞后解决。本页实测 NA 与未使用水平报同一条错误,排查时两种情况都要看:sum(is.na(meta$labels)) 和 setdiff(levels(meta$labels), unique(meta$labels))。
Apple 芯片 Mac 的编译报错
R小白(2023 年 5 月)在 M 芯片 Mac 上安装时遇到 no member named 'Rlog1p' in namespace 'std',设置 export PKG_CPPFLAGS="-DHAVE_WORKING_LOG1P" 后通过;CMake was not found on the PATH 用 conda install cmake 解决。本页用 conda 编译器与 R 4.5.3 安装时没有遇到,旧版 R 环境仍可参考。
快速检查用 nboot = 20
生信技能树(2025 年 6 月)的空转教程在调参阶段设 nboot = 20。本页实测 nboot = 20 与 100 的显著通讯重合 96%(930 / 967 条),耗时约为五分之一,适合先确定数据库和 trim,最终结果再用 100。
“v3”是独立的空转包
KS科研(2026 年 5 月)指出 SpatialCellChat 是从 CellChat 拆出的空间转录组包,安装依赖 MERINGUE、ALRA、BiocNeighbors、RcppML,与官方 README 一致;单细胞数据继续用 CellChat v2。
两处需要更新的旧写法
多篇中文教程仍写 computeCommunProb(trim = 0.1) 而不改 type,以及 Windows 用 plan("multiprocess")。前者 trim 不生效;后者在当前 future 中报 No such backend for futures: 'multiprocess',改用 plan("multisession") 或直接顺序运行。
交给 Agent
可以用一句话描述分析任务,由 Scientify 的科学智能体在云电脑中完成。
指令示例:“用 data/annotated.rds(Seurat v5,celltype 列为注释,condition 列为对照和处理,sample 列为 6 个样本)做 CellChat v2 分析:两组分别运行,数据库去掉 Non-protein Signaling,type 分别用 triMean 和 truncatedMean 0.1 并比较结果,filterCommunication 设 min.samples = 2;合并后输出两组的通讯数量与强度对比、增强和减弱的通路、巨噬细胞发出的上调配受体对气泡图,并整理成表。”
智能体在云电脑中安装 CellChat 及依赖,记录版本;检查 layer 是否拆分、标签是否有 NA 和未使用水平、两组细胞类型是否一致,必要时 liftCellChat;按两套参数运行并列出只在一种参数下出现的通讯;输出圆图、气泡图、信号角色图和差异表。智能体会对结果做对抗审阅,例如检查强度是否被 MIF 等少数通路主导、显著通讯是否只来自单个样本。工作区保留脚本、参数、日志和 rds 文件,可以复现;关闭本机后任务继续运行。
你仍需要自己核对:注释是否可靠,数据库子集是否与研究问题对应,候选配受体对在文献和组织背景中是否合理,以及哪些结论需要实验验证。
参考资料
- CellChat GitHub(jinworks)README 与安装说明 — 当前版本、依赖、v2 与 v3(SpatialCellChat)的关系
- CellChat NEWS — v2.0–v2.1.2 的改动:samples 列、min.samples、CellChatDB v2
- CellChat 单数据集教程(CellChat-vignette) — 四种输入方式、数据库组成、triMean 与 population.size 说明、作图函数
- CellChat 多数据集比较教程 — mergeCellChat、rankNet、DEG 映射与 thresh.fc = 0.05
- CellChat 细胞组成不同的数据集比较教程 — liftCellChat;组成差异大时不可用的分析
- CellChat 源码 R/modeling.R — triMean、truncatedMean、thresholdedMean 定义;filterCommunication 的 <= 判断
- Jin et al. 2024, Nature Protocols:CellChat for systematic analysis of cell–cell communication — CellChat v2 方法与流程
- Jin et al. 2021, Nature Communications:Inference and analysis of cell-cell communication using CellChat — 通讯概率模型、置换检验、网络分析
- SpatialCellChat(CellChat v3) — 单细胞分辨率空间转录组
- GitHub issue #357:multisession 运行更慢 — 经验帖:多位用户报告并行变慢及降级 future 的做法
- GitHub PR #438:computeCommunProb 置换循环并行化 — 2026-02 合入,40k 细胞 46 h 降到 5.2 h(PR 作者数据)
- GitHub issue #62:多样本的最佳做法 — 维护者建议合并运行;min.samples 的由来
- GitHub issue #185:projectData 改名 smoothData — 经验帖:需写 adj = PPI.human
- GitHub issue #202:no slot of name data.smooth — 经验帖:旧对象补空矩阵的做法
- GitHub issue #79、#16、#1:computeCommunProb 报错 — 负值输入、标签 NA 与 0、早期 v2 全库报错
- GitHub issue #167:如何加速 — 经验帖:9 万细胞、133 个群的运行时间与内存
- Dimitrov et al. 2022, Nature Communications:Comparison of methods and resources for cell-cell communication inference — 方法与数据库选择显著影响结果;LIANA
- Liu et al. 2022, Genome Biology:Evaluation of cell-cell interaction methods by integrating single-cell RNA sequencing data with spatial information — 16 种方法基准,建议至少两种方法交叉验证
- Kang et al. 2018, Nature Biotechnology(ifnb 数据集) — 本页两组比较使用的公开数据
- CellPhoneDB — 选择表
- MultiNicheNet — 多样本多条件的配体活性分析
- LIANA+ 文档 — 多方法共识与多样本分析
- 生信补给站:CellChat-V2 空间转录组细胞通讯分析(腾讯云,2023-11) — 经验帖:聚类号 0 改为 C0–C9
- 天意生信云:CellChat 因子水平报错(腾讯云,2025-03) — 经验帖:报错真实原因是注释列 NA
- R小白:CellChat 安装(腾讯云,2023-05) — 经验帖:Apple 芯片 Rlog1p 编译错误、CMake 缺失;适用于旧版 R 环境
- 生信技能树:CellChat v2 空间转录组分析(腾讯云,2025-06) — 经验帖:nboot = 20 快速检查、Visium 参数
- KS科研:CellChat V3 空转细胞通讯分析解读(腾讯云,2026-05) — 经验帖:SpatialCellChat 安装依赖与输入