从样本数据计算置信区间

Bma*_*122 90 python statistics numpy confidence-interval

假设正态分布,我有样本数据,我想计算置信区间.

我已经找到并安装了numpy和scipy软件包,并且已经很难恢复平均值和标准差(numpy.mean(数据),数据是列表).任何关于获得样本置信区间的建议都会非常感激.

小智 135

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
Run Code Online (Sandbox Code Playgroud)

你可以这样计算.

  • 小心使用`sp.stats.t._ppf`的"私人".如果没有进一步的解释,我对那里的情况不太满意.最好直接使用`sp.stats.t.ppf`,除非你确定你知道你在做什么.在快速检查[源代码](https://github.com/scipy/scipy/blob/v0.13.0/scipy/stats/distributions.py#L1474)时,使用`_ppf`跳过了相当多的代码.可能是良性的,但也可能是不安全的优化尝试? (30认同)

Ulr*_*ern 92

这里是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))
Run Code Online (Sandbox Code Playgroud)

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

import statsmodels.stats.api as sms

sms.DescrStatsW(a).tconfint_mean()
Run Code Online (Sandbox Code Playgroud)

两者的基本假设是样本(数组a)独立于具有未知标准偏差的正态分布(参见MathWorldWikipedia).

对于大样本大小n,样本均值是正态分布的,并且可以使用st.norm.interval()(如Jaime的评论中所建议的)计算其置信区间.但是上述解决方案对于小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)
Run Code Online (Sandbox Code Playgroud)

最后,使用的结果不正确st.norm.interval():

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

  • 不,`st.t.interval(0.95)` 对于 95% 置信区间是正确的,请参阅 [docs](http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.t .html) 用于 `scipy.stats.t`。不过,SciPy 将参数命名为“alpha”似乎不太理想。 (6认同)
  • 为什么使用“scale=st.sem(a)”而不是“scale=np.std(a)”?既然尺度是标准差? (2认同)

bog*_*ron 14

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

  • `scipy.stats.norm.interval(置信,loc = mean,scale = sigma)` (27认同)
  • 最初的提问者表示假定正态分布,但值得指出的是,对于小样本群体(N <100左右),最好在[学生t分布]中查找z(http:/ /en.wikipedia.org/wiki/Student%27s_t-distribution)而不是[正态分布](http://en.wikipedia.org/wiki/Standard_normal_table).shasan的答案已经做到了. (3认同)
  • @bogatron关于置信区间的建议演算,不是**平均值+/- z * sigma / sqrt(n)**,其中n是样本大小? (3认同)
  • @David,你是对的.我误解了"西格玛"的含义.我的答案中的`sigma`应该是样本均值的估计标准差,而不是分布的估计标准差.我已经更新了答案以澄清这一点.感谢您指出了这一点. (3认同)

Xav*_*hot 8

从开始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
Run Code Online (Sandbox Code Playgroud)

这个:

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

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

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


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