7

このような配列があるとします

>>> a = np.arange(1,8).reshape((1,-1))
>>> a
array([[1, 2, 3, 4, 5, 6, 7]])

aの各アイテムについて、「次の4つのアイテムの累積」を作成したいと思います。つまり、私の期待される出力は

1,       2,      3, 4, 5, 6, 7, 8
1+2,     2+3,     ...
1+2+3    2+3+4    ...
1+2+3+4  2+3+4+5  ...

つまり、次を含む行列

1, 2, 3, 4, 5, 0, 0, 0
3, 5, 7, 9, 11,0, 0, 0
6, 9, 12,15,18,0, 0, 0
10,14,18,21,26,0, 0, 0

最後の 3 項目については cumsum 操作を正しく実行できないため、あると予想され0ます。私は単一の絶頂を行う方法を知っています。実際、配列は

a[:4].cumsum().reshape((-1,1)); a[1:5].cumsum().reshape((-1,1))...

水平に積み上げます。ただし、これを効率的な方法で行う方法がわかりません。これを行うための素晴らしいベクトル化されたnumpyの方法は何でしょうか? また、効率性や読みやすさの点でscipy優勢である限り、パッケージにもオープンです。numpy

4

3 に答える 3

2

合計面積表と呼ばれる技法のより単純な変種を使用して、計算を効率的に行うことができます。これは、画像処理アプリケーションでは積分画像とも呼ばれます。0最初に、合計面積テーブルを計算して保存します。これは、前に追加された最初の行の完全な累積です。

a = np.arange(1, 8)
cs = np.concatenate(([0], np.cumsum(a)))

nそして、「次のアイテムの累積」を次のように作成できるようになりましたcs[:n] - cs[:-n]

>>> for n in range(1, 5):
...     print n, '-->', (cs[n:] - cs[:-n])[:4]
...
1 --> [1 2 3 4]
2 --> [3 5 7 9]
3 --> [ 6  9 12 15]
4 --> [10 14 18 22]

必要な形状に適切に配置する必要がありますが、元の計算が完了すると、出力の各項目を 1 回の減算で計算できます。これは、可能な限り効率的です。

于 2015-07-28T13:32:58.717 に答える
1

考えられる 1 つの方法は、ローリング ウィンドウ アプローチを と組み合わせて使用​​することcumsum()です。

例えば:

from numpy.lib.stride_tricks import as_strided

a = np.arange(1, 9) # the starting array
slice_length = 4

次に、次のように記述できます。

arr = as_strided(a, (slice_length, len(a)), (a.strides[0], a.strides[0])).cumsum(axis=0)

これで大部分が得られますが、残りの0値を埋めるには、スライスと代入を使用して目的の出力を得ることができます。

arr[:, (1-slice_length):] = 0

次に、配列があります:

>>> arr
array([[ 1,  2,  3,  4,  5,  0,  0,  0],
       [ 3,  5,  7,  9, 11,  0,  0,  0],
       [ 6,  9, 12, 15, 18,  0,  0,  0],
       [10, 14, 18, 22, 26,  0,  0,  0]])

NumPy で単一のベクトル化されたメソッド (つまり、スライスなし) を使用して、目的の出力を正確に生成する方法があるかどうかはわかりません。( accumulateat、少し似ていますがreduceat、NumPy の ufuncs に追加すると興味深いものになるかもしれません...)

于 2015-07-28T13:26:47.360 に答える
0

あなたはbroadcastingそのように使うことができます -

In [53]: a
Out[53]: array([ 4, 13,  4, 18,  1,  2, 11, 15])

In [54]: WSZ = 4 # Window size

In [55]: idx = np.arange(WSZ)[:,None] + np.arange(a.size-WSZ+1) # Broadcasted indices

In [56]: a[idx].cumsum(axis=0) # Index into "a" & perform cumsum along axis-0
Out[56]: 
array([[ 4, 13,  4, 18,  1],
       [17, 17, 22, 19,  3],
       [21, 35, 23, 21, 14],
       [39, 36, 25, 32, 29]], dtype=int32)

必要に応じてゼロで埋めます -

In [57]: np.lib.pad(a[idx].cumsum(0),((0,0),(0,WSZ-1)),'constant',constant_values=0)
Out[57]: 
array([[ 4, 13,  4, 18,  1,  0,  0,  0],
       [17, 17, 22, 19,  3,  0,  0,  0],
       [21, 35, 23, 21, 14,  0,  0,  0],
       [39, 36, 25, 32, 29,  0,  0,  0]], dtype=int32)
于 2015-07-29T05:57:05.917 に答える