单细胞分析

Seurat 气泡图怎么读?用四个细胞看懂点的大小和颜色

作者:发布于 2026-11-14约 8 分钟阅读
教学示例。甲组四个细胞为 4、4、0、0,乙组为 8、0、0、0。检出比例分别为 50% 和 25%,全群平均均为 2。

给两个细胞群画同一个标记基因,眼前是两个几乎同色的点,一大一小。写图注时该用“表达更高”,还是“表达的细胞更多”?如果两群纳入的细胞数本来就不同,连“更多”也要换成“比例更高”。先把每个点后面有哪些细胞、分母取谁写出来,组会上的争论就可以直接算一遍。

下面固定一个常见的作图条件。使用 Seurat 的 RNA assay,表达层已经做过 LogNormalize,按细胞群分组。整理过的对象可能默认指向别的 assay,先写明所用数据,才容易和同事复现同一张图。

从四个细胞算出一个点

假设甲、乙两群各有四个细胞。下表是同一基因在每个细胞里的线性归一化表达量,即按每个细胞的测序量归一化后、取对数前的值。数字专为演示选取,拿自己的原始 UMI 矩阵时要先做相应的归一化。

细胞群 四个细胞的表达量 检出比例 全群平均
甲 4、4、0、0 2/4 = 50% (4 + 4) / 4 = 2
乙 8、0、0、0 1/4 = 25% 8 / 4 = 2

甲群有一半细胞检出,乙群只有四分之一,所以甲的点应当更大。两群的总表达量都是八,除以各自的四个细胞,平均都是二。若只对检出细胞取平均,甲会得到四、乙会得到八,那是另一个问题。用这两个数字来解释气泡颜色,就把分母换掉了。

这里还有一个细节。两群的平均数完全相同,只画这两群、这一个基因时,默认的按基因标准化会遇到零方差。把 scale = FALSE 用于这个小例子,两群的颜色输入都是 log1p(2),约为 1.099。要复算检出率与平均数,可以直接运行下面的基础 R 代码。

x <- list(A = c(4, 4, 0, 0), B = c(8, 0, 0, 0))
sapply(x, function(v) c(
  pct = 100 * mean(v > 0),
  avg = mean(v),
  colour_unscaled = log1p(mean(v))
))
教学示例。甲组四个细胞为 4、4、0、0,乙组为 8、0、0、0。检出比例分别为 50% 和 25%,全群平均均为 2。
四个细胞的教学例子。分母始终取各组全部细胞,可以把检出比例和平均表达分别算清。

默认颜色为什么会随分组改变

在上述条件下,Seurat 先把每个细胞的对数归一化表达还原到线性尺度,对组内所有细胞求平均,再对各组均值取 log1p。默认开启的 scale = TRUE 还会对同一个基因在各组的这些值做中心化和标准化。最后,色阶上下限还可能把极端值截到同一种颜色。要知道某个深色点代表什么,得同时知道图里放了哪些群。DotPlot 参数说明 · Seurat v5.3.0 的计算实现

举个常见的实际操作。你先在全图谱里画一个淋巴细胞标记,再只选几个淋巴亚群重画。即便保留下来的细胞一个也没变,用来计算该基因相对高低的组已经换了,同一群的颜色就可能改变。做两项目对照时,最好把要比较的组放进同一对象、一次作图,并确认两边使用同样的表达处理。若确实要拆成两张图,除关闭按基因缩放外,还要给两张图设置相同的颜色范围。各自自动选择的色阶仍会让同一个值看上去不一样。

同样的道理也适用于一张图里的两个基因。甲基因的一枚深色点和乙基因的一枚浅色点,各自都有一组用来标准化的均值。若要比较两个基因的数值,应查看原始统计表,并交代表达单位与归一化方法。光凭颜色,最多能描述某个标记在所画各群中的相对分布。LogNormalize 的定义

从自己的图里取回那两个数

假定你的对象叫 obj,元数据里有已经检查过的 celltype 列。下面以人类免疫细胞常见的两个标记为例。其他物种或使用 Ensembl ID 的对象,请把基因名换成表达矩阵实际使用的标识。先用 table(obj$celltype) 看看每个点背后有多少细胞,再画图、取数。

library(Seurat)
table(obj$celltype)
p <- DotPlot(obj, features = c("CD3D", "MS4A1"),
             assay = "RNA", group.by = "celltype",
             scale = FALSE, dot.min = 0)
p
p$data[, c("id", "features.plot", "pct.exp", "avg.exp")]

在这份输出里,pct.exp 按百分数给出,例如 25 就是百分之二十五。avg.exp 是线性尺度的组内均值,包含零值。回到图上时,点的大小请对应图例读数。默认设置还涉及按半径映射,肉眼估计圆面积很容易高估比例差异。若别人发来的图上某处完全留白,先问是否设置了 dot.min。低于显示阈值的点会被隐藏,即使原本确实有少量细胞检出。

实跑经验|打开真实图对象,检查绘图用的三列数

我们用 R 4.3.3 实际安装并运行 Seurat 5.0.1。先建八列计数,每列补足至一万个分子,让 LogNormalize 的线性归一化值与上面的手算完全一致。用同一个 DotPlot 对象取数,甲、乙的检出比例依次是 50 和 25,线性均值都是 2,关闭按基因缩放后的颜色值也同为 1.098612。读图时如果只保存百分比和颜色截图,后来将看不出这个相同的颜色究竟对应哪个线性均值。把图对象里的三列连同分组名一并导出,就能逐项复核。

又在软件包附带的真实 PBMC 小数据上重新归一化并调用同一函数。该对象有 230 个特征、80 枚细胞,三个原始群分别有 36、25、19 枚。MS4A1 的检出率依次为 0%、8.0%、52.63%,对应没有细胞、两枚细胞和十枚细胞检出。第二群的点虽小,八个百分点确实来自两枚,而第三群只要少一枚阳性,比例就会从十除以十九降到九除以十九。实际最容易遗漏的是小群的分母。先拿百分比乘回每组细胞数,确认能还原整数,再去讨论稀有表达和正式样本中的重复性。SeuratObject 的演示数据说明

科室里两位供体,合并后要不要给他们同样的权重

设想同一类细胞里,甲供体测到了九十个,其中四十五个检出某个基因。乙供体测到十个,其中九个检出。若合并细胞画一个点,总检出率是五十四除以一百,即百分之五十四。若先给每位供体算检出率,再给两人相同权重,结果是百分之五十与百分之九十的平均,即百分之七十。两个答案各有明确的研究对象。前者描述本次收集到的细胞,后者描述两位供体各自比例的平均。画图时如果细胞较多的样本刚好来自某一种处理条件,合并的气泡就更容易反映那个样本。

要查自己的对象,把供体和细胞类型合成一个分组列,用上面的代码重新作图,同时保留各组细胞总数。十个细胞那一组少一个检出,比例会下降十个百分点。把这个分母写在图旁,读者就能判断一个显眼的小组到底有多少观测支撑。仅凭这两位供体,不能把示例中的比例差直接外推到人群。

哪些点值得回到细胞层面看

碰到小而深的点,我会先看这一群到底有几个人的样本,再画该基因的小提琴图或带散点的分布图。四个细胞里有一个检出,和四百个细胞里有一百个检出,图上都能写百分之二十五,解释的把握却很不一样。如果强信号全来自一个供体,还应检查这个供体在该群的细胞数、测序深度,以及那几个细胞是否同时表达互不相容的谱系标记。单凭这个点把整个群改名,会让一个少数现象支配注释。

另一个容易误读的地方是零值。这里的“检出”指这份数据里归一化表达大于零。一次测序没有捕获到分子,并不能证明细胞在生物学上完全不表达。实际写图注时,把对象、分组、检出比例和均值分别说清就够了。例如这个教学例子可以写成“甲群检出该基因的细胞更多,两群的全群平均表达相同”。若问题进一步变成处理组与对照组之间是否有差异,就需要回到独立生物学样本和相应统计设计。

如果接下来要把多个供体的原始计数合并、让组内同事复用同一份 Seurat 对象,可以把整理好的脚本和 R 包版本一起保留下来。课题组需要共享环境时,可了解云生信的生物信息分析服务器。

把知识用于当前任务

把方法直接跑起来

使用单细胞在线分析入口,减少环境配置和重复操作。

打开单细胞工具仍有疑问,联系客服 ↗