【问题标题】:How can I do this python list comprehension in NumPy?如何在 NumPy 中执行此 python 列表理解?
【发布时间】:2016-11-17 20:47:53
【问题描述】:

假设我有一个值数组r,其范围从01。我想删除所有远离中位数阈值的值。我们在这里假设该阈值为0.5len(r) = 3000。然后为了屏蔽掉这个范围之外的所有值,我可以做一个简单的列表理解,我喜欢:

mask = np.array([ri < np.median(r)-0.5 or ri > np.median(r)+0.5 for ri in r])

如果我在上面使用计时器:

import time
import numpy as np

start = time.time()
r = np.random.random(3000)
m = np.median(r)
maxr,minr = m-0.5, m+0.5
mask = [ri<minr or ri>maxr for ri in r]
end = time.time()
print('Took %.4f seconds'%(end-start))

&gt;&gt;&gt; Took 0.0010 seconds

有没有更快的方法来完成这个列表理解并使用NumPy 制作掩码?


编辑:

我尝试了以下几个建议,包括:

  • 逐元素或运算符:(r&lt;minv) | (r&gt;maxv)

  • 一个 Numpy 逻辑或:r[np.logical_or(r&lt;minr, r&gt;maxr)]

  • 绝对差值布尔数组:abs(m-r) &gt; 0.5

这是每个人在运行 300 次后的平均时间:

Python list comprehension: 0.6511 ms
Elementwise or: 0.0138 ms
Numpy logical or: 0.0241 ms
Absolute difference: 0.0248 ms

如您所见,逐元素 Or 总是最快的,几乎是两倍(不知道如何随数组元素缩放)。谁知道。

【问题讨论】:

  • [ri&lt;-maxr 是这里的减号错字吗?
  • @ayhan 是的,对不起,最小值和最大值也失败了
  • 改用(r &gt; maxr) | (r &lt; minr)| 用于元素或。
  • 我相信 |np.logical_or 使用相同的方法,所以差异应该源于其他东西 i.imgur.com/7Y4frKM.png abs 可能需要更长的时间,但你是对的。
  • @ayhan 不,他们不一样。 | is bitwise_or。它们仅在布尔数组上以相同的方式工作。我的性能测试结果和你一样。但我相信这取决于硬件。

标签: python arrays numpy masking bitmask


【解决方案1】:

一个班轮...

new_mask = abs(np.median(r) - r) > 0.5

【讨论】:

  • 在需要分布尾部时非常有用。我喜欢清晰。
【解决方案2】:

您可以使用 numpy 条件选择来创建新数组,而无需这些值。

start = time.time()
m = np.median(r)
maxr,minr = m-0.5, m+0.5
filtered_array = r[ (r < minr) | (r > maxr) ]
end = time.time()
print('Took %.4f seconds'%(end-start))

filtered_arrayr 的切片,没有掩码值(所有值稍后将被 filtered_array 中已移除的掩码移除)。

更新:使用@ayhan 建议的更短语法。

【讨论】:

  • 这是最快的,谢谢。尽管您使用 np.logical_or() 的原始答案较慢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
  • 2020-03-12
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多