2017-09-11 8 views
3

次元(A、B、C)の3次元行列 "M"を扱うとき、[0、 A)及びY同じ寸法の[0、B)の要素を持つD.ブール行列を使用してループを置換して高度なインデックスを作成する

より具体的には、私は

M[X,Y,:] 

を書き込むときに、我々は各 "I" Dにおいて、

ため、服用していることを理解
M[X[i], Y[i], :], 

このようにして、 e end。

は今

X is a numpy array of dim U, same concept as before 
this time Y is a matrix UxL, where each row correspond to a Boolean numpy array 
(a mask) 

を想定し、次のコード私はforループをせずに同じコードを書きたい

for u in U: 
    my_matrix[Y[u], X[u], :] += 1 # Y[u] is the mask that selects specific elements of the first dimension 

を見てください。

for u in U: a_matrix[u, Y[u], :] = my_matrix[Y[u], X[u], :] 

割り当て

を実行するとき、残念ながら次のエラー

IndexError: boolean index did not match indexed array along dimension 0; dimension is L but corresponding boolean dimension is 1

を返します。この

np.add.at(my_matrix, (Y, X), 1) # i use numpy.ufunc.at since same elements could occur multiple times in X or Y. 

よう何かが、この問題も見つけることができますが、私は(この問題に対処する方法を知っていますかs)をエレガントな方法で?

+0

3x3x2マトリックスなどの視覚化が簡単な例がありますか? –

+1

私が理解していることを確かめるために、 'Y'は2D行列で、' Y [u] 'は' Y'次元をインデックスする1Dマスクです。しかし、 'X'は1次元行列なので、' X [u] 'は1つの要素です。言い換えれば、forループの作業では、3つのディメンション全体で「Y」で示される行で1つの列に1を追加するたびに、したがって、 'Y [u]'は同じ行の一部を示すことがあります。これは、それらの要素に1を何度も追加することに相当します。あれは正しいですか? –

+0

もしそうなら、私は最善の方法は、最初に 'Y'ベクトルを崩壊させるようなことを行い、全体に加えるために合計行列を計算することだと思います。 –

答えて

0

単純な通常のnd-array-shaped fancy索引付けを使用する簡単な方法は、問題のためにはうまくいかないでしょう。ここで私はこれを言っているのです:Yには、最初の次元に沿ってどのインデックスを取るべきかを示すブール値の行があります。したがって、Y[0]Y[1]は、異なる量のTrue要素を持つ可能性があります。したがって、Yの行は、最初の次元に沿って長さが変化するサブアレイをスライスします。言い換えれば、配列型のインデックスを長方形のサブ配列に変換することはできません。

しかし、インデックス配列が何を意味するかについて考えるなら、方法があります。 Yの行は、変更する要素を正確に示します。すべてのインデックスを1次元の魅力的なインデックスの巨大なコレクションに混乱させた場合、それぞれの(x,y)ポイントを、インデックスを作成する最初の次元に沿って見つけることができます。 (痛ん方法によって、あなたの質問から欠落している)次の例を考えてみ

特に

、:

A = np.arange(4*3*2).reshape(4,3,2) 
Y = np.array([[True,False,False,True], 
       [True,True,True,False], 
       [True,False,False,True]]) 
X = np.array([2,1,2]) 

Aは形状(4,3,2)Yある形状(3,4)(最初と最後の行は意図的に同一であり、さ)、Xはshape(3、) `です(最初と最後の要素は目的に応じて同じです)。あなたが見ることができるように

U,inds = Y.nonzero() 
#U: array([0, 0, 1, 1, 1, 2, 2]) 
#inds: array([0, 3, 0, 1, 2, 0, 3]) 

UYの各True要素の行インデックスです:のは、線形インデックスのコレクションにブール指標を回してみましょう。これらは、行間の対応がYで、要素がXであるインデックスです。 2番目の配列indsは、最初の次元に沿った(指定された行の)実際の線形インデックスです。

ほとんど完了です。indsの要素と、対応する2番目の次元のXのインデックスをペアにするだけです。これは実際には非常に簡単です:XUでインデックスするだけです。

は、したがって、すべてのすべてで、同じ問題に、次の2つのです同等のループと空想・インデックス・ソリューション:

B = A.copy() 
for u in range(X.size): 
    A[Y[u],X[u],:] += 1 
U,inds = Y.nonzero() 
np.add.at(B,(inds,X[U]),1) 

ABnp.add.atを使用して変更され、ループで修飾されています。我々は2つが同じであることがわかります。

>>> (A == B).all() 
True 

そして、あなたは例を見てみた場合、あなたは私が意図的指標の第一および第三の束を重複していることがわかります。これは、np.add.atがこれらのファンシーインデックスで正しく機能し、入力時に複数回表示されるインデックスを蓄積していることを示しています。 (Bを印刷して、Aの初期値と比較すると、最後の項目が2回インクリメントされていることが分かります)

関連する問題