numpy数组:用平均列替换nan值

pio*_*kuc 38 python arrays numpy nan

我有一个主要用实数填充的numpy数组,但它中也有一些nan值.

如何nan用平均列替换s?

Dan*_*iel 61

无需循环:

print(a)
[[ 0.93230948         nan  0.47773439  0.76998063]
 [ 0.94460779  0.87882456  0.79615838  0.56282885]
 [ 0.94272934  0.48615268  0.06196785         nan]
 [ 0.64940216  0.74414127         nan         nan]]

#Obtain mean of columns as you need, nanmean is just convenient.
col_mean = np.nanmean(a, axis=0)
print(col_mean)
[ 0.86726219  0.7030395   0.44528687  0.66640474]

#Find indicies that you need to replace
inds = np.where(np.isnan(a))

#Place column means in the indices. Align the arrays using take
a[inds] = np.take(col_mean, inds[1])

print(a)
[[ 0.93230948  0.7030395   0.47773439  0.76998063]
 [ 0.94460779  0.87882456  0.79615838  0.56282885]
 [ 0.94272934  0.48615268  0.06196785  0.66640474]
 [ 0.64940216  0.74414127  0.44528687  0.66640474]]
Run Code Online (Sandbox Code Playgroud)

  • 您现在可以使用numpy.nanmean()而不是import scipy:http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.nanmean.html (8认同)
  • 您使用的任何原因而不仅仅是索引? (3认同)

Pra*_*een 11

使用蒙面数组

仅使用numpy执行此操作的标准方法是使用掩码数组模块.

Scipy是一个非常重的包,它依赖于外部库,因此值得拥有一个只有numpy的方法.这借鉴了@DonaldHobson的回答.

编辑: np.nanmean现在是一个numpy功能.但是,它不能处理全纳柱......

假设你有一个数组a:

>>> 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. ]])
Run Code Online (Sandbox Code Playgroud)

请注意,屏蔽数组的平均值不需要与形状相同a,因为我们正在利用行上的隐式广播.

还要注意如何很好地处理全纳柱.由于您采用零元素的均值,因此均值为零.使用的方法nanmean不处理全纳列:

>>> 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]])
Run Code Online (Sandbox Code Playgroud)

说明

转换a为蒙版数组会给你

>>> 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)
Run Code Online (Sandbox Code Playgroud)

对列进行均值可以得到正确的答案,仅对非掩码值进行归一化:

>>> 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)
Run Code Online (Sandbox Code Playgroud)

此外,请注意掩码如何很好地处理全纳的列!

最后,np.where做了更换工作.


行意味着

要nan使用行方式而不是按列方式替换值,需要对广播进行微小更改才能很好地生效:

>>> 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. ]])
Run Code Online (Sandbox Code Playgroud)


Don*_*son 5

如果partial是原始数据,而replace是包含平均值的相同形状的数组,则此代码将使用partial中的值(如果存在)。

Complete= np.where(np.isnan(partial),replace,partial)
Run Code Online (Sandbox Code Playgroud)