说我有一组数字
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))
似乎可能有一些花哨的方式来做到这一点。谁知道?
答案 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
显示这比列表理解略快,即使我们必须构建z
和z * a
。如果slices
的长度为3000,则此方法的速度提高约40倍。
但请注意,数组z
的形状为(len(slices), len(a))
,如果a
或slices
都非常长,则可能不太实际 - 迭代方法可能是首选避免在内存中使用大型临时数组。