1

私はnumpyでこのPythonコードを実装する方法を探しています:

  N = np.arange(5)

  for i in range(5):
     for k in range(i):
        N[i] += N[k]

私が実際に大きな 2 次元配列 (1300*1300) で作業していると仮定します。

np.cumsum()進化する配列ではなく、元の配列の値のみを合計することを除いて、1つの軸N[0][i]またはで良い方法を提供します。N[i][0]

私はそれを行う方法を理解できません。何か案が ?

@編集 :

物事を明確にするために:

1 次元配列の場合、ループは次のようになります。

Out[89]: array([ 0,  1,  3,  7, 15])

cumsum を使用:

array([ 0,  1,  3,  6, 10])

2-D の場合、次のようになります。

N = np.arange(25).reshape(5,5)
for i in range(len(N)):
    N = np.cumsum(N, axis=i)
4

2 に答える 2

2

シーケンスから始めてループの結果を計算a[n]し、2つのforループから出てくるのがシーケンスb[n]である場合、次のようになります。

b[n] = a[n] + a[n-1] + 2*a[n-2] + 4*a[n-3] + ... + 2**(n-2)*a[0] =
       a[n] + c[n-1] 

私が定義しているところ:

c[n-1] = a[n-1] + 2*a[n-2] + 4*a[n-3] + ... + 2**(n-2)*a[0]

この最後の式を念頭に置いて、二重ループをベクトル化する方法があります。ただし2**(n-2)、シーケンス内のアイテムを乗算する必要がある非常に大きな要因()に注意してください。シーケンスに正と負の項がある場合、これらはキャンセルされ、妥当な数を返す可能性があります。ただし、1000を超える正の要素の配列がある場合は、numpyのdtypeをオーバーフローさせます。

したがって、30アイテム未満の短いシーケンスの場合、int64'sを使用するように強制すると、おそらく60になりますが、forループよりも高速に動作します。

def evolving_cumsum(arr):
    arr = np.array(arr) # makes a copy of the data
    pows = 2**np.arange(len(arr))[::-1]
    c = np.cumsum(arr*pows)
    c /= pows
    arr[1:] += c[:-1]
    return arr

>>> a = np.arange(10)
>>> evolving_cumsum(a)
array([  0,   1,   3,   7,  15,  31,  63, 127, 255, 511])
>>> for i in range(len(a)):
...     for k in range(i):
...         a[i] += a[k]
... 
>>> a
array([  0,   1,   3,   7,  15,  31,  63, 127, 255, 511])

しかし、一般的に、私はあなたがあなたのループを維持しなければならないだろうと思います。

于 2013-03-18T01:51:58.400 に答える
0
import numpy as np
N = np.arange(5)
print np.cumsum(N) # outputs [ 0  1  3  6 10]

for i in range(5):
    for k in range(i):
        N[i] += N[k]

print np.cumsum(N) # outputs [ 0  1  4 11 26]

配列を進化させるとはどういう意味ですか?

于 2013-03-17T22:37:39.700 に答える