【问题标题】:Numpy subset array between first and last occurence of logical expression match逻辑表达式匹配的第一次和最后一次出现之间的 Numpy 子集数组
【发布时间】:2014-03-18 11:38:34
【问题描述】:

我有一个 numpy 数组,它是一个向量(1 x n)。我想在它遇到布尔表达式(大于某个数字)的第一次和最后一次出现之间对其进行子集化。

I.E.类似于:

positions = numpy.where(myArray >= value)[0]
subset = myArray[positions[0]:positions[-1]+1]

这是一种解决方案,但据我了解,这将涉及在整个数组中搜索两次以检索 positions 结果。 myArray 可以很大,有没有其他解决办法?

【问题讨论】:

  • 访问数组的第一个和最后一个元素不涉及任何搜索,它已经知道这些元素在哪里。这几乎是您可以做到这一点的最有效方式。至少据我所知。
  • 如所列,这将截断最后一个值,例如,如果您的数组是 arr = np.array([0,1,2,0]) 并且截断是 1 你想要 np.array([1,2]) 还是 np.array([1])
  • @M4rtini; where 和布尔索引确实需要搜索。
  • @Ophion,是的,我错过了。我调整了代码 - 我想要完整的结果

标签: python arrays numpy indexing


【解决方案1】:

让我们列出一些方法:

def original(arr, val):
    pos = np.where(arr>=val)[0]
    return arr[pos[0]:pos[-1]+1]

def with_argmax(arr, val):
    pos = (arr>=val)
    return arr[pos.argmax():-pos[::-1].argmax() or None]

设置一个中等大小的数组和几个要剪辑的值:

arr = np.ones(1E5)
arr[:300] = 0; arr[-300:]=0

时间安排:

%timeit original(arr,1)
1000 loops, best of 3: 504 µs per loop

%timeit with_argmax(arr,1)
1000 loops, best of 3: 297 µs per loop

相同的数组大小,有更多的值要剪辑:

arr = np.ones(1E5)
arr[:2E4] = 0; arr[-2E4:]=0

时间安排:

%timeit original(arr,1)
1000 loops, best of 3: 528 µs per loop

%timeit with_argmax(arr,1)
1000 loops, best of 3: 296 µs per loop

您真正想要的是“查找第一个非零元素”例程,该例程当前不在 numpy 中,但针对 numpy 2.0。更多信息可以在here找到。

【讨论】:

  • 很好的答案。我会试试这个并报告
  • @jramm 因为 searchsorted 使用二进制搜索,所以未排序数组的结果是不可预测的。如果这还不够快,我相信继续的最佳方法可能是创建某种块算法,该算法迭代数组的某些部分,如果 chunk[chunk.argmax()]!=1 转到下一个块,否则停止。这将防止 argmax 必须遍历整个数组两次。
  • 感谢 Ophion。答案很棒。较小的性能提升并不是那么理想(因此您的 with_argmax 代码很好) - 想法是替换生成器表达式而不损失性能,以便它可以被“cythonised”。现在这一切都实现了!
猜你喜欢
  • 2022-11-23
  • 2014-06-07
  • 1970-01-01
  • 2022-08-18
  • 2017-08-23
  • 1970-01-01
  • 2016-10-14
  • 2022-08-13
  • 1970-01-01
相关资源
最近更新 更多