将 Z 分数(Z 值,标准分数)转换为 Python 中正态分布的 p 值

Posted

技术标签:

【中文标题】将 Z 分数(Z 值,标准分数)转换为 Python 中正态分布的 p 值【英文标题】:Convert Z-score (Z-value, standard score) to p-value for normal distribution in Python 【发布时间】:2011-03-30 15:02:33 【问题描述】:

如何将Z-score 从Z-distribution (standard normal distribution, Gaussian distribution) 转换为p-value?我还没有找到 Scipy's stats module 的神奇功能来做到这一点,但必须有一个。

【问题讨论】:

我在这里开始了一个statsandprobability.codeplex.com 【参考方案1】:

啊哈!我找到了:scipy.special.ndtr!这似乎也在scipy.stats.stats.zprob 下(它只是一个指向ndtr 的指针)。

具体来说,给定一个一维numpy.array实例z_scores,可以得到p值

p_values = 1 - scipy.special.ndtr(z_scores)

或者

p_values = scipy.special.ndtr(-z_scores)

【讨论】:

奇怪的术语,“Z 分布”而不是“正态曲线”。 Z-score 在这种情况下我可能也会称其为标准差。 嗯,Z 分布 == “标准正态分布” == N(0, 1)。也就是说,你的观点很好。我更新了问题以反映相同概念的各种术语。【参考方案2】:

我更喜欢正态分布的生存函数(上尾概率),因为函数名称信息量更大:

p_values = scipy.stats.norm.sf(abs(z_scores)) #one-sided

p_values = scipy.stats.norm.sf(abs(z_scores))*2 #twosided

正态分布“norm”是 scipy.stats 中大约 90 个分布之一

norm.sf 还调用了 scipy.special 中的相应函数,如 gotgenes 示例中一样

生存函数的小优势,sf:数值精度对于接近 1 的分位数应该比使用 cdf 更好

【讨论】:

【参考方案3】:

我认为累积分布函数 (cdf) 优于幸存者函数。幸存者函数被定义为 1-cdf,并且可能不正确地传达语言模型用于方向百分位数的假设。还有,百分比函数(ppf)是cdf的倒数,非常方便。

>>> import scipy.stats as st
>>> st.norm.ppf(.95)
1.6448536269514722
>>> st.norm.cdf(1.64)
0.94949741652589625

编辑: 一位用户请求了“向量”的示例:

import numpy as np
vector = np.array([.925, .95, .975, .99])
p_values = [st.norm.ppf(v) for v in vector]
f_values = [st.norm.cdf(p) for p in p_values]

for p,f in zip(p_values, f_values):
 print(f'p: p, \tf: f')   

产量:

p: 1.4395314709384563,  f: 0.925
p: 1.6448536269514722,  f: 0.95
p: 1.959963984540054,   f: 0.975
p: 2.3263478740408408,  f: 0.99

【讨论】:

您能否提供更完整的代码答案,说明如何将 Z 分数向量转换为 p 值向量? @RobinDeSchepper 添加【参考方案4】:

来自公式:

import numpy as np
import scipy.special as scsp
def z2p(z):
    """From z-score return p-value."""
    return 0.5 * (1 + scsp.erf(z / np.sqrt(2)))

【讨论】:

这不是最好的解决方案;它不像上面的答案那样矢量化。 您只需将math.erfmath.sqrt 替换为scipy 中的erfsqrt 即可获得矢量化版本。 这是最好的解决方案,如果 z 不是向量【参考方案5】:
p_value = scipy.stats.norm.pdf(abs(z_score_max)) #one-sided test 
p_value = scipy.stats.norm.pdf(abs(z_score_max))*2 # two - sided test

python 中的概率密度函数 (pdf) 函数产生的值 p 值取自 intro/AP 统计书中的 z 分数表。

【讨论】:

【参考方案6】:

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

可用于应用逆累积分布函数inv_cdf,也称为分位数函数 或百分比函数)和累积分布函数 (cdf):

NormalDist().inv_cdf(0.95)
# 1.6448536269514715
NormalDist().cdf(1.64)
# 0.9494974165258963

【讨论】:

【参考方案7】:

对于 Scipy 爱好者来说,Tough 这是个老问题,但很相关,我们不仅可以有正态分布,还可以有其他分布,所以这里是更多分布的解决方案:

def get_p_value_normal(z_score: float) -> float:
    """get p value for normal(Gaussian) distribution 

    Args:
        z_score (float): z score

    Returns:
        float: p value
    """
    return round(norm.sf(z_score), decimal_limit)


def get_p_value_t(z_score: float) -> float:
    """get p value for t distribution 

    Args:
        z_score (float): z score

    Returns:
        float: p value
    """
    return round(t.sf(z_score), decimal_limit)


def get_p_value_chi2(z_score: float) -> float:
    """get p value for chi2 distribution 

    Args:
        z_score (float): z score

    Returns:
        float: p value
    """
    return round(chi2.ppf(z_score, df), decimal_limit)

【讨论】:

以上是关于将 Z 分数(Z 值,标准分数)转换为 Python 中正态分布的 p 值的主要内容,如果未能解决你的问题,请参考以下文章

统计中的Z-score是啥意思

Z-score和T-score的区别

什么是Z-score?都有哪些使用场景?

z模型怎么用电脑算

为啥在计算 z 分数时将样本标准差除以 sqrt(样本大小)

scipy.stats 转换器正常 z 分数到 p 值 Python3