【问题标题】:vectorized sum of array according to indices of second array [duplicate]根据第二个数组的索引的数组的向量化总和[重复]
【发布时间】:2017-06-27 09:44:06
【问题描述】:

我有一个空数组:

empty = np.array([0, 0, 0, 0, 0])

与我的空数组中的位置相对应的索引数组

ind = np.array([2, 3, 1, 2, 4, 2, 4, 2, 1, 1, 1, 2])

和一个值数组

val = np.array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

我想根据'ind'给出的位置将'val'中的值添加到'empty'中。

非向量化解是:

for i, v in zip(ind, val): maps[i] += v
>>> maps
[ 0.  4.  5.  1.  2.]

我的实际数组是多维的并且很长,所以我有一个需要速度我真的想要一个矢量化解决方案,或者一个非常快的解决方案。

注意这不起作用:

maps[ind] += val
>>> maps
array([ 0.,  1.,  1.,  1.,  1.])

如果有一个可以在 python 2.7、3.5、3.6 中运行且没有问题的解决方案,我将不胜感激

【问题讨论】:

  • 确实是重复的。但我的问题标题更清楚

标签: python performance python-2.7 numpy vectorization


【解决方案1】:

您要查找的是e=np.bincount(ind, weights=val, minlength=n),其中n 是空数组的长度。这样你就不必初始化empty。您只需第一次执行此操作,之后您可以执行e+=np.bincount(ind, weights=val)

这至少比np.add.at快两倍:

%timeit np.bincount(ind, val, minlength=empty.size)
The slowest run took 12.69 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 2.05 µs per loop

%timeit np.add.at(empty, ind, val)
The slowest run took 2822.05 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 4.32 µs per loop

对于多维索引,可以这样做:

np.bincount(np.ravel_multi_index(ind, empty.shape), np.ravel(val), minlength=empty.size).reshape(empty.shape)

我不确定如何使用 np.add.at 来比较速度

【讨论】:

  • 如果 empty 和 val 是多维的,这应该工作吗?例如:empty.shape = (5,2,2) 和 val.shape = (10,2,2)?
  • 不像写的那样,你需要ravel_multi_index你的索引,ravelemptyval,和reshape最终结果。那时np.add.at 可能更快,或者至少更pythonic。但这不是你问的:)
  • 这不是我问的,你是对的。我没想到这会很重要。不过谢谢!
  • 添加了一个带有bincount 的实现。我无法让np.add.at 获取多个索引,你有它的工作代码吗?
【解决方案2】:

这基本上是一个histogram,所以在一维的情况下:

h, b = np.histogram(ind, bins=np.arange(empty.size+1), weights=val)
empty += h

当然你可以省略第二条语句,以防空只有零。

【讨论】:

  • 我删除了关于np.bincount的部分,因为@DanielForsman已经给出了答案,我是在编辑后才看到的。
【解决方案3】:

您可以使用与empty[ind] += val 等效的np.add.at,除了为多次索引的元素累积结果,为您提供这些索引的累积结果。

>>> np.add.at(empty, ind, val)
>>> empty
array([0, 4, 5, 1, 2])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多