2013-04-12 21 views
24

私は2D配列内の複数の要素の値を設定していますが、私のデータには特定のインデックスの複数の値が含まれることがあります。NumPyの割り当てにおける重複インデックスの扱い

"後"の値は常に割り当てられますが(下の例を参照)、この動作は保証されているか、矛盾した結果が得られる可能性がありますか?ベクタライズされた課題で「後で」解釈できることをどのようにして知ることができますか?

つまり、私の最初の例ではaには常に4が含まれ、2番目の例ではvalues[0]が印刷されますか?

非常に簡単な例:

numpyの1.9では
import numpy as np 
indices = np.zeros(5,dtype=np.int) 
a[indices] = np.arange(5) 
a # array([4]) 

別の例

import numpy as np 

grid = np.zeros((1000, 800)) 

# generate indices and values 
xs = np.random.randint(0, grid.shape[0], 100) 
ys = np.random.randint(0, grid.shape[1], 100) 
values = np.random.rand(100) 

# make sure we have a duplicate index 
print values[0], values[5] 
xs[0] = xs[5] 
ys[0] = ys[5] 

grid[xs, ys] = values 

print "output value is", grid[xs[0], ys[0]] 
# always prints value of values[5] 
+1

Numpyアレイの動作で何が起こっているのか理解するには、私はhttp://scipy-lectures.github.io/advanced/advanced_numpy/をお勧めします。 – tom10

+4

素敵な質問...これはおそらく待つ必要があるものの1つです@sebergは意味のある答えを得るために周りにいる。 – Jaime

+3

私は何かが保証されているのではないかと疑いますが、外見的にストライドされた配列を使ったいくつかの実験では、インデックス配列上の単純な左から右へのループを指しています。 –

答えて

12

以降、これは一般的に明確に定義されることはありません。

現在の実装では、別々のイテレータを使用してすべての(ブロードキャストされた)ファンシーインデックス(および代入配列)を同時に繰り返します。これらのイテレータはすべてCオーダーを使用します。言い換えれば、現在、はい、できます。あなたはもっと正確にそれを知りたいかもしれないので。これらを処理するNumPyでmapping.cを比較すると、(documented)がCオーダーになることがわかります。

将来的に私は絵を違った色に塗ります。より新しいイテレータを使用して、すべてのインデックス+代入配列を繰り返し処理することは良いと思います。これが行われた場合、イテレータが最速の方法を決定するための順序を開いたままにすることができます。イテレータを開いたままにしておくと、何が起きるかは言い難いですが、あなたのサンプルがうまくいくかどうかはわかりません(おそらく1-dの場合は可能ですが...)。

私はそれが現時点ではうまくいくとは限りませんが、私が知っているすべてについては文書化されていませんので、実際にこれを保証する必要があると考えるなら、それが保証されることを確認してください。少なくとも、物事をより速くするなら、Cオーダーを保証する理由はありませんが、もちろんどこかに隠された正当な理由があるかもしれません...

本当の質問はここにあります:なぜですかとにかくそれが欲しいですか? ;)

+0

お返事ありがとうございました。私は何故これが何日後に起こったのか尋ねる理由を正当なものとして書き留めます。私は、Cオーダーを維持する本当に正当な理由があるかどうかを十分に知っているとは思っていません。 – YXD

+0

私は[このディスカッション]を見ました(http://mail.scipy.org/pipermail/numpy-discussion/ 2014年2月/ 068810.html)、numpy 1.9について、この質問に提示された2Dの場合の含意が何であるか疑問に思っていました。その動機は、3Dデータを離散的なピクセル座標に投影し、投影によって画像空間に衝突が発生する可能性のある「最良の」データを効率的に追跡する必要がある視覚の問題から来ています。私の実際のコードは、コスト/エラーに従ってデータをソートし、次に質問に示されているように割り当てることによってこれを実現します。 – YXD

5

私はあなたに直接お答えしていませんが、でも、が一貫していることに頼っていても、より良いことはありません。

は考えてみましょう:この時点で

a = np.zeros(4) 
x = np.arange(4) 
indices = np.zeros(4,dtype=np.int) 
a[indices] += x 

、それはa.sum()aの前の合計+ x.sum()であると仮定するのが妥当でしょうか?あなたのケースでは

assert a.sum() == x.sum() 
--> AssertionError 

a 
= array([ 3., 0., 0., 0.]) 

重複インデックスを使用してアレイに割り当てる場合、結果は直感的である:同じインデックスへの割り当ては、最後の割り当て「スティック」(それは以前のものを上書きする)ので、複数回行われます。

しかし、この例ではそうではありません。もはや直感的ではありません。そうであれば、追加はその性質上累積的であるため、インプレースの追加は複数回行われていました。

ので、別の方法を置く、あなたはこのトラップに捕まる危険にさらしている:あなたは、重複するインデックスで作業を開始

  • あなたはすべての行動はあなた
  • を期待するように正確である、よくある参照あなたの業務に重複した指標が含まれているという重要な事実に注意を払うのをやめてください。結局のところ、それは違いはありませんか?
  • 異なるインデックスで同じインデックスを使用します(例:
  • 深い後悔:)だから、

上記のように、@seberg引用:ここ

が本当の問題は:なぜあなたはとにかくことをしたいですか? ;)

+1

これは間違いなく興味深いケースです。そして、はい、あなたの弾丸ポイントはまさに私が質問した理由です。私の元の例では、何が起こっているべきかがより明らかになっているようです。私は数日後に背景/文脈を投稿します。 – YXD

6

私は、これは十分回答されているけど、私はTentative Numpy TutorialIndexing with Arrays of Indicesの下で(おそらく非公式)それは「最後の値」として文書化されていることに言及したかった:

>>> a = arange(5) 
>>> a[[0,0,2]]=[1,2,3] 
>>> a 
array([2, 1, 3, 3, 4]) 
:インデックスのリストが繰り返しが含まれている場合

しかし、割り当ては最後の値を残し、数回行われています

これは十分に合理的ですが、あなたはそれが何を期待しないこととして、Pythonの+ =の構築を使用する場合は気を付ける:

>>> a = arange(5) 
>>> a[[0,0,2]]+=1 
>>> a 
array([1, 1, 3, 3, 4]) 

0は、インデックスのリストで二回0番目の要素を発生しても1回だけインクリメントされます。これは、Pythonがa+=1a=a+1と同等にする必要があるためです。

2

は、私は、これは明らかに最適ではありませんが、この操作 を行うためにnumpyのとで方法を見つけたその速い

と(forループのpythonで)ループより: numpy.bincount

size = 5 
a = np.arange(size) 
index = [0,0,2] 
values = [1,2,3] 
a[index] += values 
a 
[2 1 5 3 4] 

魔女は 正しくありませんが:

size = 5 
a = np.arange(size) 
index = [0,0,2] 
values = [1,2,3] 
result = np.bincount(index, values, size) 
a += result 
a 
[3 1 5 3 4] 

良いですよ!

+2

おそらく、このアプローチはより良いでしょう:http://stackoverflow.com/a/24100418/1758727 – czxttkl

関連する問題