Cómo agrupar las entradas de Pandas DataFrame por fecha en una columna no única

82

Un Pandas DataFramecontiene una columna nombrada "date"que contiene datetimevalores no únicos . Puedo agrupar las líneas en este marco usando:

data.groupby(data['date'])

Sin embargo, esto divide los datos por los datetimevalores. Me gustaría agrupar estos datos por el año almacenado en la columna "fecha". Esta página muestra cómo agrupar por año en los casos en los que la marca de tiempo se usa como índice, lo cual no es cierto en mi caso.

¿Cómo logro esta agrupación?

Boris Gorelik
fuente
Para aquellos que vengan aquí en 2017+, hay varias formas nuevas de agrupar por una cantidad de tiempo particular. Vea esta respuesta a continuación
Ted Petrou

Respuestas:

91

Estoy usando pandas 0.16.2. Esto tiene un mejor rendimiento en mi gran conjunto de datos:

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

Usar la dtopción y jugar con weekofyear, dayofweeketc. se vuelve mucho más fácil.

DACW
fuente
Al mismo tiempo, esta parece ser la forma pandaica de acceder a los atributos de fecha de una serie.
dancow
74

La solución de ecatmur funcionará bien. Sin embargo, esto será un mejor rendimiento en grandes conjuntos de datos:

data.groupby(data['date'].map(lambda x: x.year))
Wes McKinney
fuente
9
¿Por qué mapear en lugar de aplicar?
Gus
1
Afaik, mapgeneralmente tiene algunas cualidades de eficiencia buenas cuando se aplican funciones arbitrarias en comparación con solo usar apply.
Coolio2654
25

Esto podría ser más fácil de explicar con un conjunto de datos de muestra.

Crear datos de muestra

Asumamos que tenemos una sola columna de marcas de tiempo, datey la otra columna nos gustaría realizar una agregación en, 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

Hay varias formas de agrupar por año

  • Utilice el descriptor de acceso dt con yearpropiedad
  • Ponga dateen índice y use la función anónima para acceder al año
  • resampleMétodo de uso
  • Convertir a período pandas

.dtaccesor con yearpropiedad

Cuando tiene una columna (y no un índice) de marcas de tiempo de pandas, puede acceder a muchas más propiedades y métodos adicionales con el dtdescriptor de acceso. Por ejemplo:

df['date'].dt.year

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

Podemos usar esto para formar nuestros grupos y calcular algunas agregaciones en una columna en particular:

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

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

poner la fecha en el índice y usar la función anónima para acceder al año

Si establece la columna de fecha como índice, se convierte en un DateTimeIndex con las mismas propiedades y métodos que el dtdescriptor de acceso proporciona a las columnas normales

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

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

Curiosamente, al usar el método groupby, puede pasarle una función. Esta función se pasará implícitamente al índice del DataFrame. Entonces, podemos obtener el mismo resultado de arriba con lo siguiente:

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

      sum  mean  max
2012   14     7    9
2015    6     2    3

Usa el resamplemétodo

Si su columna de fecha no está en el índice, debe especificar la columna con el onparámetro. También debe especificar el alias de desplazamiento como una cadena.

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

Convertir a período pandas

También puede convertir la columna de fecha en un objeto Pandas Period. Debemos pasar el alias de desplazamiento como una cadena para determinar la duración del período.

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

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

Entonces podemos usar esto como un grupo

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


      sum  mean  max
2012   14     7    9
2015    6     2    3
Ted Petrou
fuente
En el último método que usó to_period('A'), ¿para qué es eso ('A')?
shiv_90
2
@ Shiv_90 the 'A'is a timeseries offset-alias: pandas.pydata.org/pandas-docs/stable/…
ptim
¿Qué método recomendaría si también necesita guardar una columna de 'fecha' separada? Por ejemplo, si ejecuto el .dt.yearmétodo simple y lo guardo en un nuevo marco de datos, las fechas se guardan como índices y eso se vuelve problemático si digo que necesito trazar los datos porque la columna 'fechas' no está realmente allí, sino solo las tres proporcionado en.agg()
shiv_90
13

Esto debería funcionar:

data.groupby(lambda x: data['date'][x].year)
ecatmur
fuente
0

esto también funcionará

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

Chetan Kabra
fuente
Debería funcionar, pero cuando se ejecuta, muestra la ubicación del objeto en la memoria, pero no una salida real. <pandas.core.groupby.DataFrameGroupBy object at 0x10d7f6438>es lo que obtengo cuando me ejecutan.
shiv_90