Pandas groupby с подсчетом по бинам
У меня есть DataFrame, который выглядит следующим образом:
+----------+---------+-------+
| username | post_id | views |
+----------+---------+-------+
| john | 1 | 3 |
| john | 2 | 23 |
| john | 3 | 44 |
| john | 4 | 82 |
| jane | 7 | 5 |
| jane | 8 | 25 |
| jane | 9 | 46 |
| jane | 10 | 56 |
+----------+---------+-------+
Я хотел бы преобразовать его, чтобы подсчитать количество просмотров, относящихся к определённым диапазонам, примерно так:
+------+------+-------+-------+--------+
| | 1-10 | 11-25 | 25-50 | 51-100 |
+------+------+-------+-------+--------+
| john | 1 | 1 | 1 | 1 |
| jane | 1 | 1 | 1 | 1 |
+------+------+-------+-------+--------+
Я пробовал следующий код:
bins = [1, 10, 25, 50, 100]
groups = df.groupby(pd.cut(df.views, bins))
groups.username.count()
Но он возвращает только агрегированные данные, а не количество по пользователям. Как я могу получить подсчёт для каждого диапазона по пользователям?
Аggregированные данные (при использовании моих реальных данных) выглядят так:
impressions
(2500, 5000] 2332
(5000, 10000] 1118
(10000, 50000] 570
(50000, 10000000] 14
Name: username, dtype: int64
2 ответ(ов)
Вы можете сгруппировать данные как по бинам, так и по имени пользователя, вычислить размеры групп и затем использовать метод unstack()
:
>>> groups = df.groupby(['username', pd.cut(df.views, bins)])
>>> groups.size().unstack()
views (1, 10] (10, 25] (25, 50] (50, 100]
username
jane 1 1 1 1
john 1 1 1 1
Таким образом, вы получите сводную таблицу, где строки будут соответствовать пользователям, а столбцы — бинам просмотров.
Чтобы посчитать значения по группам, лучше всего использовать pd.crosstab
:
bins = [1, 10, 25, 50, 100]
pd.crosstab(df['username'], pd.cut(df['views'], bins))
Также можно воспользоваться эквивалентом — pivot_table
, который работает аналогично:
df.pivot_table(index='username', columns=pd.cut(df['views'], bins), aggfunc='size')
Чтобы убрать названия индексов, можно использовать метод rename_axis()
:
pd.crosstab(df['username'], pd.cut(df['views'], bins)).rename_axis(columns=None, index=None)
В результате вы получите таблицу, похожую на эту:
(1, 10] (10, 25] (25, 50] (50, 100]
jane 1 1 1 1
john 1 1 1 1
Таким образом, оба метода позволяют вам эффективно произвести подсчет по группам пользователей и диапазонам просмотров.
Получить статистику для каждой группы (например, количество, среднее и т.д.) с помощью pandas GroupBy?
Преобразование вывода GroupBy с многоуровневым индексом в Series обратно в DataFrame в Pandas
Как изменить порядок столбцов в DataFrame?
Установить значение для конкретной ячейки в DataFrame pandas с использованием индекса
Выбор строки из pandas Series/DataFrame по целочисленному индексу