2013-05-27 13 views
26

Próbuję dodać kolumnę deltaT do ramki danych, gdzie deltaT jest różnicą czasu między kolejnymi wierszami (w indeksie w przedziałach czasowych).Obliczanie różnicy czasu między indeksami Panda DataFame

time     value 

2012-03-16 23:50:00  1 
2012-03-16 23:56:00  2 
2012-03-17 00:08:00  3 
2012-03-17 00:10:00  4 
2012-03-17 00:12:00  5 
2012-03-17 00:20:00  6 
2012-03-20 00:43:00  7 

Pożądany wynik jest coś jak następujące (jednostek DeltaT pokazany w minutach):

time     value deltaT 

2012-03-16 23:50:00  1  0 
2012-03-16 23:56:00  2  6 
2012-03-17 00:08:00  3  12 
2012-03-17 00:10:00  4  2 
2012-03-17 00:12:00  5  2 
2012-03-17 00:20:00  6  8 
2012-03-20 00:43:00  7  23 
+1

spojrzeć tutaj na kilka podobnych pytań i docs timedelta: http://pandas.pydata.org/pandas-docs/dev/cookbook.html#miscellaneous – Jeff

Odpowiedz

42

Uwaga ta jest za pomocą numpy> = 1,7, dla numpy < 1.7, patrz konwersję tutaj: http://pandas.pydata.org/pandas-docs/dev/timeseries.html#time-deltas

oryginalna ramka ze wskaźnikiem datetime

In [196]: df 
Out[196]: 
        value 
2012-03-16 23:50:00  1 
2012-03-16 23:56:00  2 
2012-03-17 00:08:00  3 
2012-03-17 00:10:00  4 
2012-03-17 00:12:00  5 
2012-03-17 00:20:00  6 
2012-03-20 00:43:00  7 

In [199]: df.index 
Out[199]: 
<class 'pandas.tseries.index.DatetimeIndex'> 
[2012-03-16 23:50:00, ..., 2012-03-20 00:43:00] 
Length: 7, Freq: None, Timezone: None 

Oto timedelta64 co chcesz

In [200]: df['tvalue'] = df.index 

In [201]: df['delta'] = (df['tvalue']-df['tvalue'].shift()).fillna(0) 

In [202]: df 
Out[202]: 
        value    tvalue   delta 
2012-03-16 23:50:00  1 2012-03-16 23:50:00   00:00:00 
2012-03-16 23:56:00  2 2012-03-16 23:56:00   00:06:00 
2012-03-17 00:08:00  3 2012-03-17 00:08:00   00:12:00 
2012-03-17 00:10:00  4 2012-03-17 00:10:00   00:02:00 
2012-03-17 00:12:00  5 2012-03-17 00:12:00   00:02:00 
2012-03-17 00:20:00  6 2012-03-17 00:20:00   00:08:00 
2012-03-20 00:43:00  7 2012-03-20 00:43:00 3 days, 00:23:00 

Wysiadając odpowiedź, pomijając różnicę dzień (twój ostatni dzień jest 3/20, przed jest 3/17), w rzeczywistości jest trudne

In [204]: df['ans'] = df['delta'].apply(lambda x: x/np.timedelta64(1,'m')).astype('int64') % (24*60) 

In [205]: df 
Out[205]: 
        value    tvalue   delta ans 
2012-03-16 23:50:00  1 2012-03-16 23:50:00   00:00:00 0 
2012-03-16 23:56:00  2 2012-03-16 23:56:00   00:06:00 6 
2012-03-17 00:08:00  3 2012-03-17 00:08:00   00:12:00 12 
2012-03-17 00:10:00  4 2012-03-17 00:10:00   00:02:00 2 
2012-03-17 00:12:00  5 2012-03-17 00:12:00   00:02:00 2 
2012-03-17 00:20:00  6 2012-03-17 00:20:00   00:08:00 8 
2012-03-20 00:43:00  7 2012-03-20 00:43:00 3 days, 00:23:00 23 
12

Możemy utworzyć serię z indeksem i wartościami równymi kluczom indeksu przy użyciu to_series, a następnie obliczyć różnice między kolejnymi wierszami, co spowoduje powstanie dtype o wartości timedelta64[ns]. Po uzyskaniu tego, poprzez właściwość .dt, mogliśmy uzyskać dostęp do atrybutu sekund części czasu i ostatecznie podzielić każdy element przez 60, aby uzyskać jego wynik w ciągu kilku minut (opcjonalnie wypełniając pierwszą wartość przez 0).

In [13]: df['deltaT'] = df.index.to_series().diff().dt.seconds.div(60, fill_value=0) 
    ...: df         # use .astype(int) to obtain integer values 
Out[13]: 
        value deltaT 
time        
2012-03-16 23:50:00  1  0.0 
2012-03-16 23:56:00  2  6.0 
2012-03-17 00:08:00  3 12.0 
2012-03-17 00:10:00  4  2.0 
2012-03-17 00:12:00  5  2.0 
2012-03-17 00:20:00  6  8.0 
2012-03-20 00:43:00  7 23.0 

uproszczenie:

Kiedy wykonujemy diff:

In [8]: ser_diff = df.index.to_series().diff() 

In [9]: ser_diff 
Out[9]: 
time 
2012-03-16 23:50:00    NaT 
2012-03-16 23:56:00 0 days 00:06:00 
2012-03-17 00:08:00 0 days 00:12:00 
2012-03-17 00:10:00 0 days 00:02:00 
2012-03-17 00:12:00 0 days 00:02:00 
2012-03-17 00:20:00 0 days 00:08:00 
2012-03-20 00:43:00 3 days 00:23:00 
Name: time, dtype: timedelta64[ns] 

sekund do minut konwersji:

In [10]: ser_diff.dt.seconds.div(60, fill_value=0) 
Out[10]: 
time 
2012-03-16 23:50:00  0.0 
2012-03-16 23:56:00  6.0 
2012-03-17 00:08:00 12.0 
2012-03-17 00:10:00  2.0 
2012-03-17 00:12:00  2.0 
2012-03-17 00:20:00  8.0 
2012-03-20 00:43:00 23.0 
Name: time, dtype: float64 

Jeśli załóżmy, że chcesz to nawet część date jak został wykluczony wcześniej (tylko część czasu uznano), dt.total_seconds dałby Ci upływający czas w sekundach, z którymi minut mogłoby być obliczone ponownie przez podział.

In [12]: ser_diff.dt.total_seconds().div(60, fill_value=0) 
Out[12]: 
time 
2012-03-16 23:50:00  0.0 
2012-03-16 23:56:00  6.0 
2012-03-17 00:08:00  12.0 
2012-03-17 00:10:00  2.0 
2012-03-17 00:12:00  2.0 
2012-03-17 00:20:00  8.0 
2012-03-20 00:43:00 4343.0 # <-- number of minutes in 3 days 23 minutes 
Name: time, dtype: float64 
+1

Ostatni komentarz w ostatniej części kodu należy powiedzieć " 23 minuty " – Corrumpo

+0

O tak. Dziękuję za wskazanie tego. –

Powiązane problemy