<h2>使用屏蔽数组</h2>
<p>只使用numpy的标准方法是使用<a href="https://docs.scipy.org/doc/numpy/reference/maskedarray.html" rel="noreferrer">masked array</a>模块。</p>
<p>Scipy是一个非常重的包,它依赖于外部库,因此有一个只使用numpy的方法是值得的。这借用了@DonaldHobson的答案。</p>
<p><strong>编辑:</strong><a href="https://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.nanmean.html" rel="noreferrer">^{<cd1>}</a>现在是一个numpy函数。但是,它不能处理所有的nan列。。。</p>
<p>假设您有一个数组<code>a</code>:</p>
<pre><code>>>> a
array([[ 0., nan, 10., nan],
[ 1., 6., nan, nan],
[ 2., 7., 12., nan],
[ 3., 8., nan, nan],
[ nan, 9., 14., nan]])
>>> import numpy.ma as ma
>>> np.where(np.isnan(a), ma.array(a, mask=np.isnan(a)).mean(axis=0), a)
array([[ 0. , 7.5, 10. , 0. ],
[ 1. , 6. , 12. , 0. ],
[ 2. , 7. , 12. , 0. ],
[ 3. , 8. , 12. , 0. ],
[ 1.5, 9. , 14. , 0. ]])
</code></pre>
<p>注意,屏蔽数组的平均值不需要与<code>a</code>的形状相同,因为我们利用了行上的隐式<a href="https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html" rel="noreferrer">broadcasting</a>。</p>
<p>还要注意如何很好地处理all-nan列。因为取零元素的平均值,所以平均值为零。使用<code>nanmean</code>的方法不能处理所有nan列:</p>
<pre><code>>>> col_mean = np.nanmean(a, axis=0)
/home/praveen/.virtualenvs/numpy3-mkl/lib/python3.4/site-packages/numpy/lib/nanfunctions.py:675: RuntimeWarning: Mean of empty slice
warnings.warn("Mean of empty slice", RuntimeWarning)
>>> inds = np.where(np.isnan(a))
>>> a[inds] = np.take(col_mean, inds[1])
>>> a
array([[ 0. , 7.5, 10. , nan],
[ 1. , 6. , 12. , nan],
[ 2. , 7. , 12. , nan],
[ 3. , 8. , 12. , nan],
[ 1.5, 9. , 14. , nan]])
</code></pre>
<hr/>
<p><strong>说明</strong></p>
<p>将<code>a</code>转换为屏蔽数组</p>
<pre><code>>>> ma.array(a, mask=np.isnan(a))
masked_array(data =
[[0.0 -- 10.0 --]
[1.0 6.0 -- --]
[2.0 7.0 12.0 --]
[3.0 8.0 -- --]
[-- 9.0 14.0 --]],
mask =
[[False True False True]
[False False True True]
[False False False True]
[False False True True]
[ True False False True]],
fill_value = 1e+20)
</code></pre>
<p>取列上的平均值将给出<em>正确的</em>答案,仅对非屏蔽值进行规范化:</p>
<pre><code>>>> ma.array(a, mask=np.isnan(a)).mean(axis=0)
masked_array(data = [1.5 7.5 12.0 --],
mask = [False False False True],
fill_value = 1e+20)
</code></pre>
<p>此外,请注意掩码如何很好地处理<em>all nan</em>列!</p>
<p>最后,<a href="https://docs.scipy.org/doc/numpy/reference/generated/numpy.where.html" rel="noreferrer">^{<cd6>}</a>完成替换工作。</p>
<hr/>
<p><strong>行平均值</strong></p>
<p>要将<code>nan</code>值替换为行平均值而不是列平均值,广播需要进行微小的更改才能很好地生效:</p>
<pre><code>>>> a
array([[ 0., 1., 2., 3., nan],
[ nan, 6., 7., 8., 9.],
[ 10., nan, 12., nan, 14.],
[ nan, nan, nan, nan, nan]])
>>> np.where(np.isnan(a), ma.array(a, mask=np.isnan(a)).mean(axis=1), a)
ValueError: operands could not be broadcast together with shapes (4,5) (4,) (4,5)
>>> np.where(np.isnan(a), ma.array(a, mask=np.isnan(a)).mean(axis=1)[:, np.newaxis], a)
array([[ 0. , 1. , 2. , 3. , 1.5],
[ 7.5, 6. , 7. , 8. , 9. ],
[ 10. , 12. , 12. , 12. , 14. ],
[ 0. , 0. , 0. , 0. , 0. ]])
</code></pre>