我预计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'
答案 0 :(得分:2)
这看起来像scipy.stats.mstats.pearsonr
中的错误。看来x
和y
中的值预计会与索引配对,因此如果屏蔽了一个,则应忽略另一个。也就是说,如果x
和y
看起来像(使用--
作为屏蔽值):
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
接近完整的案例删除案例。