减少范围内的数组

时间:2015-03-03 19:32:27

标签: python numpy

说我有一组数字

np.array(([1, 4, 2, 1, 2, 5]))

我想计算切片列表中的总和

((0, 3), (2, 4), (2, 6))

给予

[(1 + 4 + 2), (2 + 1), (2 + 1 + 2 + 5)]

在numpy中有一个很好的方法吗?

寻找与

相当的东西
def reduce(a, ranges):
  np.array(list(np.sum(a[low:high]) for (low, high) in ranges))

似乎可能有一些花哨的方式来做到这一点。谁知道?

1 个答案:

答案 0 :(得分:1)

一种方法是使用np.add.reduceat。如果a是值数组[1, 4, 2, 1, 2, 5]

>>> np.add.reduceat(a, [0,3, 2,4, 2])[::2]
array([ 7,  3, 10], dtype=int32)

此处切片索引在列表中传递并相加以返回[ 7, 1, 3, 2, 10](即a[0:3]a[3:]a[2:4]a[4:]的总和,a[2:])。我们只想要这个数组中的所有其他元素。


更长的替代方法......

切片长度不同的事实使得在NumPy中进行矢量化变得有点棘手,但这是解决问题的一种方法。

给出一组值和一组切片......

a = np.array(([1, 4, 2, 1, 2, 5]))
slices = np.array([(0, 3), (2, 4), (2, 6)])

...创建一个类似于蒙版的数组z,对于每个切片,它将用于“清空”来自a的值,我们不想求和:

z = np.zeros((3, 6))
s1 = np.arange(6) >= s[:, 0][:,None]
s2 = np.arange(6) < s[:, 1][:,None]
z[s1 & s2] = 1

然后你可以这样做:

>>> (z * a).sum(axis=1)
array([  7.,   3.,  10.])

快速%timeit显示这比列表理解略快,即使我们必须构建zz * a。如果slices的长度为3000,则此方法的速度提高约40倍。

但请注意,数组z的形状为(len(slices), len(a)),如果aslices都非常长,则可能不太实际 - 迭代方法可能是首选避免在内存中使用大型临时数组。