2014-06-29 12 views
9

ich eine df mit den üblichen Zeitstempel als Index haben:Pandas: Timestamp-Index auf den nächsten 5. Minute Rundung

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

Wie kann ich eine Spalte auf diese Datenrahmen mit dem gleichen Zeitstempel erstellen, sondern gerundet auf die nächste 5. Minute Intervall? Wie folgt aus:

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

Viele dieser Antworten sind die mehr consise und Sie brauchen nur '5mins' statt ändern' 15min' https://stackoverflow.com/questions/32344533/how-do-i-round-datetime-column-to-nearest-quarter-hour – josh

Antwort

12

The round_to_5min(t) solution using timedelta arithmetic ist richtig, aber kompliziert und sehr langsam. Statt Verwendung des netten Timstamp in Pandas machen:

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

Lassen Sie uns die Geschwindigkeit vergleichen:

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 

Nur etwa 1000-mal schneller!

+1

Seien Sie vorsichtig, wenn Sie mit Sommerzeit zu tun haben: Nicht alle Tage haben die gleiche Länge, und Ihr Ansatz kann fehlschlagen. Ich empfehle Offsets zu verwenden: http://pandas.pydata.org/pandas-docs/stable/timeseries.html#dateoffset-objects –

+2

@Marius Ion: Keine Notwendigkeit, hier vorsichtig zu sein. Die Länge des Tages ist irrelevant. Wenn der DatetimeIndex über eine Zeitzone verfügt, wird die Operation 'astype' in UTC konvertiert. Konvertieren Sie das Ergebnis einfach zurück in Ihre Zeitzone (z. B. mit 'tz_localize (" UTC "). Tz_convert (" US/Eastern ")') – cronos

5

Sie können so etwas wie dies versuchen:

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

das sieht gut aus, aber wenn ich es auf meine Daten überprüfe, sehe ich: '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' sie sollten alle 2011-04-01 09:35:00 – Plug4

+1

Ah, in deiner Frage hast du um die 'nächsten' 5 Minuten erwähnt, aber ich sehe aus deinen Daten, dass du auf die nächsten 5 Minuten runden willst. Ich habe die Antwort behoben, danke. Ich gehe davon aus, Sie wollen 9: 30: 00: 00, um 9: 30: 00: 00 statt 9: 35: 00: 00, sonst können Sie nur die 5 Minuten hinzufügen. – dustyrockpyle

+0

Fantastisch! es funktioniert super. Danke für den Unterricht – Plug4

2

Ich hatte das gleiche Problem aber mit datetime64p [ns] Zeitstempel.

I verwendet:

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 

gefolgt von der 'Karte' Funktion