替换 NumPy 数组中大于某个值的所有元素
- 2025-01-20 09:07:00
- admin 原创
- 86
问题描述:
我有一个 2D NumPy 数组。如何用值替换其中所有大于阈值T = 255
的值x = 255
?一种基于 for 循环的慢速方法是:
# arr = arr.copy() # Optionally, do not modify original arr.
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
if arr[i, j] > 255:
arr[i, j] = x
解决方案 1:
我认为最快和最简洁的方法是使用 NumPy 内置的 Fancy 索引。如果您有一个ndarray
命名的arr
,您可以>255
用值替换所有元素,x
如下所示:
arr[arr > 255] = x
我在我的计算机上用 500 x 500 的随机矩阵运行了这个程序,将所有 >0.5 的值替换为 5,平均花费 7.59 毫秒。
In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)
In [3]: timeit A[A > 0.5] = 5
100 loops, best of 3: 7.59 ms per loop
解决方案 2:
如果您想要一个包含每当result
的副本的新数组,否则:arr
`arr < 255`255
result = np.minimum(arr, 255)
更一般地,对于下限和/或上限:
result = np.clip(arr, 0, 255)
如果您只想访问超过 255 的值,或者更复杂的东西,@mtitan8 的答案更通用,但是np.clip
和np.minimum
(或np.maximum
)对于您的情况来说更好,速度更快:
In [292]: timeit np.minimum(a, 255)
100000 loops, best of 3: 19.6 µs per loop
In [293]: %%timeit
.....: c = np.copy(a)
.....: c[a>255] = 255
.....:
10000 loops, best of 3: 86.6 µs per loop
如果您想就地执行此操作(即修改arr
而不是创建result
),则可以使用out
以下参数np.minimum
:
np.minimum(arr, 255, out=arr)
或者
np.clip(arr, 0, 255, arr)
(out=
由于参数的顺序与函数的定义相同,因此名称是可选的。)
对于就地修改,布尔索引速度加快了很多(无需单独制作然后修改副本),但仍然不如minimum
:
In [328]: %%timeit
.....: a = np.random.randint(0, 300, (100,100))
.....: np.minimum(a, 255, a)
.....:
100000 loops, best of 3: 303 µs per loop
In [329]: %%timeit
.....: a = np.random.randint(0, 300, (100,100))
.....: a[a>255] = 255
.....:
100000 loops, best of 3: 356 µs per loop
为了进行比较,如果你想用最小值和最大值来限制你的值,那么clip
你就必须这样做两次,例如
np.minimum(a, 255, a)
np.maximum(a, 0, a)
或者,
a[a>255] = 255
a[a<0] = 0
解决方案 3:
我认为你可以使用以下where
功能以最快的速度实现这一点:
例如,在 numpy 数组中查找大于 0.2 的项目并将其替换为 0:
import numpy as np
nums = np.random.rand(4,3)
print np.where(nums > 0.2, 0, nums)
解决方案 4:
另一种方法是使用np.place
进行就地替换并与多维数组一起使用:
import numpy as np
# create 2x3 array with numbers 0..5
arr = np.arange(6).reshape(2, 3)
# replace 0 with -10
np.place(arr, arr == 0, -10)
解决方案 5:
您可以考虑使用numpy.putmask:
np.putmask(arr, arr>=T, 255.0)
以下是与 Numpy 内置索引的性能比较:
In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)
In [3]: timeit np.putmask(A, A>0.5, 5)
1000 loops, best of 3: 1.34 ms per loop
In [4]: timeit A[A > 0.5] = 5
1000 loops, best of 3: 1.82 ms per loop
解决方案 6:
您还可以使用&
,|
(和/或)以获得更大的灵活性:
5 至 10 之间的值:A[(A>5)&(A<10)]
大于 10 或小于 5 的值:A[(A<5)|(A>10)]
解决方案 7:
np.where() 效果很好!
np.where(arr > 255, 255, arr)
例子:
FF = np.array([[0, 0],
[1, 0],
[0, 1],
[1, 1]])
np.where(FF == 1, '+', '-')
Out[]:
array([['-', '-'],
['+', '-'],
['-', '+'],
['+', '+']], dtype='<U1')
解决方案 8:
假设你有一个numpy
数组,其中包含从 0 到 20 的值,并且你想用 0 替换大于 10 的数字
import numpy as np
my_arr = np.arange(0,21) # creates an array
my_arr[my_arr > 10] = 0 # modifies the value
请注意,这将修改原始数组,以避免覆盖原始数组,尝试使用
arr.copy()
创建原始数组的新分离副本并对其进行修改。
import numpy as np
my_arr = np.arange(0,21)
my_arr_copy = my_arr.copy() # creates copy of the orignal array
my_arr_copy[my_arr_copy > 10] = 0