如果我有像
这样的数组a = np.array([2, 3, -1, -4, 3])
我想将所有负面元素设置为零:[2, 3, 0, 0, 3]
。如何用numpy做一个没有明确的?我需要在计算中使用修改后的a
,例如
c = a * b
其中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)
答案 0 :(得分:76)
a = a.clip(min=0)
答案 1 :(得分:12)
我会这样做:
a[a < 0] = 0
如果您想保留原始a
并且只在副本中将负元素设置为零,则可以先复制数组:
c = a.copy()
c[c < 0] = 0
答案 2 :(得分:7)
另一个技巧是使用乘法。这实际上似乎比这里的其他方法快得多。例如
b = a*(a>0) # copies data
或
a *= (a>0) # in-place zero-ing
我用timeit运行测试,预先计算&lt;和&gt;因为其中一些就地修改并且会极大地影响结果。在所有情况下,a
均为np.random.uniform(-1, 1, 20000000)
但已将负数设置为0,但在L = a < 0
更改之前G = a > 0
和a
。 clip
受到相对负面影响,因为它无法使用L
或G
(但是在同一台机器上计算它们每个只花费17毫秒,因此它不是主要原因速差)。
%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`)
当选择惩罚就地方法而不是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
非就地方法会受到20ms的惩罚(计算a>0
或a<0
所需的时间),就地方法会受到73-83 ms的惩罚(因此需要大约53-63ms)做b.copy()
)。
总体而言,乘法方法比clip
快得多。如果不是就地,则 1.5x 更快。如果你可以就地进行,那么 2.75x 会更快。
答案 3 :(得分:4)
使用where
a[numpy.where(a<0)] = 0
答案 4 :(得分:0)
为了全面起见,我想添加Heaviside函数(或step函数)的使用,以实现类似的结果,如下所示:
让我们说连续性
[Authorize]
public class NotifyHub : Hub {
private readonly MyApi _api;
public NotifyHub(MyApi api) {
_api = api;
_api.Notification += OnNotification;
}
private async void OnNotification(object sender, Notification notification) {
// can access Context.User here
await Clients.All.SendAsync("Notification", notification);
}
}
然后使用步进功能np.heaviside()
可以尝试
a = np.array([2, 3, -1, -4, 3])
请注意此操作中的一些有趣内容,因为负号得以保留!我会说,对于大多数情况不是很理想。
然后可以通过以下方式更正
b = a * np.heaviside(a, 0)
因此,在不调用某些循环的情况下,这样做可能是很长的路要走。