2013-10-16 15 views
8

numpyの配列の要素を変え連続するゼロの数に等しい単一の数値に変換、すなわち: 私はnumpyの配列を有する

b = [0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 3.] 

>は100万個の要素を持っています配列としてこれを行うためのベクトル化の方法を探しています。 ご迷惑をおかけして申し訳ございません。

+0

これはベクトル化できるが、幸運なら驚くだろう:) – Hammer

答えて

8

これは、1)すべての連続したゼロを見つけて、それらを数える、2)出力配列のサイズを計算し、ゼロで初期化する、3)パート1からのカウントを正しい場所。いくつかのさまざまな

def cz(a): 
    a = np.asarray(a, int) 

    # Find where sequences of zeros start and end 
    wz = np.zeros(len(a) + 2, dtype=bool) 
    wz[1:-1] = a == 0 
    change = wz[1:] != wz[:-1] 
    edges = np.where(change)[0] 
    # Take the difference to get the number of zeros in each sequence 
    consecutive_zeros = edges[1::2] - edges[::2] 

    # Figure out where to put consecutive_zeros 
    idx = a.cumsum() 
    n = idx[-1] if len(idx) > 0 else 0 
    idx = idx[edges[::2]] 
    idx += np.arange(len(idx)) 

    # Create output array and populate with values for consecutive_zeros 
    out = np.zeros(len(consecutive_zeros) + n) 
    out[idx] = consecutive_zeros 
    return out 
+0

優れていて、とてもうまく動作します。私が使用しようとしていたループよりも速いオーダー。 – tommw

4

a = np.array([3., 0., 4., 2., 0., 0., 0.],dtype=np.int) 

inds = np.cumsum(a) 

#Find first occurrences and values thereof. 
uvals,zero_pos = np.unique(inds,return_index=True) 
zero_pos = np.hstack((zero_pos,a.shape[0]))+1 

#Gets zero lengths 
values = np.diff(zero_pos)-1 
mask = (uvals!=0) 

#Ignore where we have consecutive values 
zero_inds = uvals[mask] 
zero_inds += np.arange(zero_inds.shape[0]) 

#Create output array and apply zero values 
out = np.zeros(inds[-1] + zero_inds.shape[0]) 
out[zero_inds] = values[mask] 

out 
[ 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 3.] 

は、主に私たちがいる限り、それは単調に増加しているとして、配列の最初の出現を検索しnp.uniqueを使用することができるという事実に変わります。

+0

良い答え。私はaが先頭に0を持っていればそれは少しだと思うが、それは修正するのが簡単でなければならない。 –

+0

どちらも素敵です、@ BiRico'sはまだ私のマシンで少し速いです。 – askewchan

+0

@BiRico良い点は、その面が欠けていることです。興味深いことに、このメソッドが高速化する前に、配列に大きな値( 'a> 300')が必要です。 – Daniel