用多个if语句Numpy重新分配值

时间:2019-02-13 08:04:46

标签: python arrays numpy

我有一个很大的Numpy ndarray,下面是一个示例:

myarray = np.array([[1.01,9.4,0.0,6.9,5.7],[1.9,2.6,np.nan,4.7,-2.45],[np.nan,0.2,0.3,4.2,15.1]])
myarray

array([[ 1.01,  9.4 ,  0.0 ,  6.9 ,  5.7 ],
       [ 1.9 ,  2.6 ,   nan,  4.7 ,  -2.45],
       [  nan,  0.2 ,  0.3 ,  4.2 , 15.1 ]])

如您所见,我的数组包含浮点数,正数,负数,零和NaN。我想基于多个if语句重新分配(重新分类)数组中的值。我已经阅读了许多答案和文档,但是我所看到的所有答案和文档都涉及一个或两个简单的条件,例如,可以使用np.where轻松解决这些条件。 我有多个条件,为简单起见,假设我有四个条件(所需的解决方案应该能够处理更多条件)。我的条件是:

if x > 6*y:
    x=3
elif x < 4*z:
    x=2
elif x == np.nan:
    x=np.nan # maybe pass is better?
else: 
    x=0

其中x是数组中的值,y和z是将在数组之间更改的变量。例如,数组#1的y = 5,z = 2,数组#2的y = 0.9,z = 0.5等。np.nan的条件仅表示如果值是nan,则不要更改它,保持它为南。

请注意,这需要同时执行,因为如果我一个接一个地使用多个np.where,则条件#2会覆盖条件#1。

我试图创建一个函数,然后将其应用于数组,但没有成功。似乎为了将一个函数应用于数组,该函数必须仅包含一个参数(数组),并且如果我打算使用一个函数,则它应包含3个参数:数组以及y和z值。 / p>

实现目标的最有效方法是什么?

1 个答案:

答案 0 :(得分:0)

In [11]: myarray = np.array([[1.01,9.4,0.0,6.9,5.7],[1.9,2.6,np.nan,4.7,-2.45],[
    ...: np.nan,0.2,0.3,4.2,15.1]])
In [13]: y, z = 0.9, 0.5

如果我在整个阵列上执行您的一项测试:

In [14]: mask1 = myarray >6*y
/usr/local/bin/ipython3:1: RuntimeWarning: invalid value encountered in greater

引起此警告的是np.nan

因此,我们首先确定那些nan(并替换):

In [25]: mask0 = np.isnan(myarray)
In [26]: mask0
Out[26]: 
array([[False, False, False, False, False],
       [False, False,  True, False, False],
       [ True, False, False, False, False]])
In [27]: arr = myarray.copy()
In [28]: arr[mask0] = 0     # temp replace the nan with 0

myarray == np.nan无效;它到处都会产生False。

arr = np.nan_to_num(myarray)也可以,将nan替换为0。

现在找到yz测试的掩码。它们如何处理原始的nan(现在为0)并不重要。首先计算两个遮罩,以减少相互干扰。

In [29]: mask1 = arr > 6*y
In [30]: mask2 = arr < 4*z
In [31]: arr[mask1]
Out[31]: array([ 9.4,  6.9,  5.7, 15.1])
In [32]: arr[mask2]
Out[32]: array([ 1.01,  0.  ,  1.9 ,  0.  , -2.45,  0.  ,  0.2 ,  0.3 ])
In [33]: arr[mask0]
Out[33]: array([0., 0.])

由于您希望其他所有内容都为0,因此让初始数组为零:

In [34]: res = np.zeros_like(arr)

现在涂上3个口罩:

In [35]: res[mask1] = 3
In [36]: res[mask2] = 2
In [37]: res[mask0] = np.nan
In [38]: res
Out[38]: 
array([[ 2.,  3.,  2.,  3.,  3.],
       [ 2.,  0., nan,  0.,  2.],
       [nan,  2.,  2.,  0.,  3.]])

我可以将蒙版应用到arr

In [40]: arr[mask1] = 3        # np.where(mask1, 3, arr) should also work
In [41]: arr[mask2] = 2
In [42]: arr[mask0] = np.nan
In [43]: arr
Out[43]: 
array([[2. , 3. , 2. , 3. , 3. ],
       [2. , 2.6, nan, 4.7, 2. ],
       [nan, 2. , 2. , 4.2, 3. ]])

我仍然必须使用一些逻辑来组合掩码以标识应该为0的插槽。