Мои оригинальные панды DataFrame выглядит следующим образом:
df =
Person_ID | trip_purpose | trip_start_time | trip_end_time
-----------------------------------------------------------
1 | 'Work' | 05:40:00 | 05:42:00
2 | 'School' | 06:40:00 | 06:45:00
1 | 'Leisure' | 05:52:00 | 06:37:00
1 | 'Home' | 06:40:00 | 06:49:00
...
Первый шаг: группировка по Person_ID:
df = df.groupby('Person_ID').agg(lambda x : ','.join(x).split(','))
# this is faster than grouping by .agg(list)
Результат группировки:
Person_ID | trip_purpose | trip_start_time | trip_end_time
---------------------------------------------------------------
| ['Work', | [05:40:00, | [05:42:00,
1 | 'Leisure', | 05:52:00, | 06:37:00,
| 'Home'] | 06:40:00] | 06:49:00]
| | |
2 | ['School'] | [06:40:00 ] | [06:45:00]
...
InНа следующем шаге я хочу рассчитать время, которое человек потратил на каждое занятие между поездками, и записать его в определенный столбец.Так как мои агенты начинают свой день дома, кулачная деятельность всегда "живая", что означает, что это duration_activity_1
дается первым временем начала
pd.to_timedelta(df['trip_start_time'].apply(lambda x: x[0]))
.
Это означает, что еслиЧеловек 1 совершает 3 поездки, у него 4 действия, потому что он / она начинает дома.
Последнее действие длится до полуночи, то есть оно рассчитывается по
pd.to_datetime("23:59:59") - pd.to_datetime(df['trip_end_time').apply(lambda x: x[-1]))
Все длительности действий между первым и последним рассчитываются путем вычитания времени начала текущей поездки за вычетом времени окончания последней поездки:
pd.to_timedelta(df['trip_start_time'].apply(lambda x: x[i])) - pd.to_timedelta(df['trip_end_time'].apply(lambda x: x[i - 1]))]
Вот чтоэто должно выглядеть так:
Person_ID | trip_purpose | trip_start_time | trip_end_time | duration_activity_1 | duration_activity_2 | duration_activity_3 | duration_activity_4 | ...
------------------------------------------------------------------------------------------------------------------------------------------------------------
| ['Work', | [05:40:00, | [05:42:00, | | | | |
1 | 'Leisure', | 05:52:00, | 06:37:00, | 05:40:00 | 00:10:00 | 00:03:00 | 17:14:00 |
| 'Home'] | 06:40:00] | 06:49:00] | | | | |
| | | | | | | |
2 | ['School'] | [06:40:00 ] | [06:45:00] | 06:40:00 | 17:15:00 | nan | nan |
...
Поскольку я хочу вычислить скалярным способом, и у меня есть более одного условия, о котором я подумал numpy.select()
:
import numpy as np
import pandas as pd
for i in range(maximum_number_of_activities):
condlist = [i == 0, # first activity
i == df["trip_purpose"].apply(len), # last activity
(i > 0) & (i < df["trip_purpose"].apply(len))] # other activities
choicelist = [pd.to_timedelta(df["trip_start_time"].apply(lambda x: x[0])), # first activity starts at midnight and ends with the first trip
pd.to_datetime("23:59:59") - pd.to_datetime(df["trip_end_time"].apply(lambda x: x[-1])), # last activity starts with the last trip and ends at midnight
pd.to_timedelta(df["trip_start_time"].apply(lambda x: x[i])) - pd.to_timedelta(df["trip_end_time"].apply(lambda x: x[i - 1]))] # all other activities are calculated by substracting the start time of the current trip minus the end time of the last trip
default = np.nan
print(pd.DataFrame(np.select(condlist=condlist,
choicelist=choicelist,
default=default),
columns=[i]))
# I'm aware that this code is not assigning it to the original DataFrame.
А вот мойпроблема: я получаю IndexError: list index out of range
Я полагаю, это как-то связано с 3-м условием в choicelist
.Я полагаю, что даже если я поймаю случаи i == 0
и i == df["trip_purpose"].apply(len)
, я не смогу использовать индексную переменную i
, потому что 3-е условие не будет выполнено?!?(Я получаю тот же результат, если я пишу choicelist
непосредственно в функцию np.select
.)
Можете ли вы найти решение этого или альтернативного способа получить желаемый DataFrame?Буду очень признателен за вашу помощь.