Как сгруппировать записи DataFrame pandas по дате в неуникальном столбце

82

Pandas DataFrameсодержит столбец с именем, "date"который содержит неуникальные datetimeзначения. Я могу сгруппировать строки в этом кадре, используя:

data.groupby(data['date'])

Однако при этом данные разбиваются по datetimeзначениям. Я хотел бы сгруппировать эти данные по годам, хранящимся в столбце «Дата». На этой странице показано, как группировать по годам в случаях, когда отметка времени используется в качестве индекса, что в моем случае неверно.

Как мне добиться этой группировки?

Борис Горелик
источник
Для тех, кто приезжает сюда в 2017+, есть несколько новых способов группироваться по определенному количеству времени. См. Этот ответ ниже
Тед Петру

Ответы:

91

Я использую панды 0.16.2. Это дает лучшую производительность для моего большого набора данных:

data.groupby(data.date.dt.year)

Используя dtопцию и играть с weekofyear, и dayofweekт.д. становится гораздо проще.

DACW
источник
Согласитесь, это похоже на пандаический способ доступа к атрибутам даты для серии.
dancow
74

Решение ecatmur подойдет. Тем не менее, это будет лучше для больших наборов данных:

data.groupby(data['date'].map(lambda x: x.year))
Уэс МакКинни
источник
9
Почему карта вместо применения?
Gus
1
Afaik mapобычно обладает некоторыми хорошими качествами эффективности при применении произвольных функций по сравнению с простым использованием apply.
Coolio2654
25

Это может быть проще объяснить на примере набора данных.

Создать образец данных

Давайте предположим , что у нас есть один столбец отметки времени, dateи еще один столбец , мы хотели бы выполнить агрегацию на, a.

df = pd.DataFrame({'date':pd.DatetimeIndex(['2012-1-1', '2012-6-1', '2015-1-1', '2015-2-1', '2015-3-1']),
                   'a':[9,5,1,2,3]}, columns=['date', 'a'])

df

        date  a
0 2012-01-01  9
1 2012-06-01  5
2 2015-01-01  1
3 2015-02-01  2
4 2015-03-01  3

Есть несколько способов сгруппировать по годам

  • Используйте метод доступа dt со yearсвойством
  • Поместите dateиндекс и используйте анонимную функцию для доступа к году
  • resampleМетод использования
  • Преобразовать в период панд

.dtаксессуар со yearсвойством

Когда у вас есть столбец (а не индекс) временных меток pandas, вы можете получить доступ ко многим дополнительным свойствам и методам с помощью средства dtдоступа. Например:

df['date'].dt.year

0    2012
1    2012
2    2015
3    2015
4    2015
Name: date, dtype: int64

Мы можем использовать это для формирования наших групп и вычисления некоторых агрегатов для определенного столбца:

df.groupby(df['date'].dt.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
date                
2012   14     7    9
2015    6     2    3

поместите дату в индекс и используйте анонимную функцию для доступа к году

Если вы установите столбец даты в качестве индекса, он станет DateTimeIndex с теми же свойствами и методами, что и средство dtдоступа дает обычные столбцы.

df1 = df.set_index('date')
df1.index.year

Int64Index([2012, 2012, 2015, 2015, 2015], dtype='int64', name='date')

Интересно, что при использовании метода groupby вы можете передать ему функцию. Этой функции будет неявно передан индекс DataFrame. Итак, мы можем получить тот же результат сверху со следующим:

df1.groupby(lambda x: x.year)['a'].agg(['sum', 'mean', 'max'])

      sum  mean  max
2012   14     7    9
2015    6     2    3

Используйте resampleметод

Если столбец даты отсутствует в индексе, необходимо указать столбец с onпараметром. Вам также необходимо указать псевдоним смещения в виде строки.

df.resample('AS', on='date')['a'].agg(['sum', 'mean', 'max'])

             sum  mean  max
date                       
2012-01-01  14.0   7.0  9.0
2013-01-01   NaN   NaN  NaN
2014-01-01   NaN   NaN  NaN
2015-01-01   6.0   2.0  3.0

Преобразовать в период панд

Вы также можете преобразовать столбец даты в объект Pandas Period. Мы должны передать псевдоним смещения в виде строки, чтобы определить длину периода.

df['date'].dt.to_period('A')

0   2012
1   2012
2   2015
3   2015
4   2015
Name: date, dtype: object

Затем мы можем использовать это как группу

df.groupby(df['date'].dt.to_period('Y'))['a'].agg(['sum', 'mean', 'max'])


      sum  mean  max
2012   14     7    9
2015    6     2    3
Тед Петру
источник
В последнем методе, который вы использовали to_period('A'), для чего это («А»)?
shiv_90 06
2
@ Shiv_90 'A'это псевдоним смещения таймсерии: pandas.pydata.org/pandas-docs/stable/…
ptim 07
Какой метод вы бы порекомендовали, если нужно сохранить отдельный столбец «Дата»? Например, если я запускаю простой .dt.yearметод и сохраняю его в новом фрейме данных, даты сохраняются как индексы, и это становится проблематичным, если, скажем, мне нужно построить данные, потому что столбца «даты» на самом деле нет, а есть только три предоставлено.agg()
shiv_90 07
13

Это должно работать:

data.groupby(lambda x: data['date'][x].year)
Ecatmur
источник
0

это тоже будет работать

data.groupby(data['date'].dt.year)

Четан Кабра
источник
Должно работать, но при выполнении выводит местоположение объекта в памяти, но не выводит реальных результатов. <pandas.core.groupby.DataFrameGroupBy object at 0x10d7f6438>это то, что я получаю при исполнении.
shiv_90 06