normaltest#
- scipy.stats.normaltest(a, axis=0, nan_policy='propagate', *, keepdims=False)[源代码][源代码]#
测试样本是否与正态分布不同。
此函数测试样本来自正态分布的零假设。它基于 D’Agostino 和 Pearson 的 [1]、[2] 检验,该检验结合了偏度和峰度,以生成正态性的综合检验。
- 参数:
- aarray_like
包含待测样本的数组。必须至少包含八个观测值。
- 轴int 或 None, 默认值: 0
如果是一个整数,表示输入数据中要计算统计量的轴。输入数据的每个轴切片(例如行)的统计量将出现在输出的相应元素中。如果为
None
,则在计算统计量之前会将输入数据展平。- nan_policy{‘propagate’, ‘omit’, ‘raise’}
定义如何处理输入的 NaN。
propagate
: 如果在计算统计量的轴切片(例如行)中存在 NaN,则输出的相应条目将为 NaN。omit
: 在执行计算时,NaN 将被省略。如果在计算统计量的轴切片中剩余的数据不足,则输出的相应条目将为 NaN。raise
: 如果存在 NaN,将引发ValueError
。
- keepdimsbool, 默认值: False
如果设置为True,被减少的轴将作为尺寸为1的维度保留在结果中。通过此选项,结果将正确地与输入数组进行广播。
- 返回:
- 统计浮点数或数组
s^2 + k^2
,其中s
是skewtest
返回的 z 分数,k
是kurtosistest
返回的 z 分数。- p值浮点数或数组
双侧卡方概率用于假设检验。
注释
从 SciPy 1.9 开始,
np.matrix
输入(不推荐用于新代码)在计算执行前被转换为np.ndarray
。在这种情况下,输出将是一个标量或适当形状的np.ndarray
,而不是一个 2D 的np.matrix
。同样,虽然掩码数组的掩码元素被忽略,但输出将是一个标量或np.ndarray
,而不是一个mask=False
的掩码数组。参考文献
[3]Shapiro, S. S., & Wilk, M. B. (1965). 正态性的方差分析检验(完整样本)。《生物统计学》, 52(3/4), 591-611.
[4]B. Phipson and G. K. Smyth. “Permutation P-values Should Never Be Zero: Calculating Exact P-values When Permutations Are Randomly Drawn.” Statistical Applications in Genetics and Molecular Biology 9.1 (2010).
[5]Panagiotakos, D. B. (2008). p值在生物医学研究中的价值。《开放心血管医学杂志》, 2, 97.
示例
假设我们希望从测量结果中推断,医学研究中成年男性体重的分布是否不是正态分布 [3]。体重(磅)记录在下面的数组
x
中。>>> import numpy as np >>> x = np.array([148, 154, 158, 160, 161, 162, 166, 170, 182, 195, 236])
对 [1] 和 [2] 的正态性检验首先通过计算基于样本偏度和峰度的统计量来开始。
>>> from scipy import stats >>> res = stats.normaltest(x) >>> res.statistic 13.034263121192582
(测试警告称,我们的样本观测值太少,无法进行测试。我们将在示例结束时回到这一点。)由于正态分布的偏度为零,峰度(“过剩”或“费舍尔”)也为零,因此从正态分布中抽取的样本的该统计量值往往较低。
测试通过将统计量的观测值与零分布进行比较来执行:零分布是在权重从正态分布中抽取的零假设下得出的统计量值的分布。对于这种正态性测试,非常大的样本的零分布是具有两个自由度的卡方分布。
>>> import matplotlib.pyplot as plt >>> dist = stats.chi2(df=2) >>> stat_vals = np.linspace(0, 16, 100) >>> pdf = dist.pdf(stat_vals) >>> fig, ax = plt.subplots(figsize=(8, 5)) >>> def plot(ax): # we'll reuse this ... ax.plot(stat_vals, pdf) ... ax.set_title("Normality Test Null Distribution") ... ax.set_xlabel("statistic") ... ax.set_ylabel("probability density") >>> plot(ax) >>> plt.show()
比较通过 p 值量化:零分布中大于或等于统计量观测值的值的比例。
>>> fig, ax = plt.subplots(figsize=(8, 5)) >>> plot(ax) >>> pvalue = dist.sf(res.statistic) >>> annotation = (f'p-value={pvalue:.6f}\n(shaded area)') >>> props = dict(facecolor='black', width=1, headwidth=5, headlength=8) >>> _ = ax.annotate(annotation, (13.5, 5e-4), (14, 5e-3), arrowprops=props) >>> i = stat_vals >= res.statistic # index more extreme statistic values >>> ax.fill_between(stat_vals[i], y1=0, y2=pdf[i]) >>> ax.set_xlim(8, 16) >>> ax.set_ylim(0, 0.01) >>> plt.show()
>>> res.pvalue 0.0014779023013100172
如果 p 值是“小”的——也就是说,如果从正态分布的总体中抽取数据产生如此极端的统计值的概率很低——这可能被视为反对零假设而支持备择假设的证据:权重并非来自正态分布。请注意:
反之则不然;也就是说,测试并不用于为零假设提供证据。
被视为“小”的值的阈值是一个选择,应在分析数据之前做出 [4] ,同时考虑假阳性(错误地拒绝零假设)和假阴性(未能拒绝错误的零假设)的风险。
请注意,卡方分布提供了零分布的渐近近似;它仅对具有大量观测值的样本准确。这就是我们在示例开始时收到警告的原因;我们的样本非常小。在这种情况下,
scipy.stats.monte_carlo_test
可能会提供更准确(尽管是随机的)的精确 p 值近似。>>> def statistic(x, axis): ... # Get only the `normaltest` statistic; ignore approximate p-value ... return stats.normaltest(x, axis=axis).statistic >>> res = stats.monte_carlo_test(x, stats.norm.rvs, statistic, ... alternative='greater') >>> fig, ax = plt.subplots(figsize=(8, 5)) >>> plot(ax) >>> ax.hist(res.null_distribution, np.linspace(0, 25, 50), ... density=True) >>> ax.legend(['aymptotic approximation (many observations)', ... 'Monte Carlo approximation (11 observations)']) >>> ax.set_xlim(0, 14) >>> plt.show()
>>> res.pvalue 0.0082 # may vary
此外,尽管它们具有随机性,但通过这种方式计算的p值可以用来精确控制零假设被错误拒绝的比率 [5]。