Conversión de mes a trimestre en el dataframe de Python

Tengo una columna en mi dataframe que indica el mes (en el formato yyyy-mm ). Quiero convertir eso a un cuarto usando pd.Period . Intenté usar la función de aplicar en la siguiente forma, pero se está ejecutando demasiado lento. ¿Hay una mejor manera de hacer esto? Estoy usando :

 hp2['Qtr'] = hp2.apply(lambda x: pd.Period(x['Mth'],'Q'),axis=1) 

Yo usaría el método to_datetime () de una manera “vectorizada”:

 In [76]: x Out[76]: Month 0 2016-11 1 2011-01 2 2015-07 3 2012-09 In [77]: x['Qtr'] = pd.to_datetime(x.Month).dt.quarter In [78]: x Out[78]: Month Qtr 0 2016-11 4 1 2011-01 1 2 2015-07 3 3 2012-09 3 

O si desea tenerlo en formato 2016Q4 (como se mencionó @root ), usando PeriodIndex() :

 In [114]: x['Qtr'] = pd.PeriodIndex(pd.to_datetime(x.Mth), freq='Q') In [115]: x Out[115]: Mth Qtr 0 2016-11 2016Q4 1 2011-01 2011Q1 2 2015-07 2015Q3 3 2012-09 2012Q3 

Como no necesita toda la fila, ¿es más rápido si asigna los valores solo de la columna?

 hp2['Qtr'] = hp2['Mth'].map(lambda x: pd.Period(x,'Q')) 

Resulta que estoy trabajando en un df que contiene 9994 filas, así que probé tu código en comparación con lo que he usado en el pasado y publiqué los resultados para ti. Aquí hay una muestra del df, no exactamente YYYY-MM pero no importa porque el código funcionará en cualquiera de los dos:

 hp2['Mth'][:10] Out[11]: 0 2016-06-26 1 2016-06-26 2 2016-06-26 3 2016-06-26 4 2016-06-26 5 2016-06-26 6 2016-06-26 7 2016-06-26 8 2016-06-26 9 2016-06-26 Name: Mth, dtype: datetime64[ns] 

Corrí su código en mi df:

 %timeit hp2['Qtr_Period']= hp2.apply(lambda x: pd.Period(x['Mth'],'Q'), axis=1) hp2['Qtr_Period'][:10] 1 loop, best of 3: 2.28 s per loop Out[13]: 0 2016Q2 1 2016Q2 2 2016Q2 3 2016Q2 4 2016Q2 5 2016Q2 6 2016Q2 7 2016Q2 8 2016Q2 9 2016Q2 Name: Qtr_Period, dtype: object 

Luego lo probé usando esto:

 %timeit hp2['Qtr_dt']= (df['Order Date'].dt.year.astype(str))+'Q'+(df['Order Date'].dt.quarter.astype(str)) hp2['Qtr_dt'][:10] 10 loops, best of 3: 67.6 ms per loop Out[14]: 0 2016Q2 1 2016Q2 2 2016Q2 3 2016Q2 4 2016Q2 5 2016Q2 6 2016Q2 7 2016Q2 8 2016Q2 9 2016Q2 Name: Qtr_dt, dtype: object 

Está claro a partir de los resultados. Espero que ayude. Puede encontrar más información sobre pandas.Series.dt.

La misma idea que @MaxU pero usando astype :

 hp2['Qtr'] = pd.to_datetime(hp2['Mth'].values, format='%Y-%m').astype('period[Q]') 

La salida resultante:

  Mth Qtr 0 2014-01 2014Q1 1 2017-02 2017Q1 2 2016-03 2016Q1 3 2017-04 2017Q2 4 2016-05 2016Q2 5 2016-06 2016Q2 6 2017-07 2017Q3 7 2016-08 2016Q3 8 2017-09 2017Q3 9 2015-10 2015Q4 10 2017-11 2017Q4 11 2015-12 2015Q4 

Tiempos

Usando la siguiente configuración para producir un gran conjunto de datos de muestra:

 n = 10**5 yrs = np.random.choice(range(2010, 2021), n) mths = np.random.choice(range(1, 13), n) df = pd.DataFrame({'Mth': ['{0}-{1:02d}'.format(*p) for p in zip(yrs, mths)]}) 

Obtengo los siguientes horarios:

 %timeit pd.to_datetime(df['Mth'].values, format='%Y-%m').astype('period[Q]') 10 loops, best of 3: 33.4 ms per loop %timeit pd.PeriodIndex(pd.to_datetime(df.Mth), freq='Q') 1 loop, best of 3: 2.68 s per loop %timeit df['Mth'].map(lambda x: pd.Period(x,'Q')) 1 loop, best of 3: 6.26 s per loop %timeit df.apply(lambda x: pd.Period(x['Mth'],'Q'),axis=1) 1 loop, best of 3: 9.49 s per loop