2012-12-18 3 views
5

Cercando di utilizzare i panda terribilmente utili per gestire i dati come serie temporali, ora mi imbatto nel fatto che non sembrano esistere librerie che possono direttamente interpolare (con una spline o simile) su dati che ha DateTime come un asse x? Mi sembra sempre di essere costretto a convertire prima un numero in virgola mobile, come i secondi dal 1980 o qualcosa del genere.Spline Python o altre interpolazioni che funzionano con il tempo sull'asse x?

Stavo cercando le seguenti cose finora, mi spiace per la formattazione strano, ho questa roba solo nel notebook ipython, e non riesco a copiare le celle da lì:

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) 
<ipython-input-67-19c6b8883073> in <module>() 
----> 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 

Utilizzando bb2temp.index.values (quello sguardo come questi:

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, 

) come x-argomento, è interessante notare che, la classe Spline fa creare un interpolatore, ma si rompe ancora quando si cerca di interpolare/estrapolare ad un DateTimeIndex più grande (che è il mio obiettivo finale qui) . Ecco come che sembra:

all_times = divcal.timed.index.levels[2] # part of a MultiIndex 

all_times 
<class 'pandas.tseries.index.DatetimeIndex'> 
[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) 
<ipython-input-74-ff11f6d6d7da> in <module>() 
----> 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 

ho provato ad usare s(all_times) e s(all_times.to_pydatetime()) pure, con la stessa TypeError: array cannot be safely cast to required type.

Sono, purtroppo, corretto? Tutti si sono abituati a convertire così tanto i tempi in virgola mobile, che nessuno ha pensato che fosse una buona idea che queste interpolazioni funzionassero automaticamente? (Avrei finalmente trovato un progetto super-utile da contribuire ..) O vorresti dimostrarmi sbagliato e guadagnare alcuni punti SO? ;)

Modifica: Avviso: controllare i dati dei panda per i NaN prima di passarli alle routine di interpolazione. Non si lamenteranno di nulla, ma semplicemente falliranno.

risposta

5

Il problema è che le routine di fitpack utilizzate sottostanti richiedono float. Quindi, a un certo punto ci deve essere una conversione da datetime a float. Questa conversione è facile. Se bb2temp.index.values è l'array datetime, basta fare:

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]) 

Hai solo bisogno di passare che per il vostro spline. E per convertire i risultati in oggetti datetime, fai results.astype('datetime64').

+0

Stavo pensando che dev'essere facile, grazie! Ma immagino giusto che una patch per le routine di interpolazione di Scipy di alto livello possa farlo per me? –

+0

Certo, una patch lo farebbe. Ma mi sembra ancora eccessivo. Potrebbe essere qualcosa di semplice come 'if array.dtype == 'datetime64': array = array.astype ('d')', e quindi il contrario per l'output. – tiago

+0

ecco perché sono confuso dal fatto che non lo facciano comunque ..;) Perché introdurre classi di alto livello sul fitpack se non funzionano per te? Molti dei passaggi tra splrep e InterpolatedUnivariateSpline potevano essere semplici one o two-liners. Nella somma, contano. –

Problemi correlati