Вы можете повернуть и найти timedelta
new_df = df.pivot('user_id', 'step', 'date').drop('step1', 1).reset_index()
new_df.columns.name = None
new_df['time (end-start)'] = (new_df['end'] - new_df['start']).astype('timedelta64[m]')
user_id end start time (end-start)
0 1 2018-04-17 15:29:07 2018-04-17 15:27:07 2.0
1 2 2018-05-17 15:30:07 2018-05-17 15:28:07 2.0
Редактировать: для фрейма данных с повторяющимися записями, например:
user_id step date
0 1 start 2018-04-17 15:27:07
1 1 step1 2018-04-17 15:28:07
2 1 end 2018-04-17 15:29:07
3 1 end 2018-04-17 15:32:07
4 2 start 2018-05-17 15:26:07
5 2 start 2018-05-17 15:28:07
6 2 step1 2018-05-17 15:29:07
7 2 end 2018-05-17 15:30:07
new_df = df.pivot_table(index = 'user_id', columns = 'step', values = 'date', aggfunc = 'first').drop('step1', 1).reset_index()
new_df.columns.name = None
new_df['time (end-start)'] = (new_df['end'] - new_df['start']).astype('timedelta64[m]')
Вы получаете
user_id end start time (end-start)
0 1 2018-04-17 15:29:07 2018-04-17 15:27:07 2.0
1 2 2018-05-17 15:30:07 2018-05-17 15:26:07 4.0