我有一个包含随机分布的1和0的numpy数组。我想将所有的1替换为0,所有的0替换为1。
arr[arr == 0] = 2
arr[arr == 1] = 0
arr[arr == 2] = 1
目前我需要使用一个临时值(在这种情况下为2),以避免所有的0变成1,然后使整个数组都充满了0。 是否有更优雅/高效的方法来解决这个问题?
在覆盖任何值之前,您可以计算并存储布尔索引器:
ones = a == 1
zeros = a == 0
a[ones] = 0
a[zeros] = 1
0
和1
以外的值。
np.where
:a = np.where(ones, 0, np.where(zeros, 1, a))
>>> a
array([[1, 0, 0, 1],
[1, 1, 1, 0]])
>>> (a-1)*-1
array([[0, 1, 1, 0],
[0, 0, 0, 1]])
针对您的特定值,进行按位异或 1 的操作。
In [19]: a=np.random.randint(2, size=10)
In [18]: a
Out[18]: array([1, 1, 1, 1, 1, 1, 0, 0, 1, 1])
In [19]: a^1
Out[19]: array([0, 0, 0, 0, 0, 0, 1, 1, 0, 0])
In [62]: convert=np.array([1,0])
In [63]: convert[a]
Out[63]: array([0, 0, 0, 0, 0, 0, 1, 1, 0, 0])
>>> a
array([[1, 0, 0, 1],
[1, 1, 1, 0]])
numpy.where
。>>> np.where(a == 0, 1, 0) # read as (if, then, else)
array([[0, 1, 1, 0],
[0, 0, 0, 1]])
a
并进行一些类型转换。>>> (~a.astype(bool)).astype(int)
array([[0, 1, 1, 0],
[0, 0, 0, 1]])
>>> a = np.eye(1000, dtype=int)
>>> %timeit np.where(a == 0, 1, 0)
1.56 ms ± 2.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit (~a.astype(bool)).astype(int)
1.74 ms ± 87.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit a^1 # Tls Chris
920 µs ± 31.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit np.array([1, 0])[a] # Tls Chris
1.4 ms ± 102 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit (a - 1)*-1 # sacul
1.57 ms ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit 1 - a # user3483203
905 µs ± 2.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
a^1
和1-a
干净、优雅且快速。使用np.where
可以处理任何你想要交换的值。import numba as nb
import numpy as np
@nb.njit()
def nb_where(arr):
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
if arr[i,j]==1:
arr[i,j] = 0
else:
arr[i,j] = 1
return arr
Timings
a = np.eye(1000, dtype=int)
np.where(a == 0, 1, 0) #timgeb -> 2.06ms
a^1 #Tls Chris -> 1.31ms
nb_where(a) -> 152 µs
(a - 1) * -1
可以分配为-a + 1
或1 - a
,这样更清晰明了(也更快)。 - user3483203