3

問題の説明から始めます。その後、問題に到達するまでソリューションを徐々に構築するコーディングの簡単なシーケンスを示します。明らかに、ここでの目標は b を計算することです。私はそれを最も効率的に行う方法を尋ねています。理想的には、反復もループもまったく行わずに、要素ごとのnumpyベクトル式を使用します。

b = sum(v)-a
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.6/site-packages/numpy/core/fromnumeric.py", line 1251, in sum
return _wrapit(a, 'sum', axis, dtype, out)
File "/usr/lib64/python2.6/site-packages/numpy/core/fromnumeric.py", line 37, in _wrapit
result = getattr(asarray(obj),method)(*args, **kwds)
File "/usr/lib64/python2.6/site-packages/numpy/core/numeric.py", line 230, in asarray
return array(a, dtype, copy=False, order=order)
ValueError: setting an array element with a sequence.

これが、そのエラーにつながった、私がやろうとしたコードの私の最高のバージョンです。わかりやすくするために、いくつかの印刷ステートメントを追加しました。

a = array([0,1,0,1,1])
b = +a
print b
array([0, 1, 0, 1, 1])

b = array([sum(a[0:2]), sum(a[0:3]), sum(a[1:4]), sum(a[2:5]), sum(a[3:5])])
print b
array([1, 1, 2, 2, 2])

b = array([sum(a[0:2])-a[0], sum(a[0:3])-a[1], sum(a[1:4])-a[2], sum(a[2:5])-a[3], sum(a[3:5])-a[4]])
print b
array([1, 0, 2, 1, 1])

v = [a[0:2], a[0:3], a[1:4], a[2:5], a[3:5]]
print v
[array([0, 1]), array([0, 1, 0]), array([1, 0, 1]), array([0, 1, 1]), array([1, 1])]

v はビュー リストであることに注意してください。ビューはバッキング配列 a を参照しています。

print a
array([0, 1, 0, 1, 1])

a[0]=9
print v
[array([9, 1]), array([9, 1, 0]), array([1, 0, 1]), array([0, 1, 1]), array([1, 1])]

a[0]=0
print v
[array([0, 1]), array([0, 1, 0]), array([1, 0, 1]), array([0, 1, 1]), array([1, 1])]

これまでのところ、変数 v は真のビューです。つまり、a が更新されると v が更新されます。

b = array([sum(v[0])-a[0], sum(v[1])-a[1], sum(v[2])-a[2], sum(v[3])-a[3], sum(v[4])-a[4]])
print b
array([1, 0, 2, 1, 1])

素晴らしい、これまでのところとても良い。ここで、コード行をもう少し単純化してみましょう.... 変数 b、v、および a はすべて同じ数の要素を持つことに注意してください。

b = sum(v)-a
Traceback (most recent call last)...(error messages)...

おお、コードが悪い!さて、b を表現する他の方法も試してみましたが、同様にエラーでした。ここでこれ以上悪いコードを示す必要はありません。問題は、代入式を正しく、しかも最も効率的に表現する方法です。この特定のアプリケーションで可能な場合、計算に特に役立ちます。ビューが設定された後、式のループを完全に避け、リスト内包表記を避けることです。

このアプリケーションでは、低速ループを使用してビューを設定しても問題ありません。ビューが頻繁に変わることはありません。バッキング配列 a は頻繁に変更され、非常に大きくなります。

読んでくれてありがとう、そしてあなたの最高の提案をありがとう!

4

4 に答える 4

2

投稿した特定のビューについて、計算はカーネルとの畳み込みvとして表現できます。[1, 1, 1]

In [78]: import numpy as np    

In [80]: a = np.array([0,1,0,1,1])

In [81]: b = np.convolve(a, [1,1,1], 'same') - a

In [82]: b
Out[82]: array([1, 0, 2, 1, 1])

時間の経過とともにどのようにv変化するかは述べていませんが、おそらくそれらが類似している場合、カーネルへの変化を伴う畳み込みとして計算を表現し続けることができます。

于 2012-08-14T16:22:33.163 に答える
0

どうですか:

b = [sum(i) for i in v] - a

( とv同じ数の項目がaあり、両方とも 1D であるため、これは機能します) ?

于 2012-08-17T01:48:36.030 に答える
0

unutbuさんの答えが正しいと思います。ただし、多様性のために、ベース アレイ上でローリング ウィンドウを使用するアプローチを次に示します。これaもビューです。aこれは、事前に の長さを知っていることを前提としています。

まず、割り当て超過の配列を作成します。

>>> datalen = 5
>>> base = numpy.zeros(datalen + 2, dtype='i8')

a次に、その配列の切り詰められたビューとして定義し、初期化します。

>>> a = base[1:-1]
>>> a[:] = [0, 1, 0, 1, 1]

を使用しますstride_tricks。形状の配列の通常のストライドは次のよう(5, 3)dtype='i8'なります(24, 8)。に減らす24こと8で、各行の開始点が 3 つではなく 1 つ前に進むようにします。

>>> window = numpy.lib.stride_tricks.as_strided(base, shape=(5, 3), 
                                                      strides=(8, 8))
>>> window
array([[0, 0, 1],
       [0, 1, 0],
       [1, 0, 1],
       [0, 1, 1],
       [1, 1, 0]])

これで、次のように呼び出すことができますsum(axis=1):

>>> window.sum(axis=1) - a
array([1, 0, 2, 1, 1])

a同じメモリをwindow指しているため、更新は正しく機能します。

>>> a[0] = 9
>>> window
array([[0, 9, 1],
       [9, 1, 0],
       [1, 0, 1],
       [0, 1, 1],
       [1, 1, 0]])
>>> window.sum(axis=1) - a
array([1, 9, 2, 1, 1])

また、ここで提供する特定の例については、次のように簡単に機能することも指摘します。

>>> base[:5] + base[-5:]
array([1, 9, 2, 1, 1])
>>> a[0] = 0
>>> base[:5] + base[-5:]
array([1, 0, 2, 1, 1])

しかし、実際のニーズはもっと複雑だと思います。

于 2012-08-14T23:24:59.587 に答える
0

どうですか:

numpy.vectorize(sum)(v) - a

例えば:

>>> import numpy
>>> a = numpy.array([0,1,0,1,1])
>>> v = [a[0:2], a[0:3], a[1:4], a[2:5], a[3:5]]
>>> numpy.vectorize(sum)(v) - a
array([1, 0, 2, 1, 1])
于 2012-08-14T16:15:13.257 に答える