2016-06-23 258 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 *'列:'pd.melt(df,id_vars ='A',value_vars = list(df.columns [1:]),value_name ='C')[[[ 'A', 'C']。dropna()'。我猜测这是更普遍的做法。 – sebap123

+0

@ sebap123,是的,它看起来更好,但它不适用于这组列:'['C1','A','C2','C3',...]' – MaxU

+0

我完全同意。但在这种情况下,我可能会做'list(df.columns [0])+ list(df.columns [2:])''。 – sebap123