pandas dataframe groupby datetime mes


90

Considere un archivo csv:

string,date,number
a string,2/5/11 9:16am,1.0
a string,3/5/11 10:44pm,2.0
a string,4/22/11 12:07pm,3.0
a string,4/22/11 12:10pm,4.0
a string,4/29/11 11:59am,1.0
a string,5/2/11 1:41pm,2.0
a string,5/2/11 2:02pm,3.0
a string,5/2/11 2:56pm,4.0
a string,5/2/11 3:00pm,5.0
a string,5/2/14 3:02pm,6.0
a string,5/2/14 3:18pm,7.0

Puedo leer esto y reformatear la columna de fecha en formato de fecha y hora:

b=pd.read_csv('b.dat')
b['date']=pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')

He intentado agrupar los datos por mes. Parece que debería haber una forma obvia de acceder al mes y agrupar por eso. Pero parece que no puedo hacerlo. ¿Alguien sabe cómo?

Lo que estoy intentando actualmente es volver a indexar por la fecha:

b.index=b['date']

Puedo acceder al mes así:

b.index.month

Sin embargo, parece que no puedo encontrar una función para agrupar por mes.

Respuestas:


174

Conseguido hacerlo:

b = pd.read_csv('b.dat')
b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')
b.groupby(by=[b.index.month, b.index.year])

O

b.groupby(pd.Grouper(freq='M'))  # update for v0.21+

52
Creo que las formas más pandónicas son usar resample(cuando proporciona la funcionalidad que necesita) o usar TimeGrouper:df.groupby(pd.TimeGrouper(freq='M'))
— Karl D.

10
para obtener la suma o el promedio de DataFrame del resultado, df.groupby(pd.TimeGrouper(freq='M')).sum()odf.groupby(pd.TimeGrouper(freq='M')).mean()
— Alexandre

9
pd.TimeGrouperha quedado en desuso en favor de pd.Grouper, que es un poco más flexible, pero todavía toma freqy levelargumentos.
— BallpointBen

el primer método no parece funcionar. Da el error, 'El objeto Serie no tiene atributo' mes '' para una Serie creada a través de to_datetime.
— Ely

1
@ely La respuesta se basa implícitamente en las líneas de la pregunta original donde bse le da un índice después de leerse desde CSV. Agregue b.index = pd.to_datetime(b['date'],format='%m/%d/%y %I:%M%p')después de la línea b = pd.read_csv('b.dat'). [Acabo de editar la respuesta también.]
— Goodside

72

(actualización: 2018)

Tenga en cuenta que pd.Timegrouperestá depreciado y se eliminará. Utilice en su lugar:

 df.groupby(pd.Grouper(freq='M'))

2
Encuentre los documentos de Grouper aquí y las especificaciones de frecuencia ( freq=...) aquí . Algunos ejemplos son freq=Dpara el día , freq=Bpara días laborables , freq=Wde semanas o incluso freq=Qde trimestres .
— Kim

1
Encontré útil usar 'key' para evitar tener que reindexar el df, de la siguiente manera: df.groupby (pd.Grouper (key = 'your_date_column', freq = 'M'))
— Edward

10

Una solución que evita MultiIndex es crear una nueva datetimeconfiguración de columna día = 1. Luego agrupe por esta columna. Ejemplo trivial a continuación.

df = pd.DataFrame({'Date': pd.to_datetime(['2017-10-05', '2017-10-20']),
                   'Values': [5, 10]})

# normalize day to beginning of month
df['YearMonth'] = df['Date'] - pd.offsets.MonthBegin(1)

# two alternative methods
df['YearMonth'] = df['Date'] - pd.to_timedelta(df['Date'].dt.day-1, unit='D')
df['YearMonth'] = df['Date'].map(lambda dt: dt.replace(day=1))

g = df.groupby('YearMonth')

res = g['Values'].sum()

# YearMonth
# 2017-10-01    15
# Name: Values, dtype: int64

El beneficio sutil de esta solución es, a diferencia de que pd.Grouperel índice de agrupamiento se normaliza al comienzo de cada mes en lugar de al final y, por lo tanto, puede extraer grupos fácilmente a través de get_group:

some_group = g.get_group('2017-10-01')

Calcular el último día de octubre es un poco más engorroso. pd.Grouper, a partir de la versión 0.23, admite un conventionparámetro, pero esto solo se aplica a un PeriodIndexagrupador.


8

Solución ligeramente alternativa a @ jpp's pero generando una YearMonthcadena:

df['YearMonth'] = pd.to_datetime(df['Date']).apply(lambda x: '{year}-{month}'.format(year=x.year, month=x.month))

res = df.groupby('YearMonth')['Values'].sum()
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.