在numpy中有一个等效的MATLAB准确吗?

pet*_*hor 15 python numpy accumulator

我正在寻找一个快速解决MATLAB的accumarraynumpy问题.的accumarray累积,其属于同一索引的数组的元素.一个例子:

a = np.arange(1,11)
# array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
accmap = np.array([0,1,0,0,0,1,1,2,2,1])
Run Code Online (Sandbox Code Playgroud)

结果应该是

array([13, 25, 17])
Run Code Online (Sandbox Code Playgroud)

到目前为止我做了什么: 我已经accum这里配方中尝试了这个功能很好但很慢.

accmap = np.repeat(np.arange(1000), 20)
a = np.random.randn(accmap.size)
%timeit accum(accmap, a, np.sum)
# 1 loops, best of 3: 293 ms per loop
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用这里应该更快工作的解决方案,但它无法正常工作:

accum_np(accmap, a)
# array([  1.,   2.,  12.,  13.,  17.,  10.])
Run Code Online (Sandbox Code Playgroud)

是否有内置的numpy功能可以像这样积累?还是其他任何建议?

Jai*_*ime 19

使用np.bincountweights可选的参数.在你的例子中,你会做:

np.bincount(accmap, weights=a)
Run Code Online (Sandbox Code Playgroud)

  • 哈!那很整齐 :) (3认同)

dan*_*man 5

迟到了,但......

正如@Jamie所说,对于求和的情况,np.bincount快速而简单.但是在更一般的情况下,对于其他ufuncs类似的情况,maximum可以使用该np.ufunc.at方法.

我总结了一个要点 [见下面的链接],它将其封装在类似Matlab的界面中.它还利用了重复索引规则提供'last''first'功能,而不像Matlab的,'mean'是合理的优化(调用accumarray@mean在Matlab实在是太慢了,因为它运行的每一个组,这是愚蠢的非内置函数).

请注意,我没有特别测试过要点,但希望将来能够通过额外的功能和错误修正来更新它.

更新2015年5月/ 6月:我已经重新设计了我的实现 - 它现在作为ml31415/numpy-groupies的一部分提供,可在PyPi(pip install numpy-groupies)上使用.基准如下(请参阅github repo获取最新值)......

function  pure-py  np-grouploop   np-ufuncat np-optimised    pandas        ratio
     std  1737.8ms       171.8ms     no-impl       7.0ms    no-impl   247.1: 24.4:  -  : 1.0 :  -  
     all  1280.8ms        62.2ms      41.8ms       6.6ms    550.7ms   193.5: 9.4 : 6.3 : 1.0 : 83.2
     min  1358.7ms        59.6ms      42.6ms      42.7ms     24.5ms    55.4: 2.4 : 1.7 : 1.7 : 1.0 
     max  1538.3ms        55.9ms      38.8ms      37.5ms     18.8ms    81.9: 3.0 : 2.1 : 2.0 : 1.0 
     sum  1532.8ms        62.6ms      40.6ms       1.9ms     20.4ms   808.5: 33.0: 21.4: 1.0 : 10.7
     var  1756.8ms       146.2ms     no-impl       6.3ms    no-impl   279.1: 23.2:  -  : 1.0 :  -  
    prod  1448.8ms        55.2ms      39.9ms      38.7ms     20.2ms    71.7: 2.7 : 2.0 : 1.9 : 1.0 
     any  1399.5ms        69.1ms      41.1ms       5.7ms    558.8ms   246.2: 12.2: 7.2 : 1.0 : 98.3
    mean  1321.3ms        88.3ms     no-impl       4.0ms     20.9ms   327.6: 21.9:  -  : 1.0 : 5.2 
Python 2.7.9, Numpy 1.9.2, Win7 Core i7.
Run Code Online (Sandbox Code Playgroud)

这里我们使用100,000统一选取的索引[0, 1000).具体而言,约25%的值0(用于bool操作),其余值均匀分布[-50,25).计时显示10次重复.

  • purepy - 只使用纯蟒蛇,部分依靠itertools.groupby.
  • np-grouploop - 用于numpy对值进行排序idx,然后用于split创建单独的数组,然后循环遍历这些数组,numpy为每个数组运行相关的函数.
  • np-ufuncat - 使用numpy ufunc.at比它应该更慢的方法 - 在我在numpy的github repo上创建的一个问题中被删除.
  • np-optimisied - 使用自定义numpy索引/其他技巧来击败上述两个实现(除了min max prod依赖ufunc.at).
  • 大熊猫 - pd.DataFrame({'idx':idx, 'vals':vals}).groupby('idx').sum()

请注意,其中一些no-impl可能是无根据的,但我还没有费心去让它们工作.

如在github解释的,accumarray现在支持nan-prefixed功能(例如nansum),以及,sort,rsort,和array.它也适用于多维索引.