首页 > 解决方案 > 在 Python 中计算 Pearson 的标准化残差

问题描述

我想使用scipy.stats.chi2_contingency. 我已经偶然发现了这个 stackoverflow 帖子,这正是我所需要的,但是我得到了错误的结果。我只能猜测它可能与我更新的 Python 版本有关(链接来自 2013 年)?

我已经分解了计算公式

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

进入条款cr_sum = csum * rsumn_rcsum = (n - rsum) * (n - csum)。两个输出数组都具有形状(2,5)。似乎有必要在这里计算 和 的 Hadamardcr_sumn_rcsum。当我为第一个单元格(频率值为 33)手动执行此操作时,我最终得到了正确的残差(-2.62309082)。但是,我无法让这个 Hadamard 产品在 Python 中工作。相反,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)

标签: pythonpython-3.xnumpy

解决方案


在 Windows 上,NumPy 数组的默认整数类型是 32 位。当代码结束时,Python 中的 R data.chisq$residuals 相当于什么?在 Windows 上使用输入数组运行时,函数中F = np.array([[33, 250, 196, 136, 32], [55, 293, 190, 71, 13]])表达式的中间计算会导致整数溢出。溢出将负负值放入变量中,因此在计算时,您会得到s 和警告。csum * rsum * (n - rsum) * (n - csum)stdresvsqrt(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)

推荐阅读