2013-10-23 11 views
8

seguito nello spirito di this answer, ho tentato il seguente per convertire una colonna dataframe di datetimes ad una colonna di secondi dall'epoca.Python Pandas Serie di datetimes per secondi dall'epoca

df['date'] = (df['date']+datetime.timedelta(hours=2)-datetime.datetime(1970,1,1)) 
df['date'].map(lambda td:td.total_seconds()) 

Il secondo comando causa il seguente errore che non capisco. Qualche idea su cosa potrebbe succedere qui? Ho sostituito la mappa con la domanda e questo non ha aiutato a fare la differenza.

--------------------------------------------------------------------------- 
AttributeError       Traceback (most recent call last) 
<ipython-input-99-7123e823f995> in <module>() 
----> 1 df['date'].map(lambda td:td.total_seconds()) 

/Users/cpd/.virtualenvs/py27-ipython+pandas/lib/python2.7/site-packages/pandas-0.12.0_937_gb55c790-py2.7-macosx-10.8-x86_64.egg/pandas/core/series.pyc in map(self, arg, na_action) 
    1932    return self._constructor(new_values, index=self.index).__finalize__(self) 
    1933   else: 
-> 1934    mapped = map_f(values, arg) 
    1935    return self._constructor(mapped, index=self.index).__finalize__(self) 
    1936 

/Users/cpd/.virtualenvs/py27-ipython+pandas/lib/python2.7/site-packages/pandas-0.12.0_937_gb55c790-py2.7-macosx-10.8-x86_64.egg/pandas/lib.so in pandas.lib.map_infer (pandas/lib.c:43628)() 

<ipython-input-99-7123e823f995> in <lambda>(td) 
----> 1 df['date'].map(lambda td:td.total_seconds()) 

AttributeError: 'float' object has no attribute 'total_seconds' 
+0

Sembra che la colonna "data" potrebbe non essere un datetime64 in primo luogo? – Boud

+1

La colonna contiene valori mancanti? I valori mancanti solitamente causano il cast dei cast serie, causando stranezze quando si tenta di interpretarli come dati. – Abe

+0

@Abe In effetti avevi ragione. Risulta che ci sono alcuni dati mancanti in alcuni dei record. Non è quello che mi aspettavo ... Ack. – Chris

risposta

12

Aggiornamento:

In 0.15.0 Timedeltas diventato un DTYPE a tutti gli effetti.

Così questo diventa possibile (oltre che dei metodi indicati)

In [45]: s = Series(pd.timedelta_range('1 day',freq='1S',periods=5))       

In [46]: s.dt.components 
Out[46]: 
    days hours minutes seconds milliseconds microseconds nanoseconds 
0  1  0  0  0    0    0   0 
1  1  0  0  1    0    0   0 
2  1  0  0  2    0    0   0 
3  1  0  0  3    0    0   0 
4  1  0  0  4    0    0   0 

In [47]: s.astype('timedelta64[s]') 
Out[47]: 
0 86400 
1 86401 
2 86402 
3 86403 
4 86404 
dtype: float64 

risposta originale:

Vedo che siete su master (e 0,13 è venuta fuori molto presto), così assumendo hai numpy> = 1.7. Fai questo. Vedere here per la documentazione (questa è la conversione di frequenza)

In [5]: df = DataFrame(dict(date = date_range('20130101',periods=10))) 

In [6]: df 
Out[6]: 
       date 
0 2013-01-01 00:00:00 
1 2013-01-02 00:00:00 
2 2013-01-03 00:00:00 
3 2013-01-04 00:00:00 
4 2013-01-05 00:00:00 
5 2013-01-06 00:00:00 
6 2013-01-07 00:00:00 
7 2013-01-08 00:00:00 
8 2013-01-09 00:00:00 
9 2013-01-10 00:00:00 

In [7]: df['date']+timedelta(hours=2)-datetime.datetime(1970,1,1) 
Out[7]: 
0 15706 days, 02:00:00 
1 15707 days, 02:00:00 
2 15708 days, 02:00:00 
3 15709 days, 02:00:00 
4 15710 days, 02:00:00 
5 15711 days, 02:00:00 
6 15712 days, 02:00:00 
7 15713 days, 02:00:00 
8 15714 days, 02:00:00 
9 15715 days, 02:00:00 
Name: date, dtype: timedelta64[ns] 

In [9]: (df['date']+timedelta(hours=2)-datetime.datetime(1970,1,1))/np.timedelta64(1,'s') 
Out[9]: 
0 1357005600 
1 1357092000 
2 1357178400 
3 1357264800 
4 1357351200 
5 1357437600 
6 1357524000 
7 1357610400 
8 1357696800 
9 1357783200 
Name: date, dtype: float64 

I valori contenuti sono np.timedelta64[ns] oggetti, non hanno gli stessi metodi timedelta oggetti, quindi nessun total_seconds().

In [10]: s = (df['date']+timedelta(hours=2)-datetime.datetime(1970,1,1)) 

In [11]: s[0] 
Out[11]: numpy.timedelta64(1357005600000000000,'ns') 

È possibile astype loro di int, e si ottiene di nuovo un'unità ns.

In [12]: s[0].astype(int) 
Out[12]: 1357005600000000000 

Si può fare anche questo (ma solo su un singolo elemento di unità).

In [18]: s[0].astype('timedelta64[s]') 
Out[18]: numpy.timedelta64(1357005600,'s') 
+1

Perfetto Jeff, grazie! Una volta che mi sono sbarazzato delle righe con dati mancanti, ho potuto applicare direttamente questo al nuovo problema. ;-) – Chris

+0

non è necessario rimuovere i valori mancanti (NaT); saranno restituiti come nan – Jeff

+0

Non ho tempo per modificare (e ricontrollare) la risposta, ma in realtà la versione 0.13 ora consente di applicare le operazioni "astype" a un'intera serie. Vedi http://pandas.pydata.org/pandas-docs/stable/timeseries.html#time-deltas-conversions, o http://pandas.pydata.org/pandas-docs/stable/whatsnew.html e fai un find-on-page per 'astype'. – TimStaley

Problemi correlati