2017-02-06 2 views
0

n x m行列Xおよびn x p行列Yここで、Yはバイナリデータです。最後にp x n行列Zがあります。ここで、Zの列はXの列の関数であり、1に対応する列の項目はYです。バイナリデータを持つ別のサブセットベースの行列

反復が

i=0, j=0: subsetted_column = [[1],[4]] 
i=0, j=1: subsetted_column = [[7]] 
i=1, j=0: subsetted_column = [[2],[5]] 
i=1, j=1: subsetted_column = [[8]] 
i=2, j=0: subsetted_column = [[3],[6]] 
i=2, j=1: subsetted_column = [[9]] 

を生成する

>>> X 
array([[1, 2, 3], 
    [4, 5, 6], 
    [7, 8, 9]]) 
>>> Y 
array([[1, 0], 
    [1, 0], 
    [0, 1]]) 
n_x,m = X.shape 
n_y,p = Y.shape 
Z = np.zeros([p, n_x]) 
for i in range(n_x): 
    col = X[:,[i]] 
    for j in range(p): 
     #this is where I subset col with Y[:,[j]] 
     Z[j][i] = my_func(subsetted_column) 

例えば私は、単一のリスト内包しているネストされたループを行うにはいくつかの方法があると仮定します。関数my_funcにも長い時間がかかりますので、何とか並列化するといいでしょう。

編集:私は

for i in range(n_x): 
    for j in range(p): 
     subsetted_column = np.trim_zeros(np.multiply(X[:,i], Y[:,j])) 
     Z[j][i] = my_func(subsetted_column) 

しかし、私はまだ簡単に解決

+0

を意味します。この質問で私たちが助けることができるのは、実行時間のごく一部であるループオーバーヘッドを減らすことだけです。 'my_func'が遅い場合、それをnx * p回呼び出すことはループ機構ではなく、ボトルネックになります。 – hpaulj

+0

合意。私の主な質問(および質問のタイトル)は、ループを指しています。 – Sal

+1

多分、関数自体を並列化しないで、関数の複数のインスタンスを並列に実行してみてください。この種のものに対して 'multiprocessing.Pool'を使う方法については、[post](http://stackoverflow.com/questions/19429377/parallel-processing-pool-python)を参照してください。 –

答えて

2

これはあなたが望む何があると考えているような何かを行うことができますか?

import numpy as np 

N, M, P = 4, 3, 2 

a = np.random.random((N, M)) 
b = np.random.randint(2, size=(N, P)).astype(bool) 

your_func = lambda x: x # insert proper function here 
flat = [your_func(ai[bj]) for bj in b.T for ai in a.T] 

out = np.empty((P, M), dtype=object) 
out.ravel()[:] = flat 
print(a) 
print(b) 
print(out) 

備考:

  • これはあなたが論理的なインデックスを使用することができますので、それはあなたのマスキング配列がdtype boolに変換するのが最も簡単です。
  • your_funcが数字を返した場合、outにはdtype=objectを使用しない方が良いでしょう。
  • もしあなたが並列化したいのであれば、リストの理解はおそらく最善のことではありませんが、私はそれについて専門家ではありません。反復の順序は無関係なので、ループは明白な並列化のターゲットのように見えるだけです。

サンプル出力:

[[ 0.62739382 0.85774837 0.81958524] 
[ 0.99690996 0.71202879 0.97636715] 
[ 0.89235107 0.91739852 0.39537849] 
[ 0.0413107 0.11662271 0.72419308]] 
[[False True] 
[ True True] 
[False False] 
[ True True]] 
[[array([ 0.99690996, 0.0413107 ]) array([ 0.71202879, 0.11662271]) 
    array([ 0.97636715, 0.72419308])] 
[array([ 0.62739382, 0.99690996, 0.0413107 ]) 
    array([ 0.85774837, 0.71202879, 0.11662271]) 
    array([ 0.81958524, 0.97636715, 0.72419308])]] 
0

それは(.Tがリスト内包の列に反復するために使用される前処理ループにおいて

In [112]: xs = [X[y,:] for y in Y.astype(bool).T] 
In [113]: xs 
Out[113]: 
[array([[1, 2, 3], 
     [4, 5, 6]]), 
array([[7, 8, 9]])] 

のサブセットを実行するのを助けることができる。boolmy_funcは平均値をとるとします。たとえば、my_funcサブセット

In [116]: [np.mean(s, axis=0) for s in xs] 
Out[116]: [array([ 2.5, 3.5, 4.5]), array([ 7., 8., 9.])] 
In [117]: np.array(_) 
Out[117]: 
array([[ 2.5, 3.5, 4.5], 
     [ 7. , 8. , 9. ]]) 

ための軸= 0で私は1つのループにそれを組み合わせることができ、それは考えるように難しいです:

np.array([np.mean(X[y,:],axis=0) for y in Y.astype(bool).T]) 

このxsリストを使用すると、効率的にmy_funcを適用する上で、あなたの努力を集中することができますxs[i]のすべての列にnp.mean(xs[i], axis=0)としています。

本のダブルループバージョンでは、我々はあなたが我々はについて何も知らない機能を「並列化」を支援することはできません

In [121]: p=np.zeros((2,3)) 
In [122]: for i in range(2): 
    ...:  for j in range(3): 
    ...:   p[i,j] = np.mean(xs[i][:,j]) 
    ...:   
In [123]: p 
Out[123]: 
array([[ 2.5, 3.5, 4.5], 
     [ 7. , 8. , 9. ]]) 

等価ダブルリスト内包

In [125]: [[np.mean(i) for i in j.T] for j in xs] 
Out[125]: [[2.5, 3.5, 4.5], [7.0, 8.0, 9.0]] 
関連する問題