#python #pandas
Вопрос:
У меня есть следующие панды dataframe
—
EventID Institution_Name
TimeCreated
2021-03-22 15:34:46 40 H1
2021-03-22 18:17:19 40 H2
2021-03-22 20:37:47 40 H2
2021-03-22 20:40:20 40 H2
2021-03-22 21:37:32 40 H2
2021-03-22 22:16:32 40 H2
2021-03-22 23:19:49 40 H2
2021-03-22 23:26:40 40 H2
2021-03-23 00:26:03 40 H3
2021-03-23 01:25:43 40 H4
2021-03-23 04:00:24 40 H5
2021-03-23 13:09:42 40 H6
2021-03-23 13:13:23 40 H1
2021-03-23 15:49:33 40 H7
2021-03-23 17:22:30 40 H8
2021-03-23 17:22:37 40 H8
2021-03-23 17:23:49 40 H9
2021-03-23 18:19:56 40 H2
2021-03-23 18:22:14 40 H2
2021-03-23 18:52:36 40 H10
Я хочу подсчитывать количество событий для каждого учреждения каждый день и сортировать количество в порядке убывания, сохраняя дни в порядке возрастания.
например, конечный результат будет выглядеть примерно так —
TimeCreated Institution_Name EventID_count
2021-03-22 H2 7
2021-03-22 H1 1
....
2021-03-23 H2 2
and so on
Я использую следующее —
grouper = df.groupby([pd.Grouper(freq='1D'), 'Institution_Name'])
grouper['EventID'].count().reset_index().sort_values(['TimeCreated'],ascending=True).sort_values('EventID', ascending=False).head(5)
but this does not give the desired result.
Ответ №1:
- Сгруппируйте по 2 столбцам
grouper = df.groupby([pd.Grouper(key='TimeCreated', freq='1D'), 'Institution_Name'])
grouper = grouper.count().groupby('TimeCreated', group_keys=False)
- Отсортируйте элементы(количество) в каждой группе дат
grouper_count_desc = grouper.apply(lambda x: x.sort_values(by='EventID', ascending=False))
In[65]: grouper_count_desc
Out[65]:
EventID
TimeCreated Institution_Name
2021-03-22 H2 7
H1 1
2021-03-23 H2 2
H8 2
H1 1
H10 1
H3 1
H4 1
H5 1
H6 1
H7 1
H9 1
- Отсортируйте группы по дате. Порядок элементов в каждой группе не изменится
grouper_date_asc = grouper_count_desc.sort_values(by='TimeCreated', ascending=True)
In[70]: grouper_date_desc = grouper_count_desc.sort_values(by='TimeCreated', ascending=False) # to show result, I used descending
In[71]: grouper_date_desc
Out[71]:
EventID
TimeCreated Institution_Name
2021-03-23 H2 2
H8 2
H1 1
H10 1
H3 1
H4 1
H5 1
H6 1
H7 1
H9 1
2021-03-22 H2 7
H1 1
- Сбросить индекс и показать результат
print(grouper_date_asc.reset_index())
Ответ №2:
Вы можете использовать dt.normalize()
, чтобы получить дату для группировки. Агрегируйте подсчет по .GroupBy.agg()
столбцам, а затем отсортируйте их следующим образом:
(df.groupby([df['TimeCreated'].dt.normalize(),
'Institution_Name'])
.agg(EventID_count=('EventID', 'count'))
.reset_index()
.sort_values(['TimeCreated', 'Institution_Name'], ascending=[True, False], ignore_index=True)
)
Если у вас TimeCreated
есть индекс, вы можете использовать df.index.normalize()
его следующим образом:
(df.groupby([df.index.normalize(),
'Institution_Name'])
.agg(EvenetID_count=('EventID', 'count'))
.reset_index()
.sort_values(['TimeCreated', 'Institution_Name'], ascending=[True, False], ignore_index=True)
)
Результат:
TimeCreated Institution_Name EventID_count
0 2021-03-22 H2 7
1 2021-03-22 H1 1
2 2021-03-23 H9 1
3 2021-03-23 H8 2
4 2021-03-23 H7 1
5 2021-03-23 H6 1
6 2021-03-23 H5 1
7 2021-03-23 H4 1
8 2021-03-23 H3 1
9 2021-03-23 H2 2
10 2021-03-23 H10 1
11 2021-03-23 H1 1
Ваш код на самом деле довольно близок (для случая TimeCreated
это индекс), просто нужно изменить способ сортировки столбцов, как показано ниже:
grouper = df.groupby([pd.Grouper(freq='1D'), 'Institution_Name'])
grouper['EventID'].count().reset_index().sort_values(['TimeCreated', 'Institution_Name'], ascending=[True, False], ignore_index=True)
Результат этих кодов такой же, как и выше, за исключением того, что имя столбца для EventID
остается как EventID
вместо EventID_count
.
Ответ №3:
Вы можете использовать pandas.Series.dt.floor
:
(df.groupby([df['TimeCreated'].dt.floor('d'),
'Institution_Name'])
[['EventID']].count()
.add_suffix('_count')
.sort_values(['TimeCreated', 'Institution_Name'], ascending=[True, False])
.reset_index()
)
выход:
TimeCreated Institution_Name EventID_count
0 2021-03-22 H2 7
1 2021-03-22 H1 1
2 2021-03-23 H9 1
3 2021-03-23 H8 2
4 2021-03-23 H7 1
5 2021-03-23 H6 1
6 2021-03-23 H5 1
7 2021-03-23 H4 1
8 2021-03-23 H3 1
9 2021-03-23 H2 2
10 2021-03-23 H10 1
11 2021-03-23 H1 1
Ваша первоначальная попытка не сработала, так как Grouper не знал, где найти ваши даты (по умолчанию он использует индекс). Вот два способа исправить это.
определите имя столбца:
(df.groupby([pd.Grouper(freq='1D', key='TimeCreated'),
'Institution_Name'])
[['EventID']].count()
.add_suffix('_count')
.sort_values(['TimeCreated', 'Institution_Name'], ascending=[True, False])
.reset_index()
)
используйте столбец в качестве индекса:
(df.set_index('TimeCreated')
.groupby([pd.Grouper(freq='1D'),
'Institution_Name'])
[['EventID']].count()
.add_suffix('_count')
.sort_values(['TimeCreated', 'Institution_Name'], ascending=[True, False])
.reset_index()
)
Комментарии:
1. EventID_count должен быть в порядке убывания, в то время как дата должна быть в порядке возрастания одновременно. Посмотрите на мои результаты.