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

use*_*121 3 python numpy matrix multidimensional-array

我有一个2D numpy数组,其中包含'n'个唯一值.我想生成一个二进制矩阵,其中所有值都替换为"零",并且我指定的值被指定为"一".

例如,我有一个如下数组,我想要为35的所有实例分配'one':

array([[12, 35, 12, 26],
       [35, 35, 12, 26]])
Run Code Online (Sandbox Code Playgroud)

我想获得以下输出:

array([[0, 1, 0, 0],
       [1, 1, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

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

yuj*_*uji 9

import numpy as np
x = np.array([[12, 35, 12, 26], [35, 35, 12, 26]])
(x == 35).astype(int)
Run Code Online (Sandbox Code Playgroud)

会给你:

array([[0, 1, 0, 0],
       [1, 1, 0, 0]])
Run Code Online (Sandbox Code Playgroud)

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

  • @ kmario23并将`numexpr`模块用于大型数组 - `import numexpr as ne; ne.evaluate('x == 35').astype(np.uint8)`进一步加速.此外,我们可以只查看那些 - "(x == 35).view(np.uint8)"等,如果视图还可以的话. (2认同)

kma*_*o23 5

与所有其他解决方案相比,一种更优雅的方法是仅使用 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]])
Run Code Online (Sandbox Code Playgroud)

np.isin()会返回一个布尔型掩码,其True值带有35原始数组和False其他位置中给定元素(此处)的位置。


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

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

标杆管理

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

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

如果您要使用真正的战马,请numexpr在中使用:

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

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


最后,如果视图还可以,我们可以使用NumPy方法本身获得如此疯狂的加速。

In [13]: %timeit (x == 35).view(np.uint8)
20.1 ms ± 93.2 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [15]: %timeit np.isin(x, 35).view(np.uint8)
30.2 ms ± 1.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)

(再次,感谢@Divakar提到了这些超级不错的技巧!)