Pandas - 基于列名称中的多个属性来熔化,堆叠,重塑或MultiIndex数据帧列

时间:2017-10-18 19:57:03

标签: python pandas stack melt

我有一个Pandas数据框,数据格式非常宽......例如:

ID  Equipment   Function    Task    exprt_cond1_time    exprt_cond2_time    exprt_cond1_freq    exprt_cond2_freq    novce_cond1_time    novce_cond2_time    novce_cond1_freq    novce_cond2_freq
0   eq_type_1   Fxn_a       task_1  12                  24                  0.031               0.055               15                  31                  0.042               0.059
1   eq_type_1   Fxn_a       task_2  10                  22                  0.028               0.052               12                  29                  0.039               0.055
2   eq_type_1   Fxn_b       task_3  13                  25                  0.033               0.057               18                  34                  0.047               0.062
3   eq_type_1   Fxn_b       task_4  9                   19                  0.027               0.051               10                  28                  0.038               0.054
4   eq_type_2   Fxn_a       task_1  14                  27                  0.036               0.056               16                  32                  0.043               0.061
5   eq_type_2   Fxn_a       task_2  11                  26                  0.030               0.054               14                  30                  0.041               0.058

但我希望使用列标签中的文本将其转换为更整齐的长格式以创建新列...例如,来自上面的第一行和最后一行的数据可能看起来更像这样:< / p>

ID  Equipment   Function    Task    Experience  Condition   Time    Freq
0   eq_type_1   Fxn_a       task_1  expert      cond1       12      0.031
1   eq_type_1   Fxn_a       task_1  expert      cond2       24      0.055
2   eq_type_1   Fxn_a       task_1  novice      cond1       15      0.042
3   eq_type_1   Fxn_a       task_1  novice      cond2       31      0.059
...
16  eq_type_2   Fxn_a       task_2  expert      cond1       11      0.030
17  eq_type_2   Fxn_a       task_2  expert      cond2       26      0.054
18  eq_type_2   Fxn_a       task_2  novice      cond1       14      0.041
19  eq_type_2   Fxn_a       task_2  novice      cond2       30      0.058

我无法弄清楚融合/叠加/重塑/ MultiIndex或其他翻译功能的正确组合,以使这种情况有效发生,或者我的代码变得丑陋,笨拙,和几乎不可读。 This questionthis question很接近并帮助我一些,但它们似乎只根据标签中的单个属性进行转换。非常喜欢SO社区的任何帮助或提示!

2 个答案:

答案 0 :(得分:7)

让我们尝试pd.wide_to_long两次使用一些列重命名使其成为可能:

rename_d = {'exprt_cond1_time':'Time_exprt_cond1',
        'exprt_cond2_time':'Time_exprt_cond2',
        'exprt_cond1_freq':'Freq_exprt_cond1',
        'exprt_cond2_freq':'Freq_exprt_cond2',
        'novce_cond1_time':'Time_novce_cond1',
        'novce_cond2_time':'Time_novce_cond2',
        'novce_cond1_freq':'Freq_novce_cond1',
        'novce_cond2_freq':'Freq_novce_cond2'}

f = df.rename(columns=rename_d)

df1 = pd.wide_to_long(df, ['Time_exprt','Freq_exprt','Time_novce','Freq_novce'],i=['Equipment','Function','Task'],j='Condition',sep='_',suffix='.')

df1 = df1.reset_index()

df_out = pd.wide_to_long(df1,['Time','Freq'],i=['Equipment','Function','Task','Condition'],j='Experience',sep='_',suffix='').reset_index().drop('ID',axis=1)

输出:

    Equipment Function    Task Condition Experience  Time   Freq
0   eq_type_1    Fxn_a  task_1     cond1    exprt    12  0.031
1   eq_type_1    Fxn_a  task_1     cond1    novce    15  0.042
2   eq_type_1    Fxn_a  task_1     cond2    exprt    24  0.055
3   eq_type_1    Fxn_a  task_1     cond2    novce    31  0.059
4   eq_type_1    Fxn_a  task_2     cond1    exprt    10  0.028
5   eq_type_1    Fxn_a  task_2     cond1    novce    12  0.039
6   eq_type_1    Fxn_a  task_2     cond2    exprt    22  0.052
7   eq_type_1    Fxn_a  task_2     cond2    novce    29  0.055
8   eq_type_1    Fxn_b  task_3     cond1    exprt    13  0.033
9   eq_type_1    Fxn_b  task_3     cond1    novce    18  0.047
10  eq_type_1    Fxn_b  task_3     cond2    exprt    25  0.057
11  eq_type_1    Fxn_b  task_3     cond2    novce    34  0.062
12  eq_type_1    Fxn_b  task_4     cond1    exprt     9  0.027
13  eq_type_1    Fxn_b  task_4     cond1    novce    10  0.038
14  eq_type_1    Fxn_b  task_4     cond2    exprt    19  0.051
15  eq_type_1    Fxn_b  task_4     cond2    novce    28  0.054
16  eq_type_2    Fxn_a  task_1     cond1    exprt    14  0.036
17  eq_type_2    Fxn_a  task_1     cond1    novce    16  0.043
18  eq_type_2    Fxn_a  task_1     cond2    exprt    27  0.056
19  eq_type_2    Fxn_a  task_1     cond2    novce    32  0.061
20  eq_type_2    Fxn_a  task_2     cond1    exprt    11  0.030
21  eq_type_2    Fxn_a  task_2     cond1    novce    14  0.041
22  eq_type_2    Fxn_a  task_2     cond2    exprt    26  0.054
23  eq_type_2    Fxn_a  task_2     cond2    novce    30  0.058

pd.wide_to_long处理熊猫中的“同时融化”。首先,我们需要重命名这些列以使pd.wide_to_long中的stubnames工作。

答案 1 :(得分:2)

这是我的尝试 - 我只尝试使用pd.wide_to_long一次:

import re

cols = ['Equipment', 'Function', 'Task']

renamer = lambda c: re.sub(r'([^_]*)_(cond\d+)_(time|freq)', r'\3_\1_\2', c)

r = pd.wide_to_long(df.drop('ID',1).rename(columns=renamer),
                    stubnames=['time','freq'], i=cols, j='Measures',
                    sep='_',suffix='(?:exprt|novce)_cond\d+') \
      .reset_index()

r[['Experience','Condition']] = r.pop('Measures').str.split('_', expand=True)

结果:

In [192]: r
Out[192]:
    Equipment Function    Task  time   freq Experience Condition
0   eq_type_1    Fxn_a  task_1    12  0.031      exprt     cond1
1   eq_type_1    Fxn_a  task_1    24  0.055      exprt     cond2
2   eq_type_1    Fxn_a  task_1    15  0.042      novce     cond1
3   eq_type_1    Fxn_a  task_1    31  0.059      novce     cond2
4   eq_type_1    Fxn_a  task_2    10  0.028      exprt     cond1
5   eq_type_1    Fxn_a  task_2    22  0.052      exprt     cond2
6   eq_type_1    Fxn_a  task_2    12  0.039      novce     cond1
7   eq_type_1    Fxn_a  task_2    29  0.055      novce     cond2
8   eq_type_1    Fxn_b  task_3    13  0.033      exprt     cond1
9   eq_type_1    Fxn_b  task_3    25  0.057      exprt     cond2
10  eq_type_1    Fxn_b  task_3    18  0.047      novce     cond1
11  eq_type_1    Fxn_b  task_3    34  0.062      novce     cond2
12  eq_type_1    Fxn_b  task_4     9  0.027      exprt     cond1
13  eq_type_1    Fxn_b  task_4    19  0.051      exprt     cond2
14  eq_type_1    Fxn_b  task_4    10  0.038      novce     cond1
15  eq_type_1    Fxn_b  task_4    28  0.054      novce     cond2
16  eq_type_2    Fxn_a  task_1    14  0.036      exprt     cond1
17  eq_type_2    Fxn_a  task_1    27  0.056      exprt     cond2
18  eq_type_2    Fxn_a  task_1    16  0.043      novce     cond1
19  eq_type_2    Fxn_a  task_1    32  0.061      novce     cond2
20  eq_type_2    Fxn_a  task_2    11  0.030      exprt     cond1
21  eq_type_2    Fxn_a  task_2    26  0.054      exprt     cond2
22  eq_type_2    Fxn_a  task_2    14  0.041      novce     cond1
23  eq_type_2    Fxn_a  task_2    30  0.058      novce     cond2

说明:

In [198]: df.drop('ID',1).rename(columns=renamer)
Out[198]:
   Equipment Function    Task  time_exprt_cond1  time_exprt_cond2  freq_exprt_cond1  freq_exprt_cond2  time_novce_cond1  \
0  eq_type_1    Fxn_a  task_1                12                24             0.031             0.055                15
1  eq_type_1    Fxn_a  task_2                10                22             0.028             0.052                12
2  eq_type_1    Fxn_b  task_3                13                25             0.033             0.057                18
3  eq_type_1    Fxn_b  task_4                 9                19             0.027             0.051                10
4  eq_type_2    Fxn_a  task_1                14                27             0.036             0.056                16
5  eq_type_2    Fxn_a  task_2                11                26             0.030             0.054                14

   time_novce_cond2  freq_novce_cond1  freq_novce_cond2
0                31             0.042             0.059
1                29             0.039             0.055
2                34             0.047             0.062
3                28             0.038             0.054
4                32             0.043             0.061
5                30             0.041             0.058

In [199]: pd.wide_to_long(df.drop('ID',1).rename(columns=renamer),
     ...:                 stubnames=['time','freq'], i=cols,j='Measures',
     ...:                 sep='_',suffix='(?:exprt|novce)_cond\d+') \
     ...:   .reset_index()
     ...:
Out[199]:
    Equipment Function    Task     Measures  time   freq
0   eq_type_1    Fxn_a  task_1  exprt_cond1    12  0.031
1   eq_type_1    Fxn_a  task_1  exprt_cond2    24  0.055
2   eq_type_1    Fxn_a  task_1  novce_cond1    15  0.042
3   eq_type_1    Fxn_a  task_1  novce_cond2    31  0.059
4   eq_type_1    Fxn_a  task_2  exprt_cond1    10  0.028
5   eq_type_1    Fxn_a  task_2  exprt_cond2    22  0.052
6   eq_type_1    Fxn_a  task_2  novce_cond1    12  0.039
7   eq_type_1    Fxn_a  task_2  novce_cond2    29  0.055
8   eq_type_1    Fxn_b  task_3  exprt_cond1    13  0.033
9   eq_type_1    Fxn_b  task_3  exprt_cond2    25  0.057
10  eq_type_1    Fxn_b  task_3  novce_cond1    18  0.047
11  eq_type_1    Fxn_b  task_3  novce_cond2    34  0.062
12  eq_type_1    Fxn_b  task_4  exprt_cond1     9  0.027
13  eq_type_1    Fxn_b  task_4  exprt_cond2    19  0.051
14  eq_type_1    Fxn_b  task_4  novce_cond1    10  0.038
15  eq_type_1    Fxn_b  task_4  novce_cond2    28  0.054
16  eq_type_2    Fxn_a  task_1  exprt_cond1    14  0.036
17  eq_type_2    Fxn_a  task_1  exprt_cond2    27  0.056
18  eq_type_2    Fxn_a  task_1  novce_cond1    16  0.043
19  eq_type_2    Fxn_a  task_1  novce_cond2    32  0.061
20  eq_type_2    Fxn_a  task_2  exprt_cond1    11  0.030
21  eq_type_2    Fxn_a  task_2  exprt_cond2    26  0.054
22  eq_type_2    Fxn_a  task_2  novce_cond1    14  0.041
23  eq_type_2    Fxn_a  task_2  novce_cond2    30  0.058