Seaborn置信区间计算是否正确?

23

首先,我必须承认我的统计学知识非常生疏:即便在刚开始学习时,我也并不是特别喜欢这门学科,这意味着我很难理解它。

尽管如此,我仍然查看了 barplot 图中误差线的计算方式,惊讶地发现使用了“置信区间”(CI)来取代更为普遍的标准偏差。进一步调查 CI ,我找到了这篇 维基百科文章 ,该文章似乎表明,CI 的计算方式如下:

mean minus 1.96 times stdev over sqrt(n)

mean plus 1.96 times stdev over sqrt(n)

或者,用伪代码表示:

def ci_wp(a):
    """calculate confidence interval using Wikipedia's formula"""
    m = np.mean(a)
    s = 1.96*np.std(a)/np.sqrt(len(a))
    return m - s, m + s

但是我们在seaborn/utils.py中发现的是:

def ci(a, which=95, axis=None):
    """Return a percentile range from an array of values."""
    p = 50 - which / 2, 50 + which / 2
    return percentiles(a, p, axis)

现在也许我完全错了,但这似乎是一个与维基百科提出的完全不同的计算。有人能解释一下这个差异吗?

再举个例子,从评论中可以看出,为什么我们在以下两种情况下得到的结果如此不同:

 >>> sb.utils.ci(np.arange(100))
 array([ 2.475, 96.525])

 >>> ci_wp(np.arange(100))
 [43.842250270646467,55.157749729353533]

与其他统计工具进行比较:

 def ci_std(a):
     """calculate margin of error using standard deviation"""
     m = np.mean(a)
     s = np.std(a)
     return m-s, m+s

 def ci_sem(a):
     """calculate margin of error using standard error of the mean"""
     m = np.mean(a)
     s = sp.stats.sem(a)
     return m-s, m+s

这给我们带来了:

>>> ci_sem(np.arange(100))
(46.598850802411796, 52.401149197588204)

>>> ci_std(np.arange(100))
(20.633929952277882, 78.366070047722118)

或者使用随机样本:

rng = np.random.RandomState(10)
a = rng.normal(size=100)
print sb.utils.ci(a)
print ci_wp(a)
print ci_sem(a)
print ci_std(a)

... 得到的结果为:

[-1.9667006   2.19502303]
(-0.1101230745774124, 0.26895640045116026)
(-0.017774461397903049, 0.17660778727165088)
(-0.88762281417683186, 1.0464561400505796)

为什么 Seaborn 的结果与其他结果差异如此之大?

我确认:sb.ci(np.arange(100)) 的结果是 array([ 2.475, 96.525]),而直接计算 np.mean(np.arange(100))-np.arange(100).std()*1.96/10 的结果是 [43.842250270646467,55.157749729353533] - DYZ
谢谢!那听起来大致正确,尽管我必须说:在这里,seaborn的结果似乎更有意义...作为比较,使用简单的 mean +/- std 得到的结果是:(20.633929952277882, 78.366070047722118) - anarcat
2个回答

29
你使用维基百科的公式进行的计算是完全正确的。Seaborn只是使用了另一种方法: https://en.wikipedia.org/wiki/Bootstrapping_(statistics)。Dragicevic [1]对此进行了很好的描述:

它由通过随机抽取观测值并进行替换来从实验数据中生成许多替代数据集组成。这些数据集之间的变化被认为近似于抽样误差,并用于计算所谓的自助法置信区间。[...]它非常灵活,适用于许多种分布。

在Seaborn的源代码中,barplot使用estimate_statistic对数据进行自助法 然后 计算置信区间:

>>> sb.utils.ci(sb.algorithms.bootstrap(np.arange(100)))
array([43.91, 55.21025])

这个结果与你的计算一致。

[1] Dragicevic, P. (2016). 公平的统计信息传达在人机交互中。在现代人机交互的统计方法(第291-330页)。Springer,Cham。


0
你需要检查百分位数的代码。你发布的seaborn ci代码只是计算百分位数限制。该区间具有50(中位数)的定义平均值和默认范围为95%置信区间。实际平均值、标准差等将出现在百分位数例程中。

1
percentiles 最终调用 scipy.stats.scoreatpercentile - 这仍然与维基百科的计算方法不同... - anarcat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接