根据样本数据计算置信区间


109

我有一些样本数据,假设正态分布,我希望为它们计算一个置信区间。

我已经找到并安装了numpy和scipy软件包,并获得了numpy以返回均值和标准差(numpy.mean(data),其中data为列表)。任何关于获得样本置信区间的建议将不胜感激。


1
我认为您确定要确定样本均值还是总体均值的CI。这将确定您是否要使用正态分布或t分布来计算z得分。下面的最高答案是样本均值,因此使用分布。
杰克

Answers:


162
import numpy as np
import scipy.stats


def mean_confidence_interval(data, confidence=0.95):
    a = 1.0 * np.array(data)
    n = len(a)
    m, se = np.mean(a), scipy.stats.sem(a)
    h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)
    return m, m-h, m+h

你可以这样计算


1
不建议使用sp.stats.stderr。我替换了sp.stats.sem,效果很好!
Bmayer0122

1
导入scipy不一定会自动导入所有子包。最好scipy.stats显式导入子包。
维克拉姆

31
小心使用的“私有”用法sp.stats.t._ppf。如果没有进一步的解释,我对此不太满意。最好sp.stats.t.ppf直接使用,除非您确定自己知道自己在做什么。在快速检查代码时,使用会跳过很多代码_ppf。可能是良性的,但也可能是不安全的优化尝试?
2014年

我喜欢它,因为您可以将其添加*ss.t._ppf((1+conf)/2.,n-1) 到内置的pandas数据框.sem方法中,因此您不必担心apply
TNT 2016年

1
只是想澄清一下此计算是针对样本均值,因此使用分布。如果问题是计算总体均值,则应使用正态分布,并且对于相同的置信度,置信区间将更小。
杰克

133

这是shasan代码的简化版本,用于计算数组均值的95%置信区间a

import numpy as np, scipy.stats as st

st.t.interval(0.95, len(a)-1, loc=np.mean(a), scale=st.sem(a))

但是使用StatsModels tconfint_mean可以说是更好的选择:

import statsmodels.stats.api as sms

sms.DescrStatsW(a).tconfint_mean()

两者的基本假设是,样本(数组a)是独立于具有未知标准偏差的正态分布绘制的(请参阅MathWorldWikipedia)。

对于大样本量n,样本均值是正态分布的,并且可以使用st.norm.interval()(如Jaime的评论中所建议的)计算其置信区间。但是上述解决方案对于较小的n也是正确的,n st.norm.interval()给出的置信区间太窄(即“假置信度”)。有关更多详细信息,请参阅我对类似问题的回答(以及此处的Russ的评论之一)。

这是一个示例,其中正确的选项给出(基本上)相同的置信区间:

In [9]: a = range(10,14)

In [10]: mean_confidence_interval(a)
Out[10]: (11.5, 9.4457397432391215, 13.554260256760879)

In [11]: st.t.interval(0.95, len(a)-1, loc=np.mean(a), scale=st.sem(a))
Out[11]: (9.4457397432391215, 13.554260256760879)

In [12]: sms.DescrStatsW(a).tconfint_mean()
Out[12]: (9.4457397432391197, 13.55426025676088)

最后,使用st.norm.interval()以下错误结果:

In [13]: st.norm.interval(0.95, loc=np.mean(a), scale=st.sem(a))
Out[13]: (10.23484868811834, 12.76515131188166)

1
我相信您应该打电话st.t.interval(0.05)获得95%的置信区间。
Scimonster

5
不,st.t.interval(0.95)是正确的95%的置信区间,看文档scipy.stats.t。不过,SciPy命名该论点alpha似乎并不理想。
乌尔里希·斯特恩

如果我有两个数据数组,然后计算它们的均值之差。有什么办法可以使这个均值差达到95%CI?您能想到使用StatsModelsl提供的一种简单方法吗?
史蒂芬

事实证明,@ steven,我回答了一个问题。:)
Ulrich Stern

16

首先从查找表中查找所需的置信区间的z值。置信区间为,其中是您的样本均值的估计标准偏差,由给出,其中是从样本数据计算出的标准偏差,是样本量。mean +/- z*sigmasigmasigma = s / sqrt(n)sn


29
scipy.stats.norm.interval(confidence, loc=mean, scale=sigma)
Jaime

4
最初的问询者表示应该假定为正态分布,但是值得指出的是,对于小样本种群(N <100左右),最好在Student t分布中查找z 而不是在正态分布中查找。shasan的答案已经做到了。
2014年

3
@bogatron关于置信区间的建议演算,不是平均值+/- z * sigma / sqrt(n),其中n是样本大小?
大卫

3
@大卫,你是对的。我错了的意思sigmasigma我的回答应该是样本均值的估计标准偏差,而不是分布的估计标准偏差。我已经更新了答案以澄清这一点。感谢您指出了这一点。
bogatron 2015年

15

从开始Python 3.8,标准库将NormalDist对象作为statistics模块的一部分提供:

from statistics import NormalDist

def confidence_interval(data, confidence=0.95):
  dist = NormalDist.from_samples(data)
  z = NormalDist().inv_cdf((1 + confidence) / 2.)
  h = dist.stdev * z / ((len(data) - 1) ** .5)
  return dist.mean - h, dist.mean + h

这个:

  • NormalDist从数据样本创建一个对象(NormalDist.from_samples(data),使我们可以通过NormalDist.mean和访问样本的均值和标准差NormalDist.stdev

  • 使用累积分布函数()的反函数,针对给定的置信度,Z-score基于标准正态分布(用表示)计算。NormalDist()inv_cdf

  • 根据样本的标准偏差和平均值产生置信区间。


假设样本量足够大(可以超过100个点),以便使用标准正态分布而不是学生的t分布来计算z值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.