Вы можете начать с установки столбца Time
в качестве индекса и сортировки его с помощью sort_index
:
df = df.set_index('Time').sort_index()
print(df)
Direction Full Name
Time
2018-08-10 09:16:52 In Uncle Scrooge
2018-08-10 15:04:07 In Donald Duck
2018-08-10 15:06:42 Out Donald Duck
2018-08-10 15:15:49 In Donald Duck
2018-08-10 16:07:57 Out Donald Duck
2018-08-10 16:42:40 Out Uncle Scrooge
И создать отображение (как предлагает @ALollz){'In':1, 'Out':-1}
:
mapper = {'In':1, 'Out':-1}
df = df.assign(Direction_mapped = df.Direction.map(mapper))
Что даст вам:
Direction Full Name Direction_mapped
Time
2018-08-10 09:16:52 In Uncle Scrooge 1
2018-08-10 15:04:07 In Donald Duck 1
2018-08-10 15:06:42 Out Donald Duck -1
2018-08-10 15:15:49 In Donald Duck 1
2018-08-10 16:07:57 Out Donald Duck -1
2018-08-10 16:42:40 Out Uncle Scrooge -1
Сопоставив столбец Направление, вы можете просто применить cumsum
к результату,который даст вам количество людей, начиная с определенного времени:
df = df.assign(n_people = df.Direction_mapped.cumsum()).drop(['Direction_mapped'], axis = 1)
, что дает:
Direction Full Name n_people
Time
2018-08-10 09:16:52 In Uncle Scrooge 1
2018-08-10 15:04:07 In Donald Duck 2
2018-08-10 15:06:42 Out Donald Duck 1
2018-08-10 15:15:49 In Donald Duck 2
2018-08-10 16:07:57 Out Donald Duck 1
2018-08-10 16:42:40 Out Uncle Scrooge 0
Общее решение
Более общее решениена случай, если не все отслеживаются, покидая здание.Давайте попробуем с новым DF, который включает в себя более одного дня.Также давайте смоделируем на этот раз, что Дональд Дак входит дважды, но не отслеживается, выходя во второй раз:
df = pd.DataFrame({'Full Name': ['Uncle Scrooge','Uncle Scrooge', 'Donald Duck', 'Donald Duck', 'Donald Duck',
'Someone else', 'Someone else'],
'Time': ['08-10-2018 09:16:52','08-10-2018 16:42:40', '08-10-2018 15:04:07', '08-10-2018 15:06:42', '08-10-2018 15:15:49',
'08-11-2018 10:42:40', '08-11-2018 10:48:40'],
'Direction': ['In','Out','In','Out', 'In','In', 'Out']})
print(df)
Full Name Time Direction
0 Uncle Scrooge 08-10-2018 09:16:52 In
1 Uncle Scrooge 08-10-2018 16:42:40 Out
2 Donald Duck 08-10-2018 15:04:07 In
3 Donald Duck 08-10-2018 15:06:42 Out
4 Donald Duck 08-10-2018 15:15:49 In
5 Someone else 08-11-2018 10:42:40 In
6 Someone else 08-11-2018 10:48:40 Out
Сначала предыдущая функциональность может быть заключена в функцию
def apply_by_day(x):
mapper = {'In':1, 'Out':-1}
x = x.assign(Direction_mapped = x.Direction.map(mapper))
x = x.assign(n_people = x.Direction_mapped.cumsum())\
.drop(['Direction_mapped'], axis = 1)
return x
И затем apply_by_day
можно применить к ежедневным группам, используя pandas.Grouper
:
df.Time = pd.to_datetime(df.Time)
df = df.set_index('Time').sort_index()
df.groupby(pd.Grouper(freq='D')).apply(lambda x: apply_by_day(x))
Full Name Direction n_people
Time Time
2018-08-10 2018-08-10 09:16:52 Uncle Scrooge In 1
2018-08-10 15:04:07 Donald Duck In 2
2018-08-10 15:06:42 Donald Duck Out 1
2018-08-10 15:15:49 Donald Duck In 2
2018-08-10 16:42:40 Uncle Scrooge Out 1
2018-08-11 2018-08-11 10:42:40 Someone else In 1
2018-08-11 10:48:40 Someone else Out 0
Как показывает результирующий кадр данных, хотя он и не отслеживался, покидая здание на2018-08-10, n_people начинается с 0 на следующий день, так как определенная функция применяется для каждого дня отдельно.