17

accumarraynumpy でMATLAB の高速なソリューションを探しています。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])

結果は

array([13, 25, 17])

これまでに行ったこと:ここのレシピ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

次に、ここでより速く動作するはずのソリューションを使用しようとしましたが、正しく動作しません:

accum_np(accmap, a)
# array([  1.,   2.,  12.,  13.,  17.,  10.])

このような累積を行うことができる組み込みの numpy 関数はありますか? または他の推奨事項はありますか?

4

7 に答える 7

8

パーティーに遅れましたが...

@Jamieが言うように、合計の場合np.bincountは高速でシンプルです。ただし、より一般的な場合、ufuncsなどの他の場合maximumは、 メソッドを使用できますnp.ufunc.at

これをMatlabのようなインターフェースにカプセル化した要点をまとめました[代わりに以下のリンクを参照してください]。また、'last'and'first'関数を提供するために繰り返されるインデックス作成ルールを利用し、Matlab とは異なり、適切に'mean'最適化されています ( Matlab でのaccumarraywith@meanの呼び出しは、グループごとに非組み込み関数を実行するため、非常に遅くなりますが、これはばかげています)。

私は要点を特にテストしていないことに注意してください。ただし、追加の機能とバグ修正で将来的に更新されることを願っています.

2015 年 5 月/6 月の更新:実装を作り直しました。現在、ml31415/numpy-groupiesの一部として利用でき、PyPi ( pip install numpy-groupies) で利用できます。ベンチマークは次のとおりです (最新の値については、github リポジトリを参照してください)...

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.

ここでは100,000、 から一様に選択されたインデックスを使用しています[0, 1000)。具体的には、値の約 25% が0(ブール演算で使用するため) であり、残りは に均一に分散され[-50,25)ます。10回の繰り返しのタイミングが示されています。

  • purepy - 純粋な python だけを使用し、部分的に に依存していitertools.groupbyます。
  • np-grouploop -numpyに基づいて値をソートするために使用しidx、次に を使用splitして個別の配列を作成し、これらの配列をループして、numpy各配列に関連する関数を実行します。
  • np-ufuncat - numpy の github リポジトリで作成した問題numpy ufunc.atで説明されているように、本来よりも遅いメソッドを使用します。
  • np-optimisied - カスタムインデックス作成/その他のトリックを使用して、上記の 2 つの実装を打ち負かします (依存するものをnumpy除く)。min max produfunc.at
  • パンダ-pd.DataFrame({'idx':idx, 'vals':vals}).groupby('idx').sum()など

一部のno-impls は不当である可能性があることに注意してください。

github で説明されてaccumarrayいるように、、 、、および. また、多次元インデックスにも対応しています。nannansumsortrsortarray

于 2015-02-10T20:18:38.653 に答える
4

accumarray の実装を作成しscipy.weave、github にアップロードしました: https://github.com/ml31415/numpy-groupies

于 2013-05-31T19:24:13.937 に答える
2

これは、pandas DataFrame を使用して 1 行で実行できます。

In [159]: df = pd.DataFrame({"y":np.arange(1,11),"x":[0,1,0,0,0,1,1,2,2,1]})

In [160]: df
Out[160]: 
   x   y
0  0   1
1  1   2
2  0   3
3  0   4
4  0   5
5  1   6
6  1   7
7  2   8
8  2   9
9  1  10

In [161]: pd.pivot_table(df,values='y',index='x',aggfunc=sum)
Out[161]: 
    y
x    
0  13
1  25
2  17

pivot_table特定の列をインデックスと値として使用し、新しい DataFrame オブジェクトを取得するように に指示できます。集計関数を合計として指定すると、結果は Matlab の accumarray と同じになります。

于 2018-05-08T12:02:58.640 に答える
0

以下はどうでしょう。

import numpy

def accumarray(a, accmap):

    ordered_indices = numpy.argsort(accmap)

    ordered_accmap = accmap[ordered_indices]

    _, sum_indices = numpy.unique(ordered_accmap, return_index=True)

    cumulative_sum = numpy.cumsum(a[ordered_indices])[sum_indices-1]

    result = numpy.empty(len(sum_indices), dtype=a.dtype)
    result[:-1] = cumulative_sum[1:]
    result[-1] = cumulative_sum[0]

    result[1:] = result[1:] - cumulative_sum[1:]

    return result
于 2013-05-31T13:13:33.587 に答える