calcule la diferencia de fecha y hora en años, meses, etc. en una nueva columna de dataframe de pandas

Tengo un dataframe de pandas con este aspecto:

Name start end A 2000-01-10 1970-04-29 

Quiero agregar una nueva columna que proporcione la diferencia entre las columnas de start y end en años, meses, días.

Entonces el resultado debería verse como:

 Name start end diff A 2000-01-10 1970-04-29 29y9m etc. 

la columna diff también puede ser un objeto de datetime y datetime o un objeto de timedelta , pero el punto clave para mí es que puedo obtener fácilmente el Año y el Mes .

Lo que intenté hasta ahora es:

 df['diff'] = df['end'] - df['start'] 

Esto resulta en la nueva columna que contiene 10848 days . Sin embargo, no sé cómo convertir los días a 29y9m, etc.

Con una simple función podrás alcanzar tu objective.

La función calcula la diferencia de años y la diferencia de meses con un cálculo simple.

 import pandas as pd import datetime def parse_date(td): resYear = float(td.days)/364.0 # get the number of years including the the numbers after the dot resMonth = int((resYear - int(resYear))*364/30) # get the number of months, by multiply the number after the dot by 364 and divide by 30. resYear = int(resYear) return str(resYear) + "Y" + str(resMonth) + "m" df = pd.DataFrame([("2000-01-10", "1970-04-29")], columns=["start", "end"]) df["delta"] = [parse_date(datetime.datetime.strptime(start, '%Y-%m-%d') - datetime.datetime.strptime(end, '%Y-%m-%d')) for start, end in zip(df["start"], df["end"])] print df start end delta 0 2000-01-10 1970-04-29 29Y9m 

Bastante sencillo con relativedelta :

 from dateutil import relativedelta >> end start >> 0 1970-04-29 2000-01-10 for i in df.index: df.at[i, 'diff'] = relativedelta.relativedelta(df.ix[i, 'start'], df.ix[i, 'end']) >> end start diff >> 0 1970-04-29 2000-01-10 relativedelta(years=+29, months=+8, days=+12) 

Creo que esta es la forma más ‘pandas’ de hacerlo, sin usar ninguno para crear bucles ni definir funciones externas:

 >>> df = pd.DataFrame({'Name': ['A'], 'start': [datetime(2000, 1, 10)], 'end': [datetime(1970, 4, 29)]}) >>> df['diff'] = map(lambda td: datetime(1, 1, 1) + td, list(df['start'] - df['end'])) >>> df['diff'] = df['diff'].apply(lambda d: '{0}y{1}m'.format(d.year - 1, d.month - 1)) >>> df Name end start diff 0 A 1970-04-29 2000-01-10 29y8m 

Tuvo que usar el mapa en lugar de aplicar debido a la panded ‘timedelda64, que no permite una adición simple a un objeto de fecha y hora.

Una forma mucho más sencilla es usar la función date_range y calcular la longitud de la misma

 startdt=pd.to_datetime('2017-01-01') enddt = pd.to_datetime('2018-01-01') len(pd.date_range(start=startdt,end=enddt,freq='M')) 

Puedes probar la siguiente función para calcular la diferencia:

 def yearmonthdiff(row): s = row['start'] e = row['end'] y = s.year - e.year m = s.month - e.month d = s.day - e.day if m < 0: y = y - 1 m = m + 12 if m == 0: if d < 0: m = m -1 elif d == 0: s1 = s.hour*3600 + s.minute*60 + s.second s2 = e.hour*3600 + e.minut*60 + e.second if s1 < s2: m = m - 1 return '{}y{}m'.format(y,m) 

Donde fila es la row dataframe. Supongo que las columnas de start y end son objetos de datetime y datetime . Luego puede usar la función DataFrame.apply() para aplicarla a cada fila.

 df Out[92]: start end 0 2000-01-10 00:00:00.000000 1970-04-29 00:00:00.000000 1 2015-07-18 17:54:59.070381 2014-01-11 17:55:10.053381 df['diff'] = df.apply(yearmonthdiff, axis=1) In [97]: df Out[97]: start end diff 0 2000-01-10 00:00:00.000000 1970-04-29 00:00:00.000000 29y9m 1 2015-07-18 17:54:59.070381 2014-01-11 17:55:10.053381 1y6m 

Similar a la respuesta de @ DeepSpace, aquí hay una implementación similar a SAS:

 import pandas as pd from dateutil import relativedelta def intck_month( start, end ): rd = relativedelta.relativedelta( pd.to_datetime( end ), pd.to_datetime( start ) ) return rd.years, rd.months 

Uso:

 >> years, months = intck_month('1960-01-01', '1970-03-01') >> print(years) 10 >> print(months) 2