Tengo un marco de datos como el que se muestra a continuación

df1 = pd.DataFrame({'person_id': [11,11,11,21,21],
                        'admit_dates': ['03/21/2015', '01/21/2016', '7/20/2018','01/11/2017','12/31/2011'],
                        'discharge_dates': ['05/09/2015', '01/29/2016', '7/27/2018','01/12/2017','01/31/2016'],
                        'drug_start_dates': ['05/29/1967', '01/21/1957', '7/27/1959','01/01/1961','12/31/1961'],
                        'offset':[223,223,223,310,310]})

Lo que me gustaría hacer es agregar offset que está en years a las columnas de fechas.

Entonces, estaba tratando de convertir el desplazamiento al objeto timedelta con unit=y o unit=Y y luego cambiar admit_dates

df1['offset'] = pd.to_timedelta(df1['offset'],unit='Y') #also tried with `y` (small y)
df1['shifted_date'] = df1['admit_dates'] + df1['offset']

Sin embargo, me sale el siguiente error

ValueError: las unidades 'M' e 'Y' ya no son compatibles, ya que no representan duraciones de valores timedelta inequívocos.

¿Hay alguna otra forma elegante de cambiar las fechas en years?

2
The Great 25 jun. 2020 a las 07:28

2 respuestas

La mejor respuesta

El máximo Timestamp admitido en pandas es Timestamp('2262-04-11 23:47:16.854775807'), por lo que no podrá agregar 310 años hasta la fecha 12/31/2011, una forma posible es utilizar los objetos de fecha y hora de Python que admiten un año máximo hasta 9999, por lo que debería poder agregar 310 años a eso.

from dateutil.relativedelta import relativedelta

df['admit_dates'] = pd.to_datetime(df['admit_dates'])
df['admit_dates'] = df['admit_dates'].dt.date.add(
    df['offset'].apply(lambda y: relativedelta(years=y)))

Resultado:

df
   person_id admit_dates discharge_dates drug_start_dates  offset
0         11  2238-03-21      05/09/2015       05/29/1967     223
1         11  2239-01-21      01/29/2016       01/21/1957     223
2         11  2241-07-20       7/27/2018        7/27/1959     223
3         21  2327-01-11      01/12/2017       01/01/1961     310
4         21  2321-12-31      01/31/2016       12/31/1961     310
1
Shubham Sharma 25 jun. 2020 a las 06:24

Una cosa que puede hacer es extraer el año fuera de la fecha y agregarlo al desplazamiento:

df1 = pd.DataFrame({'person_id': [11,11,11,21,21],
                        'admit_dates': ['03/21/2015', '01/21/2016', '7/20/2018','01/11/2017','12/31/2011'],
                        'discharge_dates': ['05/09/2015', '01/29/2016', '7/27/2018','01/12/2017','01/31/2016'],
                        'drug_start_dates': ['05/29/1967', '01/21/1957', '7/27/1959','01/01/1961','12/31/1961'],
                        'offset':[10,20,2,31,12]})
df1.admit_dates = pd.to_datetime(df1.admit_dates)

df1["new_year"] = df1.admit_dates.dt.year + df1.offset
df1["date_with_offset"] = pd.to_datetime(pd.DataFrame({"year": df1.new_year, 
                                                  "month": df1.admit_dates.dt.month, 
                                                  "day":df1.admit_dates.dt.day}))

El problema: con sus desplazamientos originales, algunas de las fechas causan el siguiente error:

OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 2328-01-11 00:00:00

De acuerdo con la documentación, la La fecha máxima en los pandas es el 11 de abril de 2262 (aproximadamente a las doce menos cuarto, para ser específicos). Probablemente sea porque mantienen el tiempo en nanosegundos, y es entonces cuando se produce el error de fuera de los límites para esta representación.

1
Roy2012 25 jun. 2020 a las 05:42