假设我有一个数字数组
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))
似乎可能有一些奇特的 numpy 方法可以做到这一点。有人知道吗?
最佳答案
一种方法是使用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
都非常长 - 可能会首选迭代方法来避免内存中出现大型临时数组。
关于python - 减少超出范围的数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28840360/