如何在没有循环的情况下将负元素转换为零?

Rug*_*rra 44 python numpy

如果我有像这样的数组

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)
  1. 1.38629984856
  2. 0.516846179962 < - a.clip(min = 0);
  3. 0.615426063538
  4. 0.944557905197
  5. 51.7364809513

Rug*_*rra 84

a = a.clip(min=0)
Run Code Online (Sandbox Code Playgroud)

  • wiso,我想你找到了最快的方法。`%timeit a.clip(min=0,out=a)` 每个循环花费 5.65 微秒。`%timeit np.where(a&gt;0,a,0)` 每个循环花费 24 微秒,`%timeit a[a&lt;0]=0` 每个循环花费 11.6 微秒。 (2认同)
  • 也可以将“ np.clip(lst,a_min = 0,a_max = None)”用于python列表。 (2认同)

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)

  • 它不适用于多个维度。 (2认同)

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运行测试,预先计算<和>,因为其中一些就地修改,这将极大地影响结果.在所有情况下anp.random.uniform(-1, 1, 20000000),但有已经被设置为0,但底片L = a < 0G = a > 0之前a被改变.的clip,因为它没有得到使用相对负面影响LG(但是这些计算在同一台机器上只花了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倍.