Pandas Dataframe:熔化交替的色谱柱组,实现从长到长的转换

时间:2017-03-10 00:46:14

标签: python pandas melt

我希望有人可以帮助我将当前的数据帧从宽格式转换为长格式。我正在使用Pandas 0.18.0,我似乎无法在stackoverflow上找到符合我需要的任何其他解决方案。

非常感谢任何帮助!

我有50个步骤,每个步骤需要融化两个类别(状态/时间),这些类别在我的数据框架中交替。 以下是仅有3套的示例,但此模式会一直持续到50。

状态可以是:是/否/ NaN

时间可以是:timestamp / NaN

当前数据帧:

       cl_id  cl_template_id status-1 time-1                     status-2 time-2                     status-3 time-3                    
0      18434   107            NaN                            NaN  NaN                            NaN  NaN                            NaN
1      18280   117            yes      2016-12-28T18:21:58+00:00  yes      2016-12-28T20:47:31+00:00  yes      2016-12-28T20:47:32+00:00
2      18356   413            yes      2017-01-11T19:23:10+00:00  yes      2017-01-11T19:23:11+00:00  yes      2017-01-11T19:23:11+00:00
3      18358   430            NaN                            NaN  NaN                            NaN  NaN                            NaN
4      18359   430            yes      2017-01-11T19:20:32+00:00  yes      2017-01-11T19:20:34+00:00  NaN                            NaN
.
.
.

目标数据框:

cl_id cl_template_id   step   status   time
18434 107               1      NaN      NaN
18434 107               2      NaN      NaN
18434 107               3      NaN      NaN
18280 117               1      yes      2016-12-28T18:21:58+00:00
18280 117               2      yes      2016-12-28T20:47:31+00:00
18280 117               3      yes      2016-12-28T20:47:32+00:00
18356 413               1      yes      2017-01-11T19:23:10+00:00
18356 413               2      yes      2017-01-11T19:23:11+00:00
18356 413               3      yes      2017-01-11T19:23:11+00:00
.
.
.

2 个答案:

答案 0 :(得分:0)

希望这个答案可以解决这个问题。

首先,我将从您的数据框中重新创建一个示例:

# Make example dataframe
df = pd.DataFrame({'cl_id' : [18434, 18280, 18356, 18358, 18359],
                   'cl_template_id' : [107, 117, 413, 430, 430],
                   'status_1' : [np.NaN, 'yes', 'yes', np.NaN, 'yes'],
                   'time_1' : [np.NaN, '2016-12-28T18:21:58+00:00', '2017-01-11T19:23:10+00:00', np.NaN, '2017-01-11T19:20:32+00:00'],
                   'status_2' : [np.NaN, 'yes', 'yes', np.NaN, 'yes'],
                   'time_2' : [np.NaN, '2016-12-28T20:47:31+00:00', '2017-01-11T19:23:11+00:00', np.NaN, '2017-01-11T19:20:34+00:00'],
                   'status_3' : [np.NaN, 'yes', 'yes', np.NaN, np.NaN],
                   'time_3' : [np.NaN, '2016-12-28T20:47:32+00:00', '2017-01-11T19:23:11+00:00', np.NaN, np.NaN]})

其次,将time_1,2,3转换为日期时间:

# Convert time_1,2,3 to datetime
df.loc[:, 'time_1'] = pd.to_datetime(df.loc[:, 'time_1'])
df.loc[:, 'time_2'] = pd.to_datetime(df.loc[:, 'time_2'])
df.loc[:, 'time_3'] = pd.to_datetime(df.loc[:, 'time_3'])

第三,将数据帧拆分为两个,一个具有状态,另一个具有时间:

# Split df into a status, time dataframe
df_status = df.loc[:, :'status_3']
df_time = df.loc[:, ['cl_id', 'cl_template_id']].merge(df.loc[:, 'time_1':],
                                                       left_index = True,
                                                       right_index = True)

第四,融合状态和时间数据框:

# Melt status
df_status = df_status.melt(id_vars = ['cl_id',
                                      'cl_template_id'],
                           value_vars = ['status_1',
                                         'status_2',
                                         'status_3'],
                           var_name = 'step',
                           value_name = 'status')

# Melt time
df_time = df_time.melt(id_vars = ['cl_id',
                                  'cl_template_id'],
                       value_vars = ['time_1',
                                     'time_2',
                                     'time_3'],
                       var_name = 'step',
                       value_name = 'time')

第五,清理步骤'状态和时间数据框中的列只保留数字:

# Clean step in status, time
df_status.loc[:, 'step'] = df_status.loc[:, 'step'].str.partition('_')[2]
df_time.loc[:, 'step'] = df_time.loc[:, 'step'].str.partition('_')[2]

第六,将状态和时间数据帧合并到最终的数据帧中:

# Merge status, time back together on cl_id, cl_template_id
final = df_status.merge(df_time,
                        how = 'inner',
                        on = ['cl_id',
                              'cl_template_id',
                              'step']).sort_values(by = ['cl_template_id',
                                                         'cl_id']).reset_index(drop = True)

瞧!您正在寻找的答案:

final df

答案 1 :(得分:0)

旧线程,但是我也面临着同样的问题,我认为Ted Petrou的回答可以在这里为您提供完美的帮助:Pandas Melt several groups of columns into multiple target columns by name

pd.wide_to_long(df, stubnames, i, j, sep, suffix) 

简而言之:pd.wide_to_long()函数使您可以指定要取消透视的各个列之间的公共组件。

例如,我的数据框与您的数据框相似,如下所示: pd.wide_to_long to unpivot groups of columns

pd.melt和pd.unstack让您接近,但不允许您使用它们的公分母来定位这些递增的列组。