用Python计算Pearson的标准化残差

时间:2019-06-15 13:10:02

标签: python python-3.x numpy

我想使用scipy.stats.chi2_contingency的输出来计算Python(3.7.1)中Pearson的标准化残差。我已经迷住了this stackoverflow post,这正是我所需要的,但是我得到了错误的结果。我只能猜测这可能与我较新的Python版本有关(链接来自2013年)?

我已经分解了

的计算公式

v = csum * rsum * (n - rsum) * (n - csum) / n**3

分为术语cr_sum = csum * rsumn_rcsum = (n - rsum) * (n - csum)。两个输出数组的形状均为(2,5)。在这里似乎有必要计算cr_sumn_rcsum的Hadamard积。当我手动处理第一个单元(频率值为33)时,我得到了正确的残差(-2.62309082)。但是,我无法在Python中使用此Hadamard产品。相反,Python在某些广播和输出中似乎是这样的:

array([[-1125512208, -267063340, -274153780, -1725637260, 691228240], [-1125512208, -267063340, -274153780, -1725637260, 691228240]])

此外,我通常对何时使用哪种乘法类型感到困惑。在stackoverflow帖子中,评论者仅使用星号,一切似乎都正常运行。必须对代码进行哪些更改,为什么?

这是我的代码:

from __future__ import division

import numpy as np
from scipy.stats.contingency import margins
from scipy.stats import chi2_contingency

def residuals(observed, expected):
    return (observed - expected) / np.sqrt(expected)

def stdres(observed, expected):
    n = observed.sum()
    rsum, csum = margins(observed)
    v = csum * rsum * (n - rsum) * (n - csum) / n**3
    return (observed - expected) / np.sqrt(v)

F = np.array([[33, 250, 196, 136, 32], [55, 293, 190, 71, 13]])
chi2, p, dof, expected = chi2_contingency(F)
stdres = stdres(F,expected)

1 个答案:

答案 0 :(得分:1)

在Windows上,NumPy数组的默认整数类型是32位。当在What is the equivalent of R data.chisq$residuals in python?处的代码上使用输入数组F = np.array([[33, 250, 196, 136, 32], [55, 293, 190, 71, 13]])在Windows上运行时,函数csum * rsum * (n - rsum) * (n - csum)中表达式stdres的中间计算会导致整数溢出。溢出将负的负值放入变量v中,因此在计算sqrt(v)时,您将得到nan和一个警告。

解决方法是在进行中间计算之前将rsumcsum转换为浮点。试试这个版本:

def stdres(observed, expected):
    n = observed.sum()
    rsum, csum = margins(observed)
    rsum = rsum.astype(np.float64)
    csum = csum.astype(np.float64)
    v = csum * rsum * (n - rsum) * (n - csum) / n**3
    return (observed - expected) / np.sqrt(v)