我想使用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 * rsum
和n_rcsum = (n - rsum) * (n - csum)
。两个输出数组的形状均为(2,5)
。在这里似乎有必要计算cr_sum
和n_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)
答案 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
和一个警告。
解决方法是在进行中间计算之前将rsum
和csum
转换为浮点。试试这个版本:
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)