为什么不scipy.stats.mstats.pearsonr结果与scipy.stats.pearsonr一致?

时间:2014-05-12 04:39:11

标签: python statistics scipy

我预计scipy.stats.mstats.pearsonr对于屏蔽数组输入的结果会为scipy.stats.pearsonr提供与输入数据的未屏蔽值相同的结果,但它没有“T:

from pylab import randn,rand
from numpy import ma
import scipy.stats

# Normally distributed data with noise
x=ma.masked_array(randn(10000),mask=False)
y=x+randn(10000)*0.6

# Randomly mask one tenth of each of x and y
x[rand(10000)<0.1]=ma.masked
y[rand(10000)<0.1]=ma.masked

# Identify indices for which both data are unmasked
bothok=((~x.mask)*(~y.mask))

# print results of both functions, passing only the data where 
# both x and y are good to scipy.stats
print "scipy.stats.mstats.pearsonr:", scipy.stats.mstats.pearsonr(x,y)[0]
print "scipy.stats.pearsonr:", scipy.stats.pearsonr(x[bothok].data,y[bothok].data)[0]

每次执行此操作时,答案会有所不同,但对于我来说,这些值差异大约为0.1,屏蔽分数越大,分歧就越大。

我注意到如果对x和y使用相同的掩码,则两个函数的结果相同,即:

mask=rand(10000)<0.1
x[mask]=ma.masked
y[mask]=ma.masked
...

这是一个错误,还是我希望预先输入数据以确保x和y中的掩码相同(当然不是)?

我正在使用numpy版本'1.8.0'和scipy版本'0.11.0b1'

2 个答案:

答案 0 :(得分:2)

这看起来像scipy.stats.mstats.pearsonr中的错误。看来xy中的值预计会与索引配对,因此如果屏蔽了一个,则应忽略另一个。也就是说,如果xy看起来像(使用--作为屏蔽值):

x = [1, --,  3,  4,  5]
y = [9,  8, --,  6,  5]

然后忽略(--, 8)(3, --),结果应该与scipy.stats.pearsonr([1, 4, 5], [9, 6, 5])相同。

the mstats version中的错误是compute the means of x and y的代码不使用公共掩码。

我在scipy github网站上为此创建了一个问题:https://github.com/scipy/scipy/issues/3645

答案 1 :(得分:1)

我们(至少)有两个缺失值处理选项,完整的案例删除和成对删除。

在使用scipy.stats.pearsonr时,您会完全删除任何变量中缺少值的情况。

numpy.ma.corrcoef会得到相同的结果。

检查scipy.stats.mstats.pearsonr的来源,它不会为计算方差或均值而完全删除案例。

>>> xm = x - x.mean(0)
>>> ym = y - y.mean(0)
>>> np.ma.dot(xm, ym) / np.sqrt(np.ma.dot(xm, xm) * np.ma.dot(ym, ym))
0.7731167378113557

>>> scipy.stats.mstats.pearsonr(x,y)[0]
0.77311673781135637

然而,平均和标准偏差的完全和成对案例删除之间的差异很小。

主要差异似乎来自对不同数量的非缺失元素的缺失修正。 Iignoring自由度修正,我得

>>> np.ma.dot(xm, ym) / bothok.sum() / \
    np.sqrt(np.ma.dot(xm, xm) / (~xm.mask).sum() * np.ma.dot(ym, ym) / (~ym.mask).sum())
0.85855728319303393

接近完整的案例删除案例。