Python 如何在没有循环的情况下将负元素转换为零?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3391843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to transform negative elements to zero without a loop?
提问by Ruggero Turra
If I have an array like
如果我有一个像
a = np.array([2, 3, -1, -4, 3])
I want to set all the negative elements to zero: [2, 3, 0, 0, 3]. How to do it with numpy without an explicit for? I need to use the modified ain a computation, for example
我想所有的消极因素设置为零[2, 3, 0, 0, 3]。如何在没有明确 for 的情况下用 numpy 做到这一点?例如,我需要a在计算中使用修改后的
c = a * b
where bis another array with the same length of the original a
哪里b是另一个与原始数组长度相同的数组a
Conclusion
结论
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)
- 1.38629984856
- 0.516846179962 <- faster a.clip(min=0);
- 0.615426063538
- 0.944557905197
- 51.7364809513
- 1.38629984856
- 0.516846179962 <- 更快的 a.clip(min=0);
- 0.615426063538
- 0.944557905197
- 51.7364809513
采纳答案by Ruggero Turra
a = a.clip(min=0)
回答by David Z
I would do this:
我会这样做:
a[a < 0] = 0
If you want to keep the original aand only set the negative elements to zero in a copy, you can copy the array first:
如果想保留原样a,只在副本中将负元素置零,可以先复制数组:
c = a.copy()
c[c < 0] = 0
回答by coderforlife
Another trick is to use multiplication. This actually seems to be much faster than every other method here. For example
另一个技巧是使用乘法。这实际上似乎比这里的所有其他方法都要快得多。例如
b = a*(a>0) # copies data
or
或者
a *= (a>0) # in-place zero-ing
I ran tests with timeit, pre-calculating the the < and > because some of these modify in-place and that would greatly effect results. In all cases awas np.random.uniform(-1, 1, 20000000)but with negatives already set to 0 but L = a < 0and G = a > 0before awas changed. The clipis relatively negatively impacted since it doesn't get to use Lor G(however calculating those on the same machine took only 17ms each, so it is not the major cause of speed difference).
我用 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`)
When choosing to penalize the in-place methods instead of clip, the following timings come up:
选择惩罚就地方法而不是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
Non in-place methods are penalized by 20ms (the time required to calculate a>0or a<0) and the in-place methods are penalize 73-83 ms (so it takes about 53-63ms to do b.copy()).
非就地方法会受到 20 毫秒的惩罚(计算a>0或所需的时间a<0),而就地方法会受到 73-83 毫秒的惩罚(因此大约需要 53-63 毫秒才能完成b.copy())。
Overall the multiplication methods are much faster than clip. If not in-place, it is 1.5xfaster. If you can do it in-place then it is 2.75xfaster.
总体而言,乘法方法比 快得多clip。如果没有就地,它会快1.5 倍。如果您可以就地完成,那么速度会快2.75倍。
回答by Kris Stern
And just for the sake of comprehensiveness, I would like to add the use of the Heaviside function (or a step function) to achieve a similar outcome as follows:
为了全面起见,我想添加使用 Heaviside 函数(或阶跃函数)来实现类似的结果,如下所示:
Let say for continuity we have
假设我们有连续性
a = np.array([2, 3, -1, -4, 3])
Then using a step function np.heaviside()one can try
然后使用阶跃函数np.heaviside()可以尝试
b = a * np.heaviside(a, 0)
Note something interesting in this operation because the negative signs are preserved! Not very ideal for most situations I would say.
请注意此操作中的一些有趣之处,因为保留了负号!对于大多数情况我会说不是很理想。
This can then be corrected for by
然后可以通过以下方式更正
b = abs(b)
So this is probably a rather long way to do it without invoking some loop.
因此,在不调用某些循环的情况下,这可能是一个相当长的方法。

