2016-03-28 6 views
0

numpyを使用して次の関数をベクトル化しようとしていますが、完全に失われています。2つの配列のインデックス作成中にナンシーベクトル化

A = ndarray: Z x 3 

B = ndarray: Z x 3 

C = integer 

D = ndarray: C x 3 

擬似コード:

entries = [] 
means = [] 
For i in range(C): 
    for p in range(len(B)): 
     if B[p] == D[i]: 
      entries.append(A[p]) 
    means.append(columnwise_means(entries)) 
return means 

例は次のようになります。

A = [[1,2,3],[1,2,3],[4,5,6],[4,5,6]] 
B = [[9,8,7],[7,6,5],[1,2,3],[3,4,5]] 
C = 2 
D = [[1,2,3],[4,5,6]] 

戻り値:

[average([9,8,7],[7,6,5]), average(([1,2,3],[3,4,5])] = [[8,7,6],[2,3,4]] 

私はnp.where、np.argwhereを使用して試してみました、 np.meanなどがありますが、望みの効果を得ることはできません。どんな助けでも大歓迎です。

ありがとうございます!

+0

あなたはAとBを逆転させると思いますか? –

+0

あなたはどういう意味なのかよく分かりません..... – user2069641

+0

「平均([9,8,7]、[7,6,5])、平均(([1,2、 3]、[3,4,5])] '?擬似コード*からはっきりと分かりません。 – Divakar

答えて

1

、私は実際のコードでは、あなたが持っているであろうと想定しています:if A[p] == D[i]、および

  • エントリ:

    • 条件としてIF文B:entries.append(B[p])から追加されます。

    だから、ここNumPy broadcastingdot-productと1つのベクトル化のアプローチだ -

    mask = (D[:,None,:] == A).all(-1) 
    out = mask.dot(B)/(mask.sum(1)[:,None]) 
    

    がの指標として配列を考慮すると、入力配列が整数配列である場合、あなたはメモリを節約し、パフォーマンスを高めることができますこのようにn次元配列とはとてもよう3Dを介さず2D maskを作成 -

    dims = np.maximum(A.max(0),D.max(0))+1 
    mask = np.ravel_multi_index(D.T,dims)[:,None] == np.ravel_multi_index(A.T,dims) 
    

    サンプルラン -

    In [107]: A 
    Out[107]: 
    array([[1, 2, 3], 
         [1, 2, 3], 
         [4, 5, 6], 
         [4, 5, 6]]) 
    
    In [108]: B 
    Out[108]: 
    array([[9, 8, 7], 
         [7, 6, 5], 
         [1, 2, 3], 
         [3, 4, 5]]) 
    
    In [109]: mask = (D[:,None,:] == A).all(-1) 
        ...: out = mask.dot(B)/(mask.sum(1)[:,None]) 
        ...: 
    
    In [110]: out 
    Out[110]: 
    array([[8, 7, 6], 
         [2, 3, 4]]) 
    
  • +0

    非常に良い!私はこの場合完全なベクトル化を想像しません。 –

    +0

    @ B.M。放送は常に可能です!そのドットプロダクトは遅れた考えとして打ちました:) – Divakar

    +0

    @ user2069641質問の擬似コードを編集して、回答の最初に示唆された2つの変更を組み入れることができますか?そうでなければ、投稿された回答は質問と一致しません。 – Divakar

    1

    2つのヒントを参照してください。

    最初に、行ごとに比較します。それを行うための方法は、1Dにあなたのインデックスシステムを簡素化することです:

    def indexer(M,base=256): 
        return (M*base**arange(3)).sum(axis=1) 
    

    ベースは整数>A.max()です。その後、選択がそのように行うことができる。ため

    indices=np.equal.outer(indexer(D),indexer(A)) 
    

    array([[ True, True, False, False], 
         [False, False, True, True]], dtype=bool) 
    

    第2に、各グループは、異なる長さを有することができるので、ベクトル化は、最後のステップのために困難です。ここに仕事を達成する方法。質問の予想出力で行く

    B=array(B) 
    means=[B[i].mean(axis=0) for i in indices] 
    
    +0

    それで、 'indexer'は入力を整数配列として仮定します。 – Divakar

    +0

    そうだそうです。私は今、ベクトル化可能な他の解決策を見つけることはできません。 –

    関連する問題