除了一个特定值之外,如何将numpy数组中的所有值替换为零?

时间:2018-01-17 19:04:49

标签: python numpy matrix multidimensional-array

我有一个2D numpy数组,其中包含'n'个唯一值。 我想生成一个二进制矩阵,其中所有值都替换为 'zero'和我指定的值被指定为'one'。

例如,我有一个如下数组,我想要所有实例 35被指定为'one':

array([[12, 35, 12, 26],
       [35, 35, 12, 26]])

我想获得以下输出:

array([[0, 1, 0, 0],
       [1, 1, 0, 0]])

在Python中最有效的方法是什么?

6 个答案:

答案 0 :(得分:8)

import numpy as np
x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
(x == 35).astype(int)

会给你:

array([[0, 1, 0, 0],
       [1, 1, 0, 0]])

numpy中的==运算符执行逐元素比较,当将布尔值转换为整数时,True编码为1,False编码为0。

答案 1 :(得分:4)

import numpy as np
x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
(x == 35) + 0
  

数组([[0,1,0,0],          [1,1,0,0]])

答案 2 :(得分:4)

与所有其他解决方案相比,更优雅的方法是使用np.isin()

>>> arr
array([[12, 35, 12, 26],
       [35, 35, 12, 26]])

# get the result as binary matrix
>>> np.isin(arr, 35).astype(np.uint8)
array([[0, 1, 0, 0],
       [1, 1, 0, 0]])

np.isin()将返回带有True值的布尔掩码,其中给定元素(此处为35)出现在原始数组中,{{1在其他地方。

另一种变体是使用数据类型为np.asarray()np.uint8转换布尔结果,以提高速度:

False

基准

通过将布尔结果显式地转换为uint8,我们可以获得超过 3x更好的性能。 (感谢@Divakar指出这一点!)见下面的时间:

In [18]: np.asarray(np.isin(x, 35), dtype=np.uint8)
Out[18]: 
array([[0, 1, 0, 0],
       [1, 1, 0, 0]], dtype=uint8)

如果您想要真正的战马,请使用numexpr,如下所示:

# setup (large) input array
In [3]: x = np.arange(25000000)
In [4]: x[0] = 35
In [5]: x[1000000] = 35
In [6]: x[2000000] = 35
In [7]: x[-1] = 35
In [8]: x = x.reshape((5000, 5000))

# timings
In [20]: %timeit np.where(x==35, 1, 0)
427 ms ± 25.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [21]: %timeit (x == 35) + 0
450 ms ± 72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [22]: %timeit (x == 35).astype(np.uint8)
126 ms ± 37.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

# the fastest choice to go for!    
In [23]: %timeit np.isin(x, 35).astype(np.uint8)
115 ms ± 2.21 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [24]: %timeit np.asarray(np.isin(x, 35), dtype=np.uint8)
117 ms ± 2.91 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

这是 ca。比使用基于NumPy的计算的最慢方法快20倍

最后,如果 views 没问题,我们可以使用NumPy方法获得如此疯狂的加速。

In [8]: import numexpr as ne

In [9]: %timeit ne.evaluate("x==35").astype(np.uint8)
23 ms ± 2.69 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

(再次感谢@Divakar提及these super nice tricks!)

答案 3 :(得分:2)

如果你的数组是一个numpy数组,那么你可以使用数组上的'=='运算符来返回一个布尔数组。然后使用astype功能将其转换为0和1。

import numpy as np
my_array = np.array([[12, 35, 12, 26],
                     [35, 35, 12, 26]])

indexed = (my_array == 35).astype(int)

print indexed

答案 4 :(得分:2)

我喜欢@yuji approach。很优雅!

为了多样性,这里是另一个需要大量劳动的答案......

>>> from numpy import np
>>> x = np.array([[12, 35, 12, 26],[35, 35, 12, 26]])
>>> x
array([[12, 35, 12, 26],
       [35, 35, 12, 26]])
>>> y=np.zeros(x.shape)
>>> y[np.where(x==35)] = np.ones(len(np.where(x==35)[0]))
>>> y
array([[ 0.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.]])
>>> 

答案 5 :(得分:2)

另一种选择是使用np.where;这个解决方案慢于@yuji's solution(参见下面的时间),但如果你想做任何其他事情,除了放入零和一个(见下面的例子),它会更灵活。

import numpy as np
x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
np.where(x==35, 1, 0)

产生

array([[0, 1, 0, 0],
       [1, 1, 0, 0]])

可以像那样读取它,其中x等于35放在1中,其他地方插入0

如上所述,您现在具有很大的灵活性,例如,还要做以下事情:

np.where(x==35, np.sqrt(x), x - 3)

array([[  9.        ,   5.91607978,   9.        ,  23.        ],
       [  5.91607978,   5.91607978,   9.        ,  23.        ]])

所以在x等于35的任何地方,您都会获得平方根,并从所有其他值中减去3

时序:

%timeit np.where(x==35, 1, 0)
100000 loops, best of 3: 5.85 µs per loop

%timeit (x == 35).astype(int)
100000 loops, best of 3: 3.23 µs per loop

%timeit np.isin(x, 35).astype(int)
10000 loops, best of 3: 18.7 µs per loop

%timeit (x == 35) + 0
100000 loops, best of 3: 5.85 µs per loop