¿Cómo trazar el diagtwig de densidad del núcleo de fechas en Pandas?

Tengo un dataframe de pandas donde cada observación tiene una fecha (como una columna de entradas en el formato datetime [64]). Estas fechas se extienden a lo largo de un período de unos 5 años. Me gustaría trazar una gráfica de densidad de núcleo de las fechas de todas las observaciones, con los años marcados en el eje x.

He descubierto cómo crear un tiempo-delta en relación con alguna fecha de referencia y luego crear una gráfica de densidad del número de horas / días / años entre cada observación y la fecha de referencia:

df['relativeDate'].astype('timedelta64[D]').plot(kind='kde') 

Pero esto no es exactamente lo que quiero: si me convierto en deltas de año, entonces el eje x es correcto pero pierdo la variación dentro del año. Pero si tomo una unidad de tiempo más pequeña como hora o día, las tags del eje x son mucho más difíciles de interpretar.

¿Cuál es la forma más sencilla de hacer que esto funcione en Pandas?

Inspirado por la respuesta de @JohnE, un enfoque alternativo para convertir la fecha en un valor numérico es usar .toordinal() .

 import pandas as pd import numpy as np # simulate some artificial data # =============================== np.random.seed(0) dates = pd.date_range('2010-01-01', periods=31, freq='D') df = pd.DataFrame(np.random.choice(dates,100), columns=['dates']) # use toordinal() to get datenum df['ordinal'] = [x.toordinal() for x in df.dates] print(df) dates ordinal 0 2010-01-13 733785 1 2010-01-16 733788 2 2010-01-22 733794 3 2010-01-01 733773 4 2010-01-04 733776 5 2010-01-28 733800 6 2010-01-04 733776 7 2010-01-08 733780 8 2010-01-10 733782 9 2010-01-20 733792 .. ... ... 90 2010-01-19 733791 91 2010-01-28 733800 92 2010-01-01 733773 93 2010-01-15 733787 94 2010-01-04 733776 95 2010-01-22 733794 96 2010-01-13 733785 97 2010-01-26 733798 98 2010-01-11 733783 99 2010-01-21 733793 [100 rows x 2 columns] # plot non-parametric kde on numeric datenum ax = df['ordinal'].plot(kind='kde') # rename the xticks with labels x_ticks = ax.get_xticks() ax.set_xticks(x_ticks[::2]) xlabels = [datetime.datetime.fromordinal(int(x)).strftime('%Y-%m-%d') for x in x_ticks[::2]] ax.set_xticklabels(xlabels) 

introduzca la descripción de la imagen aquí

Me imagino que hay una forma mejor y automática de hacer esto, pero si no, entonces debería ser una solución decente. Primero, configuremos algunos datos de muestra:

 np.random.seed(479) start_date = '2011-1-1' df = pd.DataFrame({ 'date':np.random.choice( pd.date_range(start_date, periods=365*5, freq='D'), 50) }) df['rel'] = df['date'] - pd.to_datetime(start_date) df.rel = df.rel.astype('timedelta64[D]') date rel 0 2014-06-06 1252 1 2011-10-26 298 2 2013-08-24 966 3 2014-09-25 1363 4 2011-12-23 356 

Como puede ver, ‘rel’ es solo el número de días desde el día de inicio. Es esencialmente un entero, por lo que todo lo que necesitas hacer es normalizarlo con respecto a la fecha de inicio.

 df['year_as_float'] = pd.to_datetime(start_date).year + df.rel / 365. date rel year_as_float 0 2014-06-06 1252 2014.430137 1 2011-10-26 298 2011.816438 2 2013-08-24 966 2013.646575 3 2014-09-25 1363 2014.734247 4 2011-12-23 356 2011.975342 

Necesitaría ajustarlo ligeramente para una fecha que no comience el 1 de enero. Eso también ignora los años bisiestos, lo que realmente no es un problema práctico si solo está produciendo un gráfico de KDE durante 5 años, pero podría ser importante dependiendo de ¿Qué más quieres hacer?

Aquí está la ttwig

 df['year_as_float']d.plot(kind='kde') 

introduzca la descripción de la imagen aquí