¿Splines de Python u otras interpolaciones que funcionan con el tiempo en el eje x?

Tratando de usar los pandas tremendamente útiles para tratar los datos como series de tiempo, ahora estoy tropezando con el hecho de que no parece que existan bibliotecas que puedan interpolar directamente (con una spline o similar) sobre los datos que tienen DateTime como x ¿eje? Siempre me veo obligado a convertir primero a un número de punto flotante, como segundos desde 1980 o algo así.

Estaba intentando las siguientes cosas hasta ahora, perdón por el formato extraño, tengo estas cosas solo en el cuaderno ipython, y no puedo copiar celdas desde allí:

from scipy.interpolate import InterpolatedUnivariateSpline as IUS type(bb2temp): pandas.core.series.TimeSeries s = IUS(bb2temp.index.to_pydatetime(), bb2temp, k=1) --------------------------------------------------------------------------- TypeError Traceback (most recent call last)  in () ----> 1 s = IUS(bb2temp.index.to_pydatetime(), bb2temp, k=1) /Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/scipy/interpolate/fitpack2.py in __init__(self, x, y, w, bbox, k) 335 #_data == x,y,w,xb,xe,k,s,n,t,c,fp,fpint,nrdata,ier 336 self._data = dfitpack.fpcurf0(x,y,k,w=w, --> 337 xb=bbox[0],xe=bbox[1],s=0) 338 self._reset_class() 339 TypeError: float() argument must be a string or a number 

Al utilizar bb2temp.index.values (que se parecen a estos:

 array([1970-01-15 184:00:35.884999, 1970-01-15 184:00:58.668999, 1970-01-15 184:01:22.989999, 1970-01-15 184:01:45.774000, 1970-01-15 184:02:10.095000, 1970-01-15 184:02:32.878999, 1970-01-15 184:02:57.200000, 1970-01-15 184:03:19.984000, 

) como argumento x, curiosamente, la clase Spline crea un interpolador, pero aún se rompe cuando se intenta interpolar / extrapolar a un DateTimeIndex más grande (que es mi objective final aquí). Aquí es cómo se ve:

 all_times = divcal.timed.index.levels[2] # part of a MultiIndex all_times  [2009-07-20 00:00:00.045000, ..., 2009-07-20 00:30:00.018000] Length: 14063, Freq: None, Timezone: None s(all_times.values) # applying the above generated interpolator --------------------------------------------------------------------------- TypeError Traceback (most recent call last)  in () ----> 1 s(tall.values) /Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/scipy/interpolate/fitpack2.py in __call__(self, x, nu) 219 # return dfitpack.splev(*(self._eval_args+(x,))) 220 # return dfitpack.splder(nu=nu,*(self._eval_args+(x,))) --> 221 return fitpack.splev(x, self._eval_args, der=nu) 222 223 def get_knots(self): /Library/Frameworks/EPD64.framework/Versions/7.3/lib/python2.7/site-packages/scipy/interpolate/fitpack.py in splev(x, tck, der, ext) 546 547 x = myasarray(x) --> 548 y, ier =_fitpack._spl_(x, der, t, c, k, ext) 549 if ier == 10: 550 raise ValueError("Invalid input data") TypeError: array cannot be safely cast to required type 

Intenté usar s(all_times) s(all_times.to_pydatetime()) también, con el mismo TypeError: array cannot be safely cast to required type .

¿Soy, lamentablemente, correcto? ¿Todos se acostumbraron a convertir los tiempos en puntos flotantes tanto que nadie pensó que era una buena idea que estas interpolaciones funcionaran automáticamente? (Finalmente, habría encontrado un proyecto súper útil para contribuir …) ¿O te gustaría demostrar que estoy equivocado y ganar algunos puntos SO? 😉

Edición: Advertencia: compruebe los datos de sus pandas en busca de NaN antes de entregarlos a las rutinas de interpolación. No se quejarán de nada, solo fallarán en silencio.

El problema es que las rutinas de fitpack que se usan debajo requieren flotadores. Por lo tanto, en algún momento tiene que haber una conversión de datetime a floats. Esta conversión es fácil. Si bb2temp.index.values es su matriz datetime, simplemente haga lo siguiente:

 In [1]: bb2temp.index.values.astype('d') Out[1]: array([ 1.22403588e+12, 1.22405867e+12, 1.22408299e+12, 1.22410577e+12, 1.22413010e+12, 1.22415288e+12, 1.22417720e+12, 1.22419998e+12]) 

Solo necesitas pasar eso a tu spline. Y para volver a convertir los resultados en objetos de fecha y hora, debe realizar results.astype('datetime64') .