二维散点图中置信区间与置信椭圆的差异及合理呈现方式
我们需要在散点图中可视化多样本的两个参数,研究组通常会在x、y方向添加置信区间(比如生物学重复的汇总结果)。我尝试用R语言的stat_ellipse函数绘制置信椭圆,却发现就算经过严格的Bonferroni校正,椭圆范围仍远大于常规置信区间。是我对置信椭圆的含义有误解,还是常规置信区间计算有误?在二维可视化中添加置信区间的最合适方式是什么?
可复现示例
以iris数据集的Sepal.Length和Petal.Length参数为例,下方代码生成同时包含置信椭圆和基于t检验、Bonferroni校正的常规置信区间的图表。我原本预期椭圆会被置信区间包围,但实际情况并非如此。
n_comparisons = 6 # 2*3 comparisons # 生成Bonferroni校正的置信区间 # 使用t.test函数,设置conf.level为Bonferroni校正后的值,然后提取$conf.int中的置信区间 metrics = iris |> pivot_longer(Sepal.Length:Petal.Length) |> group_by(Species, name) |> summarise(mean = mean(value), upper_ci = t.test(value, conf.level = 1-(0.05/n_comparisons))$conf.int[2], lower_ci = t.test(value, conf.level = 1-(0.05/n_comparisons))$conf.int[1]) |> pivot_wider(values_from = mean:lower_ci) ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) + theme_classic() + geom_point() + stat_ellipse(level = 0.95, type = "t") + geom_errorbar(data = metrics, aes(x = mean_Sepal.Length, y = mean_Petal.Length, ymin = lower_ci_Petal.Length, ymax = upper_ci_Petal.Length), width = 0.2) + geom_errorbarh(data = metrics, aes(x = mean_Sepal.Length, y = mean_Petal.Length, xmin = lower_ci_Sepal.Length, xmax = upper_ci_Sepal.Length), height = 0.2)

问题解答
1. 核心误解:置信椭圆与单变量置信区间的本质差异
你看到的差异完全是正常现象,因为两者的统计含义完全不同:
- 单变量置信区间:你计算的是每个变量(x或y)单独的均值置信区间,Bonferroni校正只是调整了单变量检验的置信水平,控制多变量比较的整体Type I错误,但本质上还是对单个维度的估计范围。
- 置信椭圆:
stat_ellipse(type = "t", level = 0.95)绘制的是二维均值的联合置信区域——它描述的是“真实的二维均值落在这个椭圆内的概率为95%”,考虑了两个变量之间的相关性。这个区域的边界不是单变量区间的简单组合,因为相关性会让联合区域的范围在某些方向上超出单变量区间,某些方向上更窄。
比如当x和y高度正相关时,x高于均值时y也大概率高于均值,联合置信椭圆会沿着相关方向延伸,自然会超出x或y单独的置信区间范围。
2. 你的置信区间计算是否正确?
你的Bonferroni校正逻辑存在小偏差:你设置1-(0.05/n_comparisons)作为置信水平,其中n_comparisons=6对应“2个变量×3个物种”,但如果只是要展示每个物种两个变量的均值置信区间,Bonferroni校正的对比次数应该是每个物种内的2个变量,或是整体6个单变量区间——这个校正本身逻辑通顺,但要明确:校正后的单变量区间依然是单维度的,和二维椭圆没有直接的包含关系。
3. 二维可视化中添加置信区间的合适方式
根据你展示生物学重复汇总结果的需求,可选择以下几种方式:
方式一:保留单变量置信区间(误差棒)+ 补充置信椭圆
如果核心需求是展示每个变量的均值波动,误差棒(x/y方向的单变量置信区间)更直观,置信椭圆可作为补充,用于展示变量间的相关性和联合波动范围。无需追求椭圆被误差棒包围,因为两者统计含义完全不同。
方式二:正确使用二维均值的联合置信椭圆
如果想展示二维均值的联合置信区域,确保stat_ellipse参数正确:
type = "t":适用于小样本,基于t分布计算,和你用的t检验单变量区间逻辑匹配;level:若要做Bonferroni校正的联合置信区间,需调整联合检验的置信水平。比如针对k个变量,联合置信水平可设为1 - α/k,但二维联合区间的校正逻辑和单变量不同,更准确的是使用Hotelling's T²检验计算联合置信区域,而stat_ellipse(type="t")已经封装了这个逻辑。
方式三:使用标准差/标准误椭圆(而非置信椭圆)
如果想展示数据的分布范围(而非均值的置信区间),可将stat_ellipse的type设为"norm"(基于正态分布的标准差范围)或type="euclid"(欧式距离的椭圆),此时椭圆描述的是数据离散程度,和均值置信区间是不同统计量。
修正后的代码示例(可选)
如果想让联合置信椭圆和单变量置信区间的置信水平匹配,无需对单变量做Bonferroni校正(除非要同时做多个单变量假设检验),直接使用0.95的置信水平即可:
metrics = iris |> pivot_longer(Sepal.Length:Petal.Length) |> group_by(Species, name) |> summarise(mean = mean(value), upper_ci = t.test(value, conf.level = 0.95)$conf.int[2], lower_ci = t.test(value, conf.level = 0.95)$conf.int[1]) |> pivot_wider(values_from = mean:lower_ci) ggplot(iris, aes(x = Sepal.Length, y = Petal.Length, color = Species)) + theme_classic() + geom_point() + stat_ellipse(level = 0.95, type = "t") + geom_errorbar(data = metrics, aes(x = mean_Sepal.Length, y = mean_Petal.Length, ymin = lower_ci_Petal.Length, ymax = upper_ci_Petal.Length), width = 0.2) + geom_errorbarh(data = metrics, aes(x = mean_Sepal.Length, y = mean_Petal.Length, xmin = lower_ci_Sepal.Length, xmax = upper_ci_Sepal.Length), height = 0.2)
这样两者的置信水平均为95%,虽然椭圆还是不会被误差棒包围,但统计含义一致:误差棒是单变量均值的95%置信区间,椭圆是二维均值的95%联合置信区间。
内容的提问来源于stack exchange,提问作者Michiel Schreurs

