2017-10-24 4 views
2

ほとんどのパンダの問題として、私は以前問題があったと推測していますが、私は直接的な答えは見つけられず、パフォーマンスも心配しています。私のデータセットは大きいので、私はが最も効率的であることを願っています。これを行う方法。DataFrameリストから転載

問題 私は2つのデータフレームを持っています - dfAにはdfBからのIDのリストが含まれています。私は合計ここ

  1. 転置列としてこれらのIDを値がDFBから
  2. 崩壊繰り返し列を見上げて
  3. は、IDを交換し、集計したいことはイラストです:

    DFA

    dfA = pd.DataFrame({'a_id':['0000001','0000002','0000003','0000004'], 
            'list_of_b_id':[['2','3','7'],[],['1','2','3','4'],['6','7']] 
            }) 
    
    +------+--------------+ 
    | a_id | list_of_b_id | 
    +------+--------------+ 
    | 1 | [2, 3, 7] | 
    +------+--------------+ 
    | 2 | []   | 
    +------+--------------+ 
    | 3 | [1, 2, 3, 4] | 
    +------+--------------+ 
    | 4 | [6, 7]  | 
    +------+--------------+ 
    

    DFBここ

    dfB = pd.DataFrame({'b_id':['1','2','3','4','5','6','7'], 
            'replacement': ['Red','Red','Blue','Red','Green','Blue','Red'] 
            }) 
    
    +------+-------------+ 
    | b_id | replacement | 
    +------+-------------+ 
    | 1 | Red   | 
    +------+-------------+ 
    | 2 | Red   | 
    +------+-------------+ 
    | 3 | Blue  | 
    +------+-------------+ 
    | 4 | Red   | 
    +------+-------------+ 
    | 5 | Orange  | 
    +------+-------------+ 
    | 6 | Blue  | 
    +------+-------------+ 
    | 7 | Red   | 
    +------+-------------+ 
    

    ゴール(最終結果) は、私は可能な限り最も効率的な方法で、最終的に得ることを望んだものです。

    実際には、私はdfAとdfBの両方で5M以上のobsを持ち、dfBで〜50個の一意の値を持つことができます。なぜこれをハードコードするのではなく動的な方法で行う必要があるのか​​を説明します。

    +------+-----+------+ 
    | a_id | Red | Blue | 
    +------+-----+------+ 
    | 1 | 2 | 1 | 
    +------+-----+------+ 
    | 2 | 0 | 0 | 
    +------+-----+------+ 
    | 3 | 3 | 1 | 
    +------+-----+------+ 
    | 4 | 1 | 1 | 
    +------+-----+------+ 
    

答えて

1

まずリストがnumpy.repeatnumpy.concatenateにより平坦化されています。そして、

df = pd.DataFrame({'id':np.repeat(dfA['a_id'], dfA['list_of_b_id'].str.len()), 
        'b': np.concatenate(dfA['list_of_b_id'])}) 

print (df) 
    b  id 
0 2 0000001 
0 3 0000001 
0 7 0000001 
2 1 0000003 
2 2 0000003 
2 3 0000003 
2 4 0000003 
3 6 0000004 
3 7 0000004 

mapカウントのため groupbyのために使用されているdfBから作成Series、によって、unstackによって再形成し、reindexによって欠損値を追加します:

​​
print (df['b'].map(dfB.set_index('b_id')['replacement'])) 
0  Red 
0 Blue 
0  Red 
2  Red 
2  Red 
2 Blue 
2  Red 
3 Blue 
3  Red 
Name: b, dtype: object 
+0

dfAの50KレコードとdfBの5Mレコードのサンプルでは、​​これは0.67分かかりました! – Josh

+0

その良い時間、受け入れてくれてありがとう! – jezrael

0
a = [['2','3','7'],[],['1','2','3','4'],['6','7']] 
    b =['Red','Red','Blue','Red','Green','Blue','Red'] 
    res = [] 
    for line in a: 
    tmp = {} 
    for ele in line: 
     tmp[b[int(ele)-1]] = tmp.get(b[int(ele)-1], 0) +1 
    res.append(tmp) 

    print pd.DataFrame(res).fillna(0) 

    Blue Red 
0 1.0 2.0 
1 0.0 0.0 
2 1.0 3.0 
3 1.0 1.0 
0

使用

In [5611]: dft = (dfA.set_index('a_id')['list_of_b_id'] 
        .apply(pd.Series) 
        .stack() 
        .replace(dfB.set_index('b_id')['replacement']) 
        .reset_index()) 

In [5612]: (dft.groupby(['a_id', 0]).size().unstack() 
       .reindex(dfA['a_id'].unique(), fill_value=0)) 
Out[5612]: 
0  Blue Red 
a_id 
0000001  1 2 
0000002  0 0 
0000003  1 3 
0000004  1 1 

詳細

In [5613]: dft 
Out[5613]: 
     a_id level_1  0 
0 0000001  0 Red 
1 0000001  1 Blue 
2 0000001  2 Red 
3 0000003  0 Red 
4 0000003  1 Red 
5 0000003  2 Blue 
6 0000003  3 Red 
7 0000004  0 Blue 
8 0000004  1 Red 
0

あなたは以下のコード試すことができます。

pd.concat([dfA, dfA.list_of_b_id.apply(lambda x: dfB[dfB.b_id.isin(x)].replacement.value_counts())], axis=1) 
0
d=dfB.set_index('b_id').T.to_dict('r')[0] 

dfA['list_of_b_id']=dfA['list_of_b_id'].apply(lambda x : [d.get(k,k) for k in x]) 
pd.concat([dfA,pd.get_dummies(dfA['list_of_b_id'].apply(pd.Series).stack()).sum(level=0)],axis=1) 


Out[66]: 
     a_id   list_of_b_id Blue Red 
0 0000001  [Red, Blue, Red] 1.0 2.0 
1 0000002      [] NaN NaN 
2 0000003 [Red, Red, Blue, Red] 1.0 3.0 
3 0000004   [Blue, Red] 1.0 1.0 
関連する問題