2014-06-29 10 views
9

Ho un df con i soliti timestamp come un indice:Pandas: indice di timestamp arrotondando al 5 ° minuto più vicino

2011-04-01 09:30:00 
    2011-04-01 09:30:10 
    ... 
    2011-04-01 09:36:20 
    ... 
    2011-04-01 09:37:30 

Come si crea una colonna a questo dataframe con la stessa data e ora, ma arrotondati al più vicino Intervallo del 5 ° minuto? Come questo:

index     new_col 
    2011-04-01 09:30:00 2011-04-01 09:35:00   
    2011-04-01 09:30:10 2011-04-01 09:35:00 
    2011-04-01 09:36:20 2011-04-01 09:40:00 
    2011-04-01 09:37:30 2011-04-01 09:40:00 
+1

Molte di queste risposte sono più conciso ed è necessario solo cambiare '5mins' al posto di' 15min' https://stackoverflow.com/questions/32344533/how-do-i-round-datetime-column-to-nearest-quarter-hour – josh

risposta

12

The round_to_5min(t) solution using timedelta arithmetic è corretto ma complicato e molto lento. Invece di utilizzare la bella Timstamp in panda:

import numpy as np 
import pandas as pd 

ns5min=5*60*1000000000 # 5 minutes in nanoseconds 
pd.to_datetime(((df.index.astype(np.int64) // ns5min + 1) * ns5min)) 

Mettiamo a confronto la velocità:

rng = pd.date_range('1/1/2014', '1/2/2014', freq='S') 

print len(rng) 
# 86401 

# ipython %timeit 
%timeit pd.to_datetime(((rng.astype(np.int64) // ns5min + 1) * ns5min)) 
# 1000 loops, best of 3: 1.01 ms per loop 

%timeit rng.map(round_to_5min) 
# 1 loops, best of 3: 1.03 s per loop 

soli circa 1000 volte più veloce!

+1

Fai attenzione quando hai a che fare con l'ora legale: non tutti i giorni hanno la stessa lunghezza e il tuo approccio potrebbe fallire. Raccomando di utilizzare gli offset: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects –

+2

@Marius Ion: Non occorre fare attenzione qui. La durata della giornata è irrilevante. Se DatetimeIndex ha un fuso orario, l'operazione 'astype' viene convertita in UTC. Devi solo convertire il risultato nel tuo fuso orario (ad esempio con 'tz_localize (" UTC "). Tz_convert (" US/Eastern ")') – cronos

5

Si può provare qualcosa di simile:

def round_to_5min(t): 
    delta = datetime.timedelta(minutes=t.minute%5, 
           seconds=t.second, 
           microseconds=t.microsecond) 
    t -= delta 
    if delta > datetime.timedelta(0): 
     t += datetime.timedelta(minutes=5) 
    return t 

df['new_col'] = df.index.map(round_to_5min) 
+0

che sembra buono ma quando lo provo sui miei dati vedo: '2011-04- 01 09:32:10 -> 2011-04-01 09: 30: 00' '2011-04-01 09:32:20 -> 2011-04-01 09: 30: 00' ' 2011-04- 01 09:32:30 -> 2011 -04-01 09: 35: 00' '2011-04-01 09:32:40 -> 2011-04-01 09: 35: 00' dovrebbero essere tutti 2011-04-01 09:35:00 – Plug4

+1

Ah, nella tua domanda hai citato il "più vicino" 5 minuti, ma vedo dai tuoi dati che vuoi arrotondare per i prossimi 5 minuti. Ho risolto la risposta, grazie. Suppongo che tu voglia 9: 30: 00: 00 per arrotondare alle 9: 30: 00: 00 invece che alle 9: 35: 00: 00, altrimenti puoi sempre aggiungere solo i 5 minuti. – dustyrockpyle

+0

Fantastico! funziona alla grande grazie per l'insegnamento – Plug4

2

Ho avuto lo stesso problema ma con datetime64p [ns] timestamp.

ho usato:

def round_to_5min(t): 
    """ This function rounds a timedelta timestamp to the nearest 5-min mark""" 
    t = datetime.datetime(t.year, t.month, t.day, t.hour, t.minute - t.minute%5, 0) 
    return t 

seguita dalla funzione di 'mappa'

Problemi correlati