如何使用numpy的行均值替换丢失/屏蔽数据

时间:2013-10-30 16:07:41

标签: python numpy missing-data

如何替换' b'中的缺失值?下面的数组中包含相应的行平均值' c'?

a=numpy.arange(24).reshape(4,-1)
b=numpy.ma.masked_where(numpy.remainder(a,5)==0,a);b
Out[46]: 
 masked_array(data =
 [[-- 1 2 3 4 --]
 [6 7 8 9 -- 11]
 [12 13 14 -- 16 17]
 [18 19 -- 21 22 23]],
         mask =
 [[ True False False False False  True]
 [False False False False  True False]
 [False False False  True False False]
 [False False  True False False False]],
       fill_value = 999999)

c=b.mean(axis=1);c
Out[47]: 
masked_array(data = [2.5 8.2 14.4 20.6],
         mask = [False False False False],
   fill_value = 1e+20)

2 个答案:

答案 0 :(得分:2)

您可以使用wheretake

inds = np.where(b.mask)

b[inds] = np.take(c,inds[0])

b
masked_array(data =
 [[2 1 2 3 4 2]
 [6 7 8 9 8 11]
 [12 13 14 14 16 17]
 [18 19 20 21 22 23]],
             mask =
 [[False False False False False False]
 [False False False False False False]
 [False False False False False False]
 [False False False False False False]],
       fill_value = 999999)

在此特定示例中,您遇到了dtype a的问题。如果您在创建a = a.astype(np.float)之前添加b,那就可以了。可能有一种更快的方法来创建索引np.where

答案 1 :(得分:2)

试试这个:

np.copyto(b, c[...,None], where=b.mask)

您必须将额外轴添加到c,以便它知道将其应用于每一行。 (如果np.mean有一个keepdims选项,例如np.sum,则没有必要:P

import numpy as np

a = np.arange(24).reshape(4,-1).astype(float)   # I changed your example to be a float
b = np.ma.masked_where(numpy.remainder(a,5)==0,a)
c = b.mean(1)

np.copyto(b, c[...,None], where=b.mask)

In [189]: b.data
Out[189]: 
array([[  2.5,   1. ,   2. ,   3. ,   4. ,   2.5],
       [  6. ,   7. ,   8. ,   9. ,   8.2,  11. ],
       [ 12. ,  13. ,  14. ,  14.4,  16. ,  17. ],
       [ 18. ,  19. ,  20.6,  21. ,  22. ,  23. ]])

这比创建inds数组更快:

In [169]: %%timeit
   .....: inds = np.where(b.mask)
   .....: b[inds] = np.take(c, inds[0])
   .....: 
10000 loops, best of 3: 81.2 µs per loop


In [173]: %%timeit
   .....: np.copyto(b, c[...,None], where=b.mask)
   .....: 
10000 loops, best of 3: 45.1 µs per loop

另一个优点是它会警告你dtype问题:

a = np.arange(24).reshape(4,-1)    # still an int
b = np.ma.masked_where(numpy.remainder(a,5)==0,a)
c = b.mean(1)

In [193]: np.copyto(b, c[...,None], where=b.mask)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-193-edc7f01f3f89> in <module>()
----> 1 np.copyto(b, c[...,None], where=b.mask)

TypeError: Can not cast scalar from dtype('float64') to dtype('int64') according to the rule 'same_kind'

顺便提一下,这个任务有一组函数,具体取决于你有哪些不同的源格式,例如

np.put
顺序将输入数组放入索引给出的位置的输出数组中,就像@Ophion的回答一样。

np.place
顺序将输入(列表或1d数组)中的每个元素分配到输出数组中掩码为真的位置(不与输入数组对齐,因为它们的形状不必匹配)。

np.copyto
将始终将输入数组中的值放入输出数组中的相同(广播)位置。形状必须匹配(或可广播)。它有效地取代了旧函数np.putmask