2016-11-25 8 views
2

浮動小数点数を持つ3D numpy配列を持ち、各要素の値を隣接(i-1)に置き換える必要がある場合はif値は値(vmin)より小さい。実装されたコードは非常に非効率的です:3D numpy配列列を反復して、隣の数値を次の数値に変更する場合

def replace_values(B,vmin,nt,nx,ny): 
    # B is a numpy array 
    # nt, nx ny the dimensions 
    for z in xrange(0,nt): 
     print i 
     for y in xrange(0,ny): 
      values=B[z,:,y] 
      if numpy.amin(values)==0: 
       for x in xrange(1,nx): 
        if B[z,x,y]<vmin: 
         B[z,x,y]=B[z,x-1,y] 
    return B  

速度を向上させるためにイテレータを実装する方法はありますか?

私は配列のサイズを持っている1つの制限は、ほとんどのRAMメモリのサイズです、コピーを行うことはできません。

答えて

1

あなたの内側のループが1Dビューに取り組んでいるように見え、そのようにコード化することができます(その場合は

In [386]: values=np.random.randint(0,10,20) 
In [387]: values 
Out[387]: array([1, 5, 9, 4, 6, 7, 1, 5, 6, 4, 4, 3, 9, 5, 8, 5, 0, 3, 1, 2]) 
In [388]: np.amin? 
In [389]: for x in range(1,len(values)): 
    ...:  if values[x]<5: 
    ...:   values[x]=values[x-1] 
    ...:   
In [390]: values 
Out[390]: array([1, 5, 9, 9, 6, 7, 7, 5, 6, 6, 6, 6, 9, 5, 8, 5, 5, 5, 5, 5]) 

、一つの目標は、おそらくufunc accumulate機能の一つで、これをスピードアップすることですcumsumの動作を考えてください)。

次の質問は、他の2次元の反復を避けることができるかどうかです。いくつかの転調と変形によって、それを1dの反復に凝縮することができますが、それは時間を節約しません。そして、3dよりも2次元アレイ上でアイデアをテストする方が簡単です。

私はapply_along_axisの反復の詳細を処理するように提案していましたが、その場では機能しませんし、outパラメータを使用することもできません)。

=======================

はのは、2次元配列のすべての値にこのアクションを適用してみましょう。

In [398]: val2d=np.array((x1,x1+2, x1-2)) 
In [399]: val2d 
Out[399]: 
array([[ 1, 5, 9, 4, 6, 7, 1, 5, 6, 4, 4, 3, 9, 5, 8, 5, 0, 3, 1, 2], 
     [ 3, 7, 11, 6, 8, 9, 3, 7, 8, 6, 6, 5, 11, 7, 10, 7, 2, 5, 3, 4], 
     [-1, 3, 7, 2, 4, 5, -1, 3, 4, 2, 2, 1, 7, 3, 6, 3, -2, 1, -1, 0]]) 
In [400]: for i in range(1,val2d.shape[1]): 
    ...:  mask = val2d[:,i]<5 
    ...:  val2d[mask,i]=val2d[mask,i-1] 
    ...:  
In [401]: val2d 
Out[401]: 
array([[ 1, 5, 9, 9, 6, 7, 7, 5, 6, 6, 6, 6, 9, 5, 8, 5, 5, 5, 5, 5], 
     [ 3, 7, 11, 6, 8, 9, 9, 7, 8, 6, 6, 5, 11, 7, 10, 7, 7, 5, 5, 5], 
     [-1, -1, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, 7, 7, 6, 6, 6, 6, 6, 6]]) 

そして、この3Dバージョンは(テストしていない)動作するはず:

for i in range(1, B.shape[1]): 
    mask = B[:,i,:]<vmin 
    I,J = np.where(mask) 
    B[I,i,J] = B[I,i-1,J] 
1

問題:フォワード充填マスク

に基づいて、ここで使用して単純な方法で説明した問題ですサンプル1Dデータ。

In [398]: a 
Out[398]: array([4, 8, 2, 6, 3]) 

は、(充填がFalseの位置に行う必要がある)であるのは、前方充填されるべきデータに基づいてマスクをしましょう:

のは、入力されたデータ配列があるとしましょう

In [407]: mask 
Out[407]: array([ True, True, False, True, False], dtype=bool) 

まず第一には、我々は次のマスクされたベースのインデックス配列

In [409]: mask*np.arange(mask.size) 
Out[409]: array([0, 1, 0, 3, 0]) 

を作成し、我々は、W、最大蓄積んあなたは、元のデータとこれを比較すると

In [411]: a[np.maximum.accumulate(mask*np.arange(mask.size))] 
Out[411]: array([4, 8, 8, 6, 6]) 

-

In [410]: np.maximum.accumulate(mask*np.arange(mask.size)) 
Out[410]: array([0, 1, 1, 3, 3]) 

だから、最後のステップは、単にこれらのデータ配列のインデックスは、インデックス配列蓄積する - HICH前方にマスクベースのインデックスの配列を埋めます配列から、マスクのFalseポジションに転送します。

最終的な実装

のは、いくつかのインデックスメソッドで3D場合に以前記載されているnp.maximum.accumulateベースのソリューションを拡張するため、自分自身の完全にベクトル化されたアプローチを挙げてみましょう -

nt, nx, ny = B.shape 
d0,d2 = np.where(B.min(1)==0)  
dim2_idx = np.maximum.accumulate((B[d0,:,d2]>=vmin)*np.arange(nx), axis=1) 
B[d0[:,None],np.arange(nx),d2[:,None]] = B[d0[:,None],dim2_idx,d2[:,None]] 
+0

ん '' 'mask'' '' 'B'''と同じくらい多くのメモリを消費しますか? – wwii

+0

@wwii '8 '倍ではなく、' m1'がブール配列であるのと同じですが、 'm2'はおそらく' B'と同じです。質問者のシステムメモリに合うといいでしょう:) – Divakar

+0

OPにはメモリの制約があります。 – wwii

関連する問題