2016-06-23 9 views
3

現在、単一のpanadas DataFrame行を複数のわずかに変更された行に分割する効率的な方法を見つけようとしています。このような構造を想像:パンダでDataFrame行を分割する

A C1 C2 C3 C4 
1 a b c a 
2 b a e b a 
3 g c 
4 d e 

と私はそのような構造で終わるしたい:

A C 
1 a b 
2 a c 
3 a a 
4 b a 
5 b e 
6 b b 
7 b a 
8 g c 
9 d e 
10 d e 

これまでのところ、私はループに使用して、そのような辞書を作成してきた(DFが私のデータフレームです):

rows = [] 
for i, r in df.iterrows(): 
    tmp = r[1:].dropna() 
    for c in tmp.values: 
    dict = {'A': r[0], 'C': c} 
    rows.append(dict) 

残念ながら、このアプローチは非常に遅いです。これまでのところ、パンダを使って作業した後、実行時間を大幅に改善することができますが、このケースをより速くする方法を理解するための多くの経験はありません。

これをスピードアップするために何かアドバイスできますか?

答えて

3

はこの試してみてください。

In [10]: pd.melt(df, id_vars='A', value_vars=['C1','C2','C3','C4']) 
Out[10]: 
    A variable value 
0 a  C1  b 
1 b  C1  a 
2 g  C1  c 
3 d  C1  e 
4 a  C2  c 
5 b  C2  e 
6 g  C2 NaN 
7 d  C2 NaN 
8 a  C3  a 
9 b  C3  b 
10 g  C3 NaN 
11 d  C3 NaN 
12 a  C4 NaN 
13 b  C4  a 
14 g  C4 NaN 
15 d  C4 NaN 

あなたがNaNのを取り除くしたい場合:

In [15]: pd.melt(df, id_vars='A', value_vars=['C1','C2','C3','C4'], value_name='C')[['A','C']].dropna() 
Out[15]: 
    A C 
0 a b 
1 b a 
2 g c 
3 d e 
4 a c 
5 b e 
8 a a 
9 b b 
13 b a 

同じですが、動的にC*列を選択:

In [21]: (pd.melt(df, id_vars='A', 
    ....:   value_vars=df.filter(like='C').columns.tolist(), 
    ....:   value_name='C')[['A','C']] 
    ....: .dropna() 
    ....:) 
Out[21]: 
    A C 
0 a b 
1 b a 
2 g c 
3 d e 
4 a c 
5 b e 
8 a a 
9 b b 
13 b a 
+0

をいただき、誠にありがとうございます素晴らしい答え。私はすべての 'C *'列を選択するためのアプローチをいくつか作成しました: 'pdmelt(df、id_vars = 'A'、value_vars = list(df.columns [1:])、value_name = 'C' 'A'、 'C​​']]。dropna() '。それは私が推測するより普遍的なアプローチです。 – sebap123

+0

@ sebap123、はい、それは良く見えますが、この列のセットでは機能しません: '['C1'、 'A'、 'C​​2'、C3 '、...]' – MaxU

+0

私は全く同意します。しかし、このような場合は、おそらく 'list(df.columns [0])+ list(df.columns [2:])'を実行します。 – sebap123

関連する問題