statistics — 数学统计函数 — Python 文档
statistics — 数理统计函数
3.4 版中的新功能。
源代码: :source:`Lib/statistics.py`
该模块提供用于计算数值(Real 值)数据的数理统计的函数。
该模块无意成为第三方库(如 NumPy、SciPy)或面向专业统计学家(如 Minitab、SAS 和 Matlab)的专有全功能统计软件包的竞争对手. 它针对图形和科学计算器的级别。
除非明确说明,否则这些函数支持 int、float、Decimal 和 Fraction。 当前不支持其他类型的行为(无论是否在数字塔中)。 混合类型的集合也是未定义的并且依赖于实现。 如果您的输入数据由混合类型组成,您可以使用 map() 来确保一致的结果,例如:map(float, input_data)
。
中心位置的平均值和度量
这些函数计算总体或样本的平均值或典型值。
mean()
|
数据的算术平均值(“平均值”)。 |
fmean()
|
快速,浮点算术平均值。 |
geometric_mean()
|
数据的几何平均值。 |
harmonic_mean()
|
数据的调和平均值。 |
median()
|
数据的中位数(中间值)。 |
median_low()
|
数据中位数较低。 |
median_high()
|
数据中位数高。 |
median_grouped()
|
分组数据的中位数或第 50 个百分位数。 |
mode()
|
离散或标称数据的单一模式(最常见的值)。 |
multimode()
|
离散或标称数据的模式(最常见的值)列表。 |
quantiles()
|
将数据划分为具有相等概率的区间。 |
传播措施
这些函数计算总体或样本倾向于偏离典型值或平均值的程度。
pstdev()
|
数据的总体标准偏差。 |
pvariance()
|
数据的总体方差。 |
stdev()
|
数据的样本标准差。 |
variance()
|
数据的样本方差。 |
功能详情
注意:这些函数不需要对提供给它们的数据进行排序。 但是,为了阅读方便,大多数示例都显示了排序序列。
- statistics.mean(data)
返回 data 的样本算术平均值,可以是序列或可迭代的。
算术平均值是数据的总和除以数据点的数量。 它通常被称为“平均值”,尽管它只是许多不同的数学平均值之一。 它是对数据中心位置的度量。
如果 data 为空,则会引发 StatisticsError。
一些使用示例:
>>> mean([1, 2, 3, 4, 4]) 2.8 >>> mean([-1.0, 2.5, 3.25, 5.75]) 2.625 >>> from fractions import Fraction as F >>> mean([F(3, 7), F(1, 21), F(5, 3), F(1, 3)]) Fraction(13, 21) >>> from decimal import Decimal as D >>> mean([D("0.5"), D("0.75"), D("0.625"), D("0.375")]) Decimal('0.5625')
- statistics.fmean(data)
将 data 转换为浮点数并计算算术平均值。
这比 mean() 函数运行得更快,并且它总是返回一个 float。 data 可以是序列或可迭代的。 如果输入数据集为空,则引发 StatisticsError。
>>> fmean([3.5, 4.0, 5.25]) 4.25
3.8 版中的新功能。
- statistics.geometric_mean(data)
将 data 转换为浮点数并计算几何平均值。
几何平均值表示 数据 使用值的乘积(与使用它们的总和的算术平均值相反)的集中趋势或典型值。
如果输入数据集为空、包含零或包含负值,则引发 StatisticsError。 data 可以是序列或可迭代的。
没有特别的努力来获得准确的结果。 (但是,这在未来可能会改变。)
>>> round(geometric_mean([54, 24, 36]), 1) 36.0
3.8 版中的新功能。
- statistics.harmonic_mean(data)
返回 data 的调和平均值,实值数的序列或可迭代对象。
调和平均数,有时称为逆向平均数,是数据倒数的算术 mean() 的倒数。 例如,三个值 a、b 和 c 的调和平均值将等价于
3/(1/a + 1/b + 1/c)
。 如果其中一个值为零,则结果为零。调和平均值是一种平均值,是数据中心位置的度量。 在平均速率或比率时通常是合适的,例如速度。
假设一辆汽车以 40 公里/小时的速度行驶了 10 公里,然后又以 60 公里/小时的速度行驶了 10 公里。 平均速度是多少?
>>> harmonic_mean([40, 60]) 48.0
假设投资者购买三家公司中每家公司的等值股份,市盈率(市盈率)分别为 2.5、3 和 10。 投资者投资组合的平均市盈率是多少?
>>> harmonic_mean([2.5, 3, 10]) # For an equal investment portfolio. 3.6
StatisticsError 如果 data 为空,或者任何元素小于零,则会引发 StatisticsError。
当前算法在输入中遇到零时会提前退出。 这意味着不测试后续输入的有效性。 (这种行为将来可能会改变。)
3.6 版中的新功能。
- statistics.median(data)
使用常见的“中间两个平均值”方法返回数值数据的中值(中间值)。 如果 data 为空,则引发 StatisticsError。 data 可以是一个序列或可迭代的。
中位数是对中心位置的可靠度量,受异常值的影响较小。 当数据点数为奇数时,返回中间数据点:
>>> median([1, 3, 5]) 3
当数据点数为偶数时,通过取两个中间值的平均值来插值中位数:
>>> median([1, 3, 5, 7]) 4.0
这适用于您的数据是离散的,并且您不介意中位数可能不是实际数据点的情况。
如果数据是序数(支持顺序操作)但不是数字(不支持加法),请考虑使用 median_low() 或 median_high() 代替。
- statistics.median_low(data)
返回数值数据的低中位数。 如果 data 为空,则引发 StatisticsError。 data 可以是一个序列或可迭代的。
低中位数始终是数据集的成员。 当数据点数为奇数时,返回中间值。 当它是偶数时,返回两个中间值中较小的一个。
>>> median_low([1, 3, 5]) 3 >>> median_low([1, 3, 5, 7]) 3
当您的数据是离散的并且您希望中位数是实际数据点而不是插值时,请使用低中位数。
- statistics.median_high(data)
返回数据的高中位数。 如果 data 为空,则引发 StatisticsError。 data 可以是一个序列或可迭代的。
高中位数始终是数据集的成员。 当数据点数为奇数时,返回中间值。 当它是偶数时,返回两个中间值中较大的一个。
>>> median_high([1, 3, 5]) 3 >>> median_high([1, 3, 5, 7]) 5
当您的数据是离散的并且您希望中位数是实际数据点而不是插值时,请使用高中位数。
- statistics.median_grouped(data, interval=1)
使用插值返回分组连续数据的中位数,计算为第 50 个百分位数。 如果 data 为空,则引发 StatisticsError。 data 可以是一个序列或可迭代的。
>>> median_grouped([52, 52, 53, 54]) 52.5
在下面的例子中,数据被四舍五入,所以每个值代表数据类的中点,例如 1 是类 0.5-1.5 的中点,2 是 1.5-2.5 的中点,3 是 2.5-3.5 的中点,以此类推。 根据给定的数据,中间值属于 3.5-4.5 类,并使用插值来估计它:
>>> median_grouped([1, 2, 2, 3, 4, 4, 4, 4, 4, 5]) 3.7
可选参数 interval 表示类间隔,默认为 1。 自然地改变类间隔会改变插值:
>>> median_grouped([1, 3, 3, 5, 7], interval=1) 3.25 >>> median_grouped([1, 3, 3, 5, 7], interval=2) 3.5
此函数不检查数据点是否至少间隔 间隔 。
- statistics.mode(data)
从离散或标称 数据 返回单个最常见的数据点。 众数(当它存在时)是最典型的值,用作中心位置的度量。
如果有多个相同频率的模式,则返回data中遇到的第一个。 如果需要其中的最小或最大,请使用
min(multimode(data))
或max(multimode(data))
。 如果输入 data 为空,则会引发 StatisticsError。mode
假设离散数据并返回单个值。 这是学校通常教授的模式的标准处理方式:>>> mode([1, 1, 2, 3, 3, 3, 3, 4]) 3
该模式的独特之处在于它是此包中唯一也适用于名义(非数字)数据的统计数据:
>>> mode(["red", "blue", "blue", "red", "green", "red", "red"]) 'red'
3.8 版更改: 现在通过返回遇到的第一个模式来处理多模式数据集。 以前,当发现不止一种模式时,它会引发 StatisticsError。
- statistics.multimode(data)
按照它们在 data 中首次遇到的顺序返回最常出现的值的列表。 如果有多种模式,将返回多个结果,如果 data 为空,则返回一个空列表:
>>> multimode('aabbbbccddddeeffffgg') ['b', 'd', 'f'] >>> multimode('') []
3.8 版中的新功能。
- statistics.pstdev(data, mu=None)
返回总体标准差(总体方差的平方根)。 有关参数和其他详细信息,请参阅 pvariance()。
>>> pstdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75]) 0.986893273527251
- statistics.pvariance(data, mu=None)
返回 data 的总体方差,一个非空序列或可迭代的实数值。 方差,或关于均值的二阶矩,是对数据可变性(传播或分散)的度量。 大的方差表明数据是分散的; 小的方差表明它紧密地聚集在均值附近。
如果给出了可选的第二个参数 mu,它通常是 data 的平均值。 它还可用于计算非均值点周围的二阶矩。 如果缺少或
None
(默认值),则自动计算算术平均值。使用此函数计算整个总体的方差。 要估计样本的方差,variance() 函数通常是更好的选择。
如果 data 为空,则引发 StatisticsError。
例子:
>>> data = [0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25] >>> pvariance(data) 1.25
如果您已经计算了数据的平均值,则可以将其作为可选的第二个参数 mu 传递以避免重新计算:
>>> mu = mean(data) >>> pvariance(data, mu) 1.25
支持小数和分数:
>>> from decimal import Decimal as D >>> pvariance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")]) Decimal('24.815') >>> from fractions import Fraction as F >>> pvariance([F(1, 4), F(5, 4), F(1, 2)]) Fraction(13, 72)
笔记
当用整个总体调用时,这给出了总体方差 σ²。 当改为调用样本时,这是有偏样本方差 s²,也称为具有 N 自由度的方差。
如果您以某种方式知道真实的总体均值 μ,则可以使用此函数来计算样本的方差,将已知总体均值作为第二个参数。 如果数据点是总体的随机样本,则结果将是总体方差的无偏估计。
- statistics.stdev(data, xbar=None)
返回样本标准差(样本方差的平方根)。 有关参数和其他详细信息,请参阅 variance()。
>>> stdev([1.5, 2.5, 2.5, 2.75, 3.25, 4.75]) 1.0810874155219827
- statistics.variance(data, xbar=None)
返回 data 的样本方差,它是至少两个实数值的迭代。 方差,或关于均值的二阶矩,是对数据可变性(传播或分散)的度量。 大的方差表明数据是分散的; 小的方差表明它紧密地聚集在均值附近。
如果给出了可选的第二个参数 xbar,它应该是 data 的平均值。 如果缺失或
None
(默认值),则会自动计算平均值。当您的数据是来自总体的样本时,请使用此函数。 要计算整个总体的方差,请参阅 pvariance()。
如果 data 的值少于两个,则引发 StatisticsError。
例子:
>>> data = [2.75, 1.75, 1.25, 0.25, 0.5, 1.25, 3.5] >>> variance(data) 1.3720238095238095
如果您已经计算了数据的平均值,则可以将其作为可选的第二个参数 xbar 传递以避免重新计算:
>>> m = mean(data) >>> variance(data, m) 1.3720238095238095
此函数不会尝试验证您是否已通过 xbar 的实际平均值。 对 xbar 使用任意值会导致无效或不可能的结果。
支持小数和小数值:
>>> from decimal import Decimal as D >>> variance([D("27.5"), D("30.25"), D("30.25"), D("34.5"), D("41.75")]) Decimal('31.01875') >>> from fractions import Fraction as F >>> variance([F(1, 6), F(1, 2), F(5, 3)]) Fraction(67, 108)
笔记
这是具有贝塞尔校正的样本方差 s²,也称为具有 N-1 自由度的方差。 前提是数据点具有代表性(例如 独立同分布),结果应该是真实总体方差的无偏估计。
如果您以某种方式知道实际总体均值 μ,您应该将其作为 mu 参数传递给 pvariance() 函数以获得样本的方差。
- statistics.quantiles(data, *, n=4, method='exclusive')
将 data 分成 n 个等概率连续区间。 返回分隔间隔的
n - 1
切割点列表。将四分位数的 n 设置为 4(默认值)。 对于十分位数,将 n 设置为 10。 对于百分位数,将 n 设置为 100,这将提供 99 个切割点,将 data 分成 100 个相同大小的组。 如果 n 不小于 1,则引发 StatisticsError。
data 可以是包含样本数据的任何可迭代对象。 对于有意义的结果,data 中的数据点数应大于 n。 如果没有至少两个数据点,则引发 StatisticsError。
切割点从两个最近的数据点线性插值。 例如,如果切割点落在两个样本值
100
和112
之间距离的三分之一处,则该切割点的计算结果为104
。用于计算分位数的 方法 可以根据 数据 是否包含或排除总体中的最低和最高可能值而有所不同。
默认的 方法 是“独占的”,用于从可能具有比样本中发现的更多的极端值的总体中采样的数据。 低于 m 排序数据点的 i-th 的总体部分计算为
i / (m + 1)
。 给定九个样本值,该方法对它们进行排序并分配以下百分位数:10%、20%、30%、40%、50%、60%、70%、80%、90%。将 方法 设置为“包含”用于描述总体数据或用于已知包含总体中最极端值的样本。 data 中的最小值被视为第 0 个百分位数,最大值被视为第 100 个百分位数。 低于 m 排序数据点的 i-th 的总体部分计算为
(i - 1) / (m - 1)
。 给定 11 个样本值,该方法对它们进行排序并分配以下百分位数:0%、10%、20%、30%、40%、50%、60%、70%、80%、90%、100%。# Decile cut points for empirically sampled data >>> data = [105, 129, 87, 86, 111, 111, 89, 81, 108, 92, 110, ... 100, 75, 105, 103, 109, 76, 119, 99, 91, 103, 129, ... 106, 101, 84, 111, 74, 87, 86, 103, 103, 106, 86, ... 111, 75, 87, 102, 121, 111, 88, 89, 101, 106, 95, ... 103, 107, 101, 81, 109, 104] >>> [round(q, 1) for q in quantiles(data, n=10)] [81.0, 86.2, 89.0, 99.4, 102.5, 103.6, 106.0, 109.8, 111.0]
3.8 版中的新功能。
NormalDist 对象
NormalDist 是用于创建和操作 随机变量 的正态分布的工具。 它是一个将数据测量的均值和标准差视为单个实体的类。
正态分布源自 中心极限定理 ,在统计学中有着广泛的应用。
- class statistics.NormalDist(mu=0.0, sigma=1.0)
返回一个新的 NormalDist 对象,其中 mu 表示 算术平均值 ,sigma 表示 标准偏差 。
如果 sigma 为负,则引发 StatisticsError。
- mean
正态分布的 算术平均值 的只读属性。
- median
正态分布的 中值 的只读属性。
- mode
正态分布的 mode 的只读属性。
- stdev
正态分布的 标准偏差 的只读属性。
- variance
正态分布的 方差 的只读属性。 等于标准差的平方。
- classmethod from_samples(data)
使用 fmean() 和 stdev()[ 从 data 估计的 mu 和 sigma 参数制作正态分布实例X155X]。
data 可以是任何 iterable 并且应该由可以转换为类型 float 的值组成。 如果 data 不包含至少两个元素,则引发 StatisticsError,因为它至少需要一个点来估计中心值,至少需要两个点来估计离散度。
- samples(n, *, seed=None)
为给定的均值和标准差生成 n 个随机样本。 返回 float 值的 list。
如果给出 seed,则创建底层随机数生成器的新实例。 这对于创建可重现的结果非常有用,即使在多线程上下文中也是如此。
- pdf(x)
使用 概率密度函数 (pdf),计算随机变量 X 将接近给定值 x 的相对可能性。 在数学上,当 dx 接近零时,它是比率
P(x <= X < x+dx) / dx
的极限。相对似然计算为样本出现在狭窄范围内的概率除以范围的宽度(因此称为“密度”)。 由于似然是相对于其他点,其值可以大于1.0。
- cdf(x)
使用 累积分布函数 (cdf),计算随机变量 X 小于或等于 x 的概率。 在数学上,它被写成
P(X <= x)
。
- inv_cdf(p)
计算逆累积分布函数,也称为 分位数函数 或 percent-point 函数。 在数学上,它被写成
x : P(X <= x) = p
。求随机变量 X 的值 x,使得变量小于或等于该值的概率等于给定的概率 p。
- overlap(other)
测量两个正态概率分布之间的一致性。 返回一个介于 0.0 和 1.0 之间的值,给出 两个概率密度函数 的重叠区域。
- quantiles(n=4)
以等概率将正态分布划分为 n 个连续区间。 返回分隔间隔的 (n - 1) 个切割点列表。
将四分位数的 n 设置为 4(默认值)。 对于十分位数,将 n 设置为 10。 对于百分位数,将 n 设置为 100,这给出了将正态分布分成 100 个大小相等的组的 99 个切割点。
NormalDist 的实例支持常量的加减乘除。 这些操作用于平移和缩放。 例如:
>>> temperature_february = NormalDist(5, 2.5) # Celsius >>> temperature_february * (9/5) + 32 # Fahrenheit NormalDist(mu=41.0, sigma=4.5)
不支持将常量除以 NormalDist 的实例,因为结果不会呈正态分布。
由于正态分布是由自变量的加法效应引起的,因此可以 加减两个独立的正态分布随机变量 ,表示为 NormalDist 的实例。 例如:
>>> birth_weights = NormalDist.from_samples([2.5, 3.1, 2.1, 2.4, 2.7, 3.5]) >>> drug_effects = NormalDist(0.4, 0.15) >>> combined = birth_weights + drug_effects >>> round(combined.mean, 1) 3.1 >>> round(combined.stdev, 1) 0.5
3.8 版中的新功能。
NormalDist 例子和食谱
NormalDist 很容易解决经典的概率问题。
例如,给定 SAT 考试的历史数据 显示分数呈正态分布,平均值为 1060,标准差为 195,在四舍五入到最接近的整数:
>>> sat = NormalDist(1060, 195)
>>> fraction = sat.cdf(1200 + 0.5) - sat.cdf(1100 - 0.5)
>>> round(fraction * 100.0, 1)
18.4
>>> list(map(round, sat.quantiles()))
[928, 1060, 1192]
>>> list(map(round, sat.quantiles(n=10)))
[810, 896, 958, 1011, 1060, 1109, 1162, 1224, 1310]
为了估计不容易解析求解的模型分布,NormalDist 可以为 蒙特卡罗模拟 生成输入样本:
>>> def model(x, y, z):
... return (3*x + 7*x*y - 5*y) / (11 * z)
...
>>> n = 100_000
>>> X = NormalDist(10, 2.5).samples(n, seed=3652260728)
>>> Y = NormalDist(15, 1.75).samples(n, seed=4582495471)
>>> Z = NormalDist(50, 1.25).samples(n, seed=6582483453)
>>> quantiles(map(model, X, Y, Z))
[1.4591308524824727, 1.8035946855390597, 2.175091447274739]
当样本量很大且试验成功的概率接近 50% 时,正态分布可用于近似 二项式分布 。
例如,一个开源会议有 750 名与会者和两个可容纳 500 人的房间。 有一个关于 Python 的讨论,另一个关于 Ruby 的讨论。 在之前的会议中,65% of 的与会者更喜欢听 Python 演讲。 假设人口偏好没有改变,Python 房间保持在其容量限制内的概率是多少?
>>> n = 750 # Sample size
>>> p = 0.65 # Preference for Python
>>> q = 1.0 - p # Preference for Ruby
>>> k = 500 # Room capacity
>>> # Approximation using the cumulative normal distribution
>>> from math import sqrt
>>> round(NormalDist(mu=n*p, sigma=sqrt(n*p*q)).cdf(k + 0.5), 4)
0.8402
>>> # Solution using the cumulative binomial distribution
>>> from math import comb, fsum
>>> round(fsum(comb(n, r) * p**r * q**(n-r) for r in range(k+1)), 4)
0.8402
>>> # Approximation using a simulation
>>> from random import seed, choices
>>> seed(8675309)
>>> def trial():
... return choices(('Python', 'Ruby'), (p, q), k=n).count('Python')
>>> mean(trial() <= k for i in range(10_000))
0.8398
正态分布通常出现在机器学习问题中。
维基百科有一个 朴素贝叶斯分类器 的好例子。 面临的挑战是通过测量正态分布特征(包括身高、体重和脚的大小)来预测一个人的性别。
我们得到了一个训练数据集,其中包含八个人的测量数据。 假设测量值是正态分布的,所以我们用 NormalDist 总结数据:
>>> height_male = NormalDist.from_samples([6, 5.92, 5.58, 5.92])
>>> height_female = NormalDist.from_samples([5, 5.5, 5.42, 5.75])
>>> weight_male = NormalDist.from_samples([180, 190, 170, 165])
>>> weight_female = NormalDist.from_samples([100, 150, 130, 150])
>>> foot_size_male = NormalDist.from_samples([12, 11, 12, 10])
>>> foot_size_female = NormalDist.from_samples([6, 8, 7, 9])
接下来,我们遇到一个新人,其特征测量值已知但性别未知:
>>> ht = 6.0 # height
>>> wt = 130 # weight
>>> fs = 8 # foot size
从男性或女性的 50% 先验概率 开始,我们将后验计算为给定性别的特征测量的似然乘积的先验乘积:
>>> prior_male = 0.5
>>> prior_female = 0.5
>>> posterior_male = (prior_male * height_male.pdf(ht) *
... weight_male.pdf(wt) * foot_size_male.pdf(fs))
>>> posterior_female = (prior_female * height_female.pdf(ht) *
... weight_female.pdf(wt) * foot_size_female.pdf(fs))
最后的预测去最大的后验。 这被称为 最大后验 或 MAP:
>>> 'male' if posterior_male > posterior_female else 'female'
'female'