0

Pandas groupby с подсчетом по бинам

9

У меня есть 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 ответ(ов)

0

Вы можете сгруппировать данные как по бинам, так и по имени пользователя, вычислить размеры групп и затем использовать метод 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

Таким образом, вы получите сводную таблицу, где строки будут соответствовать пользователям, а столбцы — бинам просмотров.

0

Чтобы посчитать значения по группам, лучше всего использовать 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

Таким образом, оба метода позволяют вам эффективно произвести подсчет по группам пользователей и диапазонам просмотров.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь