2017-05-04 2 views
2

私は以下のことに苦労しています。私はパンダN x Dのデータフレームがpと呼ばれていて、いくらか欠落している(NAN)値があります。私はD x K x Tによってインデックスされた別の対応する配列を持っています。私はすべてのパンダのエントリn,dのデータフレーム内のa[d][k][p[n,d]]へのマップを作成して、可能なすべてのkについてN x D x Kマトリックスにしたいと考えています。 PandasとNumpyのライブラリでこれを最も効率的に行う方法についていくつか助けてもらえますか?パンダとナンシーファンシーインデックス

実際にはN x Dを最終行列の一部とし、列に沿ってN x K行列を残して製品を取り出します。最終的な出力は(ゆっくり)以下で再現することができます。

def generate_entry(i, j): 
     result = np.prod([alpha[s][j][int(p.loc[i][s])] for s in range(num_features) if not isNaN(p.loc[i][s]) ]) 
     return result 

    vgenerate_entry = np.vectorize(generate_entry) 
    result = np.fromfunction(vgenerate_entry, shape=(len(p), k), dtype=int) 

私はpandas.get_dummiesの一部の使用は行列乗算のための参考になると思いますが、私は非常にそれを把握することはできません。

次ははるかに高速です:

r = None 
    for i in range(num_features): 
     rel_data = pd.get_dummies(data.ix[:,i]) 
     rel_probs = alpha[i].T 
     prod = rel_data.dot(rel_probs) 
     prod[prod == 0] = 1 
     if r is None: 
      r = prod 
     else: 
      r = r.multiply(prod) 

    r = r.as_matrix() 
    r = r * pi 
    posteriers = r/np.sum(r, axis=1)[:, np.newaxis] 
+0

はい、それだけでかなり遅いです。 – modesitt

+0

あなたはそれを共有できますか?どのように 'p'でNaNを避ける予定ですか?/それらのNaNに対応する出力はどうでしょうか? – Divakar

+0

p [n、d]がnan – modesitt

答えて

3

ここでは避けるべきであるNaNsを、持っているパンダのデータフレームpとnumpyの配列aへのインデックスへの一つのアプローチだと私たちはそれらの中で、いくつかの値fillvalを充填しています場所 -

def fancy_indexing_avoid_NaNs(p, a, fillval = 1): 
    # Extract values from p and get NaN mask 
    pv = p.values 
    mask = np.isnan(pv) 

    # Get int version, replacing NaNs with some number, say 0 
    p_idx = np.where(mask, 0, pv).astype(int) 

    # FANCY-INDEX into array 'a' with those indices fron p 
    a_indexed_vals = a[np.arange(D), np.arange(K)[:,None,None],p_idx] 

    # FANCY-INDEX once more to replace the values set by NaNs as 1s, so 
    # that in the prod-reduction later on they would have no effect 
    a_indexed_vals[np.arange(K)[:,None,None],mask] = fillval 
    return a_indexed_vals 

そのfillvalはアプリケーションによって異なります。この場合、prodを使用しているため、fillval=1が意味を持ちますが、結果には影響しません。 OPによって投稿

オリジナルのアプローチ -

def generate_entry(i, j): 
    result = np.prod([a[s][j][int(p.loc[i][s])] for s in range(D) \ 
            if not np.isnan(p.loc[i][s]) ]) 
    return result 

vgenerate_entry = np.vectorize(generate_entry) 

サンプル実行 -

In [154]: N,D,K,T = 3,4,5,6 
    ...: a = np.random.randint(0,5,(D,K,T)) 
    ...: 
    ...: p = pd.DataFrame(np.random.randint(0,T,(N,D)).astype(float)) 
    ...: p.iloc[2,3] = np.nan 
    ...: p.iloc[1,2] = np.nan 
    ...: 

In [155]: result = np.fromfunction(vgenerate_entry, shape=(len(p), K), dtype=int) 

In [156]: a_indexed_vals = fancy_indexing_avoid_NaNs(p, a) 

In [157]: out = a_indexed_vals.prod(2).T 

In [158]: np.allclose(out, result) 
Out[158]: True 
+0

はアレンジについて知りませんでした。マスクの優れた使用 – modesitt