1

A は ((d,e)) numpy 配列です。((d,e)) numpy 配列 B を計算し、エントリ B[i,j] を次のように計算します。

b=0
for k in range(i+1,d):
    for l in range(j+1,e):
        b=b+A[k,l]
B[i,j]=b

言い換えると、B[i,j] は、すべてのインデックス k>i、l>j で取得された A[k,l] の合計です。これは、両方の軸に適用される通常の cumsum の反対のようなものです。これを行うためのよりエレガントで高速な方法 (np.cumsum を使用するなど) があるかどうか疑問に思っています。

4

1 に答える 1

2

あなたがこれをやろうとしていると仮定します:

A = np.arange(15).reshape((5, -1))

def cumsum2_reverse(arr):
    out = np.empty_like(arr)
    d, e = arr.shape
    for i in xrange(d):
        for j in xrange(e):
            b = 0
            for k in xrange(i + 1, d):
                for l in xrange(j + 1, e):
                    b += arr[k, l]
            out[i, j] = b
    return out

そうすれば、

In [1]: A_revsum = cumsum2_reverse(A)

In [2]: A_revsum
Out[2]: 
array([[72, 38,  0],
      [63, 33,  0],
      [48, 25,  0],
      [27, 14,  0],
      [ 0,  0,  0]])

np.cumsum逆順の配列で使用して、合計を計算できます。たとえば、最初は @Jaime が提案したものに似たものを試すことができます。

In [3]: np.cumsum(np.cumsum(A[::-1, ::-1], 0), 1)[::-1, ::-1]
Out[3]:
array([[105,  75,  40],
       [102,  72,  38],
       [ 90,  63,  33],
       [ 69,  48,  25],
       [ 39,  27,  14]])

ここnp.cumsumで、最初の列 (この場合は最後の列) の値から始まることを覚えているので、そこにゼロを確保するために、この操作の出力をシフトすることができます。これは次のようになります。

def cumsum2_reverse_alt(arr):
    out = np.zeros_like(arr)
    out[:-1, :-1] = np.cumsum(np.cumsum(arr[:0:-1, :0:-1], 0), 1)[::-1, ::-1]
    return out

これにより、上記と同じ値が得られます。

In [4]: (cumsum2_reverse(A) == cumsum2_reverse_alt(A)).all()
Out[4]: True

np.cumsumを使用するものは、大きな配列の場合にはるかに高速であることに注意してください。例えば:

In [5]: A=np.arange(3000).reshape((50, -1))

In [6]: %timeit cumsum2_reverse(A)
1 loops, best of 3: 453 ms per loop

In [7]: %timeit cumsum2_reverse_alt(A)
10000 loops, best of 3: 24.7 us per loop
于 2015-07-29T19:30:04.920 に答える