2016-06-14 10 views
2

S x n配列DATAとデータがあります。私は、整数値が<=n(S x 1)の配列ARRAYを持っています。 DATAの各行iについて、私は配列に基づくベクトル化された行列選択

DATA[i, ARRAY[i]:] = np.nan 

にしたいここでは、今、私はそれをやっている方法です

from numpy.random import poisson as poissonN 
from numpy.random import uniform 
import numpy as np 
S = 1000 
n = 8 
DATA = uniform(low=0, high=1, size=S*n).reshape((S, n)) 
ARRAY = poissonN(1, S).reshape((-1, 1)) 

for i, draw in enumerate(ARRAY): 
    DATA[i, draw:] = np.nan 

Sがでいけば、より効率的で、これにベクトル化されたアナログが存在する必要があります何十万、そう?どんなメッシュでしようとしても、それはうまくいかないでしょう - あるいはこの反復的なアプローチにも同じように遅いです。

DATA[ARRAY <= np.arange(DATA.shape[1])] = np.nan 

解説者はS = 5n=4でサンプルケースを取り、DATAARRAYを作成してみましょう -

+1

は(私はそれを知っていない)、この作品を作るために派手なインデックストリックがあるかもしれません。表示されない場合は、このコードスニペットが大きなボトルネックになる場合は、Cythonで書き込むと処理が速くなります。 – mgilson

答えて

2

あなたはNumPy broadcastingboolean indexingを使用することができます。

In [288]: S = 5 
    ...: n = 4 
    ...: DATA = uniform(low=0, high=1, size=S*n).reshape((S, n)) 
    ...: ARRAY = poissonN(1, S).reshape((-1, 1)) 
    ...: 

In [289]: DATA 
Out[289]: 
array([[ 0.54235747, 0.01309313, 0.62664698, 0.92081697], 
     [ 0.17877576, 0.36536259, 0.91874957, 0.81924979], 
     [ 0.7518459 , 0.73218436, 0.99685998, 0.26435871], 
     [ 0.73130257, 0.77123956, 0.10437601, 0.09296549], 
     [ 0.804398 , 0.78675381, 0.71066382, 0.87481544]]) 

In [290]: ARRAY 
Out[290]: 
array([[1], 
     [1], 
     [0], 
     [2], 
     [1]]) 

さて、ループの多いコードを実行すると何が起こるか見て -

In [291]: for i, draw in enumerate(ARRAY): 
    ...:  DATA[i, draw:] = np.nan 
    ...:  

In [292]: DATA 
Out[292]: 
array([[ 0.54235747,   nan,   nan,   nan], 
     [ 0.17877576,   nan,   nan,   nan], 
     [  nan,   nan,   nan,   nan], 
     [ 0.73130257, 0.77123956,   nan,   nan], 
     [ 0.804398 ,   nan,   nan,   nan]]) 

を今、我々はそれがすべてNaN要素を覆うようにDATAと同じ形状のブール配列を作成している提案された解決策でTrueとし、残りはFalseとする。同じのために

ここに示したように、我々はbroadcastingを使用している -

したがって
In [293]: ARRAY <= np.arange(DATA.shape[1]) 
Out[293]: 
array([[False, True, True, True], 
     [False, True, True, True], 
     [ True, True, True, True], 
     [False, False, True, True], 
     [False, True, True, True]], dtype=bool) 

、ブールインデックスで、我々はDATA内のNaNなど、すべてのそれらの位置を設定することができます。のは、ランダムな要素の別のインスタンスを作成し、私たちの提案されたアプローチとNaNを試してみよう -

In [294]: DATA = uniform(low=0, high=1, size=S*n).reshape((S, n)) 

In [295]: DATA[ARRAY <= np.arange(DATA.shape[1])] = np.nan 

In [296]: DATA 
Out[296]: 
array([[ 0.87061908,   nan,   nan,   nan], 
     [ 0.69237094,   nan,   nan,   nan], 
     [  nan,   nan,   nan,   nan], 
     [ 0.04257803, 0.82311917,   nan,   nan], 
     [ 0.00723291,   nan,   nan,   nan]]) 

我々はデータを再作成しているので、非NaN値は、異なっているのでご注意ください。重要なことは、NaNsを正しく設定したことです。

ランタイムテスト

In [297]: # Inputs 
    ...: S = 1000 
    ...: n = 8 
    ...: DATA = uniform(low=0, high=1, size=S*n).reshape((S, n)) 
    ...: ARRAY = poissonN(1, S).reshape((-1, 1)) 
    ...: 

In [298]: DATAc = DATA.copy() # Make copy for testing proposed ans 

In [299]: def org_app(DATA,ARRAY): 
    ...:  for i, draw in enumerate(ARRAY): 
    ...:   DATA[i, draw:] = np.nan 
    ...:   

In [301]: %timeit org_app(DATA,ARRAY) 
100 loops, best of 3: 4.99 ms per loop 

In [302]: %timeit DATAc[ARRAY <= np.arange(DATAc.shape[1])] = np.nan 
10000 loops, best of 3: 94.1 µs per loop 

In [305]: np.allclose(np.isnan(DATA),np.isnan(DATAc)) 
Out[305]: True 
関連する問題