statistics
——数理统计函数¶
3.4 新版功能.
源代码: Lib/statistics.py
此模块提供计算数字统计的函数 (Real
数据。
该模块不打算成为第三方库的竞争对手,如 NumPy , SciPy ,或专门针对Minitab、SAS和Matlab等专业统计学家的全功能统计软件包。它的目标是绘图和科学计算器的水平。
除非明确指出,否则这些函数支持 int
, float
, Decimal
和 Fraction
. 当前不支持与其他类型(无论是否在数字塔中)的行为。具有多种类型的集合也未定义且依赖于实现。如果输入数据由混合类型组成,则可以使用 map()
为了确保结果一致,例如: map(float, input_data)
.
中心位置的平均值和度量¶
这些函数计算总体或样本的平均值或典型值。
数据的算术平均(“平均”)。 |
|
快速,浮点算术平均值。 |
|
数据的几何平均值。 |
|
数据的调和平均值。 |
|
数据的中值(中值)。 |
|
数据中位数低。 |
|
数据中位数高。 |
|
分组数据的中位数或50%。 |
|
离散或名义数据的单模(最常用的值)。 |
|
离散或多项式数据的模式列表(最常见的值)。 |
|
将数据分成等概率的区间。 |
扩散测量¶
这些函数计算总体或样本偏离典型值或平均值的程度。
数据总体标准偏差。 |
|
数据的总体方差。 |
|
样本数据标准差。 |
|
数据的样本方差。 |
功能详细信息¶
注意:函数不需要对给定的数据进行排序。然而,为了方便阅读,大多数示例显示排序序列。
- statistics.mean(data)¶
返回的样本算术平均值 data 它可以是一个序列,也可以是iterable。
算术平均数是数据的和除以数据点的数目。它通常被称为“平均值”,尽管它只是许多不同数学平均值中的一个。它是对数据中心位置的度量。
如果 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 可能是一个序列或iterable。如果输入数据集为空,则引发StatisticsError
.>>> fmean([3.5, 4.0, 5.25]) 4.25
3.8 新版功能.
- statistics.geometric_mean(data)¶
转换 data
几何平均值表示 data 使用值的乘积(与使用其和的算术平均数相反)。
提出一个
StatisticsError
如果输入数据集为空、包含零或包含负值。这个 data 可能是一个序列或iterable。没有特别的努力来取得确切的结果。(然而,这在将来可能会改变。)
>>> round(geometric_mean([54, 24, 36]), 1) 36.0
3.8 新版功能.
- statistics.harmonic_mean(data, weights=None)¶
返回的调和平均值 data 、实数序列或可迭代的实数。如果 重量 被省略或省略 None ,则假定权重相等。
调和平均数,有时称为次trary平均数,是算术的倒数。
mean()
数据的倒数。例如,三个值的调和平均值 a , b 和 c 相当于3/(1/a + 1/b + 1/c)
. 如果其中一个值为零,则结果为零。调和平均数是一种平均数,是对数据中心位置的度量。当平均速率或比率(例如速度)时,它通常是合适的。
假设一辆车以40公里/小时的速度行驶10公里,然后再以60公里/小时的速度行驶10公里。平均速度是多少?
>>> harmonic_mean([40, 60]) 48.0
假设一辆车以40公里/小时的速度行驶5公里,当交通畅通时,速度-剩下的30公里最高可达60公里/小时。平均速度是多少?
>>> harmonic_mean([40, 60], weights=[5, 30]) 56.0
StatisticsError
如果发生以下情况,则引发 data 为空,则任何元素都小于零,或者如果加权和不为正。当当前算法在输入中遇到零时,它会提前退出。这意味着随后的输入没有经过有效性测试。(这种行为将来可能会改变。)
3.6 新版功能.
在 3.10 版更改: 添加了对以下各项的支持 重量 。
- statistics.median(data)¶
返回数值数据的中位数(中间值),使用常用的“中间两个值的平均值”方法。如果 data 是空的,
StatisticsError
提高了。 data 可以是序列,也可以是iterable。中值是一种稳健的中心位置度量,受异常值的影响较小。当数据点数为奇数时,返回中间数据点:
>>> median([1, 3, 5]) 3
当数据点的数目为偶数时,通过取两个中间值的平均值来插值中值:
>>> median([1, 3, 5, 7]) 4.0
这适用于数据是离散的,您不介意中间值可能不是实际的数据点。
如果数据是序数(支持顺序操作)而不是数字(不支持加法),请考虑使用
median_low()
或median_high()
相反。
- statistics.median_low(data)¶
返回数值数据的低中位数。如果 data 是空的,
StatisticsError
提高了。 data 可以是序列,也可以是iterable。低中位数始终是数据集的成员。当数据点数为奇数时,返回中间值。如果为偶数,则返回两个中间值中较小的值。
>>> median_low([1, 3, 5]) 3 >>> median_low([1, 3, 5, 7]) 3
当您的数据是离散的,并且您希望中间值是实际的数据点而不是插值时,请使用低中间值。
- statistics.median_high(data)¶
返回数据的高中位数。如果 data 是空的,
StatisticsError
提高了。 data 可以是序列,也可以是iterable。高中位数始终是数据集的成员。当数据点数为奇数时,返回中间值。如果为偶数,则返回两个中间值中较大的值。
>>> median_high([1, 3, 5]) 3 >>> median_high([1, 3, 5, 7]) 5
当您的数据是离散的并且您希望中间值是实际的数据点而不是插值时,请使用高中间值。
- statistics.median_grouped(data, interval=1)¶
返回分组连续数据的中位数,使用插值计算为第50个百分点。如果 data 是空的,
StatisticsError
提高了。 data 可以是序列,也可以是iterable。>>> 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
可选参数 间隔 表示类间隔,默认为1。自然更改类间隔将更改插值:
>>> median_grouped([1, 3, 3, 5, 7], interval=1) 3.25 >>> median_grouped([1, 3, 3, 5, 7], interval=2) 3.5
此函数不检查数据点是否至少 间隔 分开。
CPython implementation detail: 在某些情况下,
median_grouped()
可能会强制数据点浮动。这种行为将来可能会改变。参见
“行为科学统计”,Frederick J Gravetter和Larry B Wallnau(第8版)。
这个 SSMEDIAN gnome gnumeric电子表格中的函数,包括 this discussion .
- statistics.mode(data)¶
从离散或名义返回单个最常见的数据点 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()
功能通常是更好的选择。引发
StatisticsError
如果 data 是空的。实例:
>>> 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)
注解
当对整个总体进行调用时,这将给出总体方差σ2。当调用一个样本时,这是有偏差的样本方差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()
.引发
StatisticsError
如果 data 值少于两个。实例:
>>> 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自由度的方差。如果数据点具有代表性(例如独立且分布相同),则结果应为真实总体方差的无偏估计。
如果你知道实际人口的意思,你应该把它传给
pvariance()
作为 mu 获取样本方差的参数。
- statistics.quantiles(data, *, n=4, method='exclusive')¶
分 data 进入之内 n 等概率的连续区间。返回的列表
n - 1
分隔间隔的切割点。集合 n 四分位数为4(默认值)。集合 n 十分之一。集合 n 百分位数为100,该百分位数给出了99个分割点 data 分成100个大小相等的小组。提高
StatisticsError
如果 n 不是至少1。这个 data 可以是任何包含示例数据的iterable。对于有意义的结果,数据点的数量 data 应该大于 n . 加薪
StatisticsError
如果没有至少两个数据点。切割点从最近的两个数据点进行线性插值。例如,如果一个切割点落下两个采样值之间距离的三分之一,
100
和112
,切割点将评估为104
.这个 方法 对于计算,分位数可以根据 data 包括或排除人口中可能的最低和最高值。
默认值 方法 是“独占”的,用于从具有比样本中更极端值的总体中采样的数据。人口中低于 i-th 属于 m 排序后的数据点计算为
i / (m + 1)
.在给定9个样本值的情况下,该方法对其进行排序并分配以下百分比:10%、20%、30%、40%、50%、60%、70%、80%、90%。设置 方法 “包含”用于描述总体数据或已知包含总体中最极端值的样本。最小值 data 按0%处理,最大值按100%处理。人口中低于 i-th 属于 m 排序后的数据点计算为
(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 新版功能.
例外情况¶
定义单个异常:
- exception statistics.StatisticsError¶
的子类
ValueError
统计相关异常。
NormalDist
物体¶
NormalDist
是创建和操作 random variable . 它是一个将数据测量的平均值和标准偏差视为单个实体的类。
正态分布产生于 Central Limit Theorem 在统计学上有广泛的应用。
- class statistics.NormalDist(mu=0.0, sigma=1.0)¶
返回新的 NormalDist 对象在哪里 mu 代表 arithmetic mean 和 西格玛 代表 standard deviation .
如果 西格玛 是负的,引发
StatisticsError
.- mean¶
的只读属性 arithmetic mean 正态分布的。
- stdev¶
的只读属性 standard deviation 正态分布的。
- classmethod from_samples(data)¶
使正态分布实例具有 mu 和 西格玛 参数估计来自 data 使用
fmean()
和stdev()
.这个 data 可以是任何 iterable 并且应包含可转换为类型的值
float
. 如果 data 不包含至少两个元素,引发StatisticsError
因为估计中心值至少需要一个点,估计分散度至少需要两个点。
- samples(n, *, seed=None)¶
生成 n 给定平均值和标准偏差的随机样本。返回A
list
属于float
价值观。如果 seed 如果给定,则创建基础随机数生成器的新实例。这对于创建可重复的结果非常有用,即使在多线程环境中也是如此。
- pdf(x)¶
使用A probability density function (pdf) ,计算一个随机变量 X 将接近给定值 x . 从数学上讲,这是比率的极限
P(x <= X < x+dx) / dx
作为 dx 接近零。相对可能性的计算方法是:样本发生在一个狭窄范围内的概率除以该范围的宽度(因此称为“密度”)。由于可能性与其他点相关,其值可以大于 1.0 .
- cdf(x)¶
使用A cumulative distribution function (cdf) ,计算一个随机变量 X 将小于或等于 x . 数学上,它是写的
P(X <= x)
.
- inv_cdf(p)¶
计算反累积分布函数,也称为 quantile function 或 percent-point 功能。数学上,它是写的
x : P(X <= x) = p
.查找值 x 随机变量的 X 使变量小于或等于该值的概率等于给定概率 p .
- overlap(other)¶
测量两个正态概率分布之间的一致性。返回介于0.0和1.0之间的值 the overlapping area for the two probability density functions .
- quantiles(n=4)¶
将正态分布分为 n 等概率连续区间。返回分隔间隔的(n-1)个切点的列表。
集合 n 四分位数为4(默认值)。集合 n 到10分贝。套 n 百分位数为100,给出了将正态分布分为100个等大小组的99个切点。
- zscore(x)¶
计算 Standard Score 描述 x 就高于或低于正态分布平均值的标准差数量而言:
(x - mean) / stdev
.3.9 新版功能.
实例
NormalDist
支持加、减、乘、除一个常数。这些操作用于转换和缩放。例如:>>> temperature_february = NormalDist(5, 2.5) # Celsius >>> temperature_february * (9/5) + 32 # Fahrenheit NormalDist(mu=41.0, sigma=4.5)
将常量除以
NormalDist
不支持,因为结果不会正常分布。由于正态分布是由自变量的加性效应引起的,因此有可能 add and subtract two independent normally distributed random variables 表示为的实例
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
很容易解决经典的概率问题。
例如,给定 historical data for SAT exams 显示分数正态分布,平均值为1060,标准差为195,在四舍五入到最接近的整数后,确定测试分数在1100到1200之间的学生百分比:
>>> sat = NormalDist(1060, 195)
>>> fraction = sat.cdf(1200 + 0.5) - sat.cdf(1100 - 0.5)
>>> round(fraction * 100.0, 1)
18.4
找到 quartiles 和 deciles 对于SAT分数:
>>> 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
可以为 Monte Carlo simulation :
>>> 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]
正态分布可用于近似 Binomial distributions 当样本量较大且试验成功率接近50%时。
例如,一个开放源码会议有750名与会者和两个容纳500人的会议室。有一个关于Python的讨论,还有一个关于Ruby的讨论。在以前的会议中,65%的与会者更喜欢听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
正态分布通常出现在机器学习问题中。
维基百科有 nice example of a Naive Bayesian Classifier . 挑战在于通过测量身高、体重和脚的大小来预测一个人的性别。
我们得到了一个训练数据集,里面有八个人的测量数据。假设测量值是正态分布的,因此我们用 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 probability 对于男性或女性,我们将后验作为之前的时间,根据性别计算特征测量的相似性乘积:
>>> 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))
最后的预测是最大的后验。这被称为 maximum a posteriori 或地图:
>>> 'male' if posterior_male > posterior_female else 'female'
'female'