Tengo un marco de datos que tiene dos columnas de fecha:

   Date1       Date2
2018-10-02    2018-12-21
2019-01-20    2019-04-30

Y así sucesivamente

Quiero crear una tercera columna que básicamente es una columna que contiene todos los meses entre las dos fechas, algo como esto:

   Date1       Date2           months
2018-10-02    2018-12-21       201810
2018-10-02    2018-12-21       201811
2018-10-02    2018-12-21       201812
2019-01-20    2019-04-30       201901
2019-01-20    2019-04-30       201902
2019-01-20    2019-04-30       201903
2019-01-20    2019-04-30       201904

¿Cómo puedo hacer esto? Intenté usar esta fórmula:

df['months']=df.apply(lambda x: pd.date_range(x.Date1,x.Date2, freq='MS').strftime("%Y%m"))

Pero no estoy obteniendo el resultado deseado. Amablemente ayuda. Gracias

4
Kshitij Yadav 7 oct. 2019 a las 23:30

3 respuestas

La mejor respuesta

Usando merge

final = df.merge(df.apply(lambda s: pd.date_range(s.Date1, s.Date2, freq='30D'), 1)\
                   .explode()\
                   .rename('Months')\
                   .dt.strftime('%Y%m'),
                 left_index=True, 
                 right_index=True)

   Months       Date1       Date2
0  201810  2018-10-02  2018-12-21
0  201811  2018-10-02  2018-12-21
0  201812  2018-10-02  2018-12-21
1  201901  2019-01-20  2019-04-30
1  201902  2019-01-20  2019-04-30
1  201903  2019-01-20  2019-04-30
1  201904  2019-01-20  2019-04-30
5
rafaelc 7 oct. 2019 a las 20:41

Usando groupby con pd.date_range y join.

Aviso : utilicé replace(day=1), para asegurarme de capturar todos los meses.

months = df.groupby(level=0).apply(lambda x: pd.date_range(x['Date1'].iat[0].replace(day=1), 
                                                           x['Date2'].iat[0], 
                                                           freq='MS')).explode().to_frame(name='Months')

df2 = months.join(df).reset_index(drop=True)

Salida

      Months      Date1      Date2
0 2018-10-01 2018-10-02 2018-12-21
1 2018-11-01 2018-10-02 2018-12-21
2 2018-12-01 2018-10-02 2018-12-21
3 2019-01-01 2019-01-20 2019-04-30
4 2019-02-01 2019-01-20 2019-04-30
5 2019-03-01 2019-01-20 2019-04-30
6 2019-04-01 2019-01-20 2019-04-30
2
Erfan 7 oct. 2019 a las 20:51

Puede fundir los datos, volver a muestrear y fusionar:

df.merge(df.reset_index()                               # reset index as column
           .melt(id_vars='index', value_name='months')  # usual melt
           .resample('M', on='months')                  # resample to get the month list
           .first().ffill()                             # interpolate the index
           .drop(['variable', 'months'], axis=1)        # remove unnecessary columns
           .reset_index(),                              # make months a column
         left_index=True,
         right_on='index'
)

Salida:

       Date1      Date2     months  index
0 2018-10-02 2018-12-21 2018-10-31    0.0
1 2018-10-02 2018-12-21 2018-11-30    0.0
2 2018-10-02 2018-12-21 2018-12-31    0.0
3 2019-01-20 2019-04-30 2019-01-31    1.0
4 2019-01-20 2019-04-30 2019-02-28    1.0
5 2019-01-20 2019-04-30 2019-03-31    1.0
6 2019-01-20 2019-04-30 2019-04-30    1.0
1
Quang Hoang 7 oct. 2019 a las 20:46
58276737