我希望有人可以帮助我将当前的数据帧从宽格式转换为长格式。我正在使用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
.
.
.
答案 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)
瞧!您正在寻找的答案:
答案 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.melt和pd.unstack让您接近,但不允许您使用它们的公分母来定位这些递增的列组。