如果我有像这样的数组
a = np.array([2, 3, -1, -4, 3])
Run Code Online (Sandbox Code Playgroud)
我想将所有负面元素设置为零:[2, 3, 0, 0, 3].如何用numpy做一个没有明确的?例如,我需要a在计算中使用修改
c = a * b
Run Code Online (Sandbox Code Playgroud)
where b是另一个与原始长度相同的数组a
import numpy as np
from time import time
a = np.random.uniform(-1, 1, 20000000)
t = time(); b = np.where(a>0, a, 0); print ("1. ", time() - t)
a = np.random.uniform(-1, 1, 20000000)
t = time(); b = a.clip(min=0); print ("2. ", time() - t)
a = np.random.uniform(-1, 1, 20000000)
t = time(); a[a < 0] = 0; print ("3. ", time() - t)
a = np.random.uniform(-1, 1, 20000000)
t = time(); a[np.where(a<0)] = 0; print ("4. ", time() - t)
a = np.random.uniform(-1, 1, 20000000)
t = time(); b = [max(x, 0) for x in a]; print ("5. ", time() - t)
Run Code Online (Sandbox Code Playgroud)
Rug*_*rra 84
a = a.clip(min=0)
Run Code Online (Sandbox Code Playgroud)
Dav*_*d Z 14
我会这样做:
a[a < 0] = 0
Run Code Online (Sandbox Code Playgroud)
如果要保留原始文件a并仅在副本中将负元素设置为零,则可以先复制数组:
c = a.copy()
c[c < 0] = 0
Run Code Online (Sandbox Code Playgroud)
cod*_*ife 10
另一个技巧是使用乘法.这实际上似乎比这里的其他方法快得多.例如
b = a*(a>0) # copies data
Run Code Online (Sandbox Code Playgroud)
要么
a *= (a>0) # in-place zero-ing
Run Code Online (Sandbox Code Playgroud)
我使用timeit运行测试,预先计算<和>,因为其中一些就地修改,这将极大地影响结果.在所有情况下a是np.random.uniform(-1, 1, 20000000),但有已经被设置为0,但底片L = a < 0和G = a > 0之前a被改变.的clip,因为它没有得到使用相对负面影响L或G(但是这些计算在同一台机器上只花了17MS每一个,所以它不是速度差的主要原因).
%timeit b = np.where(G, a, 0) # 132ms copies
%timeit b = a.clip(min=0) # 165ms copies
%timeit a[L] = 0 # 158ms in-place
%timeit a[np.where(L)] = 0 # 122ms in-place
%timeit b = a*G # 87.4ms copies
%timeit np.multiply(a,G,a) # 40.1ms in-place (normal code would use `a*=G`)
Run Code Online (Sandbox Code Playgroud)
当选择惩罚就地方法而不是时clip,会出现以下时间:
%timeit b = np.where(a>0, a, 0) # 152ms
%timeit b = a.clip(min=0) # 165ms
%timeit b = a.copy(); b[a<0] = 0 # 231ms
%timeit b = a.copy(); b[np.where(a<0)] = 0 # 205ms
%timeit b = a*(a>0) # 108ms
%timeit b = a.copy(); b*=a>0 # 121ms
Run Code Online (Sandbox Code Playgroud)
非就地方法会受到20ms的惩罚(计算所需的时间a>0或者a<0),而就地方法会受到73-83 ms的惩罚(因此需要大约53-63ms b.copy()).
总的来说,乘法方法要快得多clip.如果不是就地,则速度提高1.5倍.如果你可以就地做到那么它快2.75倍.