Как группировать и подсчитывать строки по месяцам и годам с помощью Pandas?

У меня есть набор данных с личными данными, такими как имя, высота, вес и дата рождения. Я бы построил график с количеством людей, родившихся в конкретный месяц и год. Я использую python pandas, чтобы выполнить это, и моя стратегия заключалась в том, чтобы пытаться группировать по годам и месяцам и добавлять счетчик. Но самое близкое, что я получил, - это подсчитать количество людей по годам или месяцам, но не тем и другим.

df['birthdate'].groupby(df.birthdate.dt.year).agg('count')

Другие вопросы в stackoverflow указывают на группу, называемую TimeGrouper, но поиск в документации pandas ничего не нашел. Любая идея?

Ответ 1

Чтобы сгруппировать по нескольким критериям, передайте список столбцов или критериев:

df['birthdate'].groupby([df.birthdate.dt.year, df.birthdate.dt.month]).agg('count')

Пример:

In [165]:
df = pd.DataFrame({'birthdate':pd.date_range(start=dt.datetime(2015,12,20),end=dt.datetime(2016,3,1))})
df.groupby([df['birthdate'].dt.year, df['birthdate'].dt.month]).agg({'count'})

Out[165]:
                    birthdate
                        count
birthdate birthdate          
2015      12               12
2016      1                31
          2                29
          3                 1

ОБНОВИТЬ

Начиная с версии 0.23.0 приведенный выше код больше не работает из-за ограничения на то, что имена 0.23.0 уровней должны быть уникальными, теперь вам нужно rename уровни, чтобы это работало:

In[107]:
df.groupby([df['birthdate'].dt.year.rename('year'), df['birthdate'].dt.month.rename('month')]).agg({'count'})

Out[107]: 
           birthdate
               count
year month          
2015 12           12
2016 1            31
     2            29
     3             1

Ответ 2

Вы также можете использовать "месячный" период с to_period с to_period dt:

In [11]: df = pd.DataFrame({'birthdate': pd.date_range(start='20-12-2015', end='3-1-2016')})

In [12]: df['birthdate'].groupby(df.birthdate.dt.to_period("M")).agg('count')
Out[12]:
birthdate
2015-12    12
2016-01    31
2016-02    29
2016-03     1
Freq: M, Name: birthdate, dtype: int64

Стоит отметить, что если datetime является индексом (а не столбцом), вы можете использовать resample:

df.resample("M").count()

Ответ 3

Другим решением является установка birthdate в качестве индекса и повторной выборки:

import pandas as pd

df = pd.DataFrame({'birthdate': pd.date_range(start='20-12-2015', end='3-1-2016')})
df.set_index('birthdate').resample('MS').size()

Вывод:

birthdate
2015-12-01    12
2016-01-01    31
2016-02-01    29
2016-03-01     1
Freq: MS, dtype: int64

Ответ 4

По состоянию на апрель 2019 года: это будет работать. Версия для панд - 0.24.x

df.groupby([df.dates.dt.year.rename('year'), df.dates.dt.month.rename('month')]).size()

Ответ 5

Замените поля даты и количества соответствующими именами столбцов. Этот фрагмент кода будет группировать, суммировать и сортировать на основе заданных параметров. Вы также можете изменить частоту на 1M или 2M и так далее...

df[['date', 'count']].groupby(pd.Grouper(key='date', freq='1M')).sum().sort_values(by='date', ascending=True)['count']