2013-10-30 2 views
6

Auf der Suche nach der schnellsten Lösung des Zeitmittelungsproblems.Durchschnittliche Zeit für Datetime-Liste

Ich habe eine Liste von Datetime-Objekten. Müssen den Durchschnittswert der Zeit finden (außer Jahr, Monat, Tag). Hier ist, was ich habe, so weit:

import datetime as dtm 
def avg_time(times): 
    avg = 0 
    for elem in times: 
     avg += elem.second + 60*elem.minute + 3600*elem.hour 
    avg /= len(times) 
    rez = str(avg/3600) + ' ' + str((avg%3600)/60) + ' ' + str(avg%60) 
    return dtm.datetime.strptime(rez, "%H %M %S") 
+1

Was ist Ihre Frage? Ist es nicht schnell genug für deinen Zweck? Wie viel schneller müsste es dann sein? Was ist der Kontext (d. H. Es kann einen anderen Ansatz geben, der schneller ist und diese Routine umgeht)? – Evert

+0

Meine Frage ist, wie man die Gesamtgeschwindigkeit verbessert. So viel schneller wie es auf Python sein kann. Vielleicht gibt es eine Funktion oder einen alternativen Weg, um das Gleiche zu tun. Wichtiger Hinweis: Ursprünglich stammen die Daten für die Mittelung aus der pandas DataFrame-Spalte (datetime64 [ns] type) – user2915556

Antwort

4

Hier ist eine bessere Möglichkeit, dieses Problem anzugehen

Gene bewerten eine Probe von Datetimes

In [28]: i = date_range('20130101',periods=20000000,freq='s') 

In [29]: i 
Out[29]: 
<class 'pandas.tseries.index.DatetimeIndex'> 
[2013-01-01 00:00:00, ..., 2013-08-20 11:33:19] 
Length: 20000000, Freq: S, Timezone: None 

avg 20m mal

In [30]: %timeit pd.to_timedelta(int((i.hour*3600+i.minute*60+i.second).mean()),unit='s') 
1 loops, best of 3: 2.87 s per loop 

Das Ergebnis als Timedelta (beachten Sie, dass diese numpy 1,7 und Pandas 0,13 für den to_timedelta Teil erfordert, kommt sehr bald)

In [31]: pd.to_timedelta(int((i.hour*3600+i.minute*60+i.second).mean()),unit='s') 
Out[31]: 
0 11:59:12 
dtype: timedelta64[ns] 

In Sekunden (dies wird für Pandas 0.12, numpy> = 1.6) funktionieren.

In [32]: int((i.hour*3600+i.minute*60+i.second).mean()) 
Out[32]: 43152 
+0

Ich scheint pandas.tseries.index.DatetimeIndex zu sein. Meine Daten (df ['Date']) haben den Typ pandas.core.series.Series. Können Sie vorschlagen, wie Sie es konvertieren? – user2915556

+0

'' Index (your_series) '' – Jeff

+0

Es arbeitet mit 4,78 sec vs. guten alten 37,7 sec auf 29M Basis (von '% timeit'). Ich denke, das ist es. Vielen Dank! – user2915556

0

Sie würden mindestens sum() mit einem Generator Ausdruck verwenden, um die Gesamtzahl von Sekunden zu erstellen:

from datetime import datetime, date, time 

def avg_time(datetimes): 
    total = sum(dt.hour * 3600 + dt.minute * 60 + dt.second for dt in datetimes) 
    avg = total/len(datetimes) 
    minutes, seconds = divmod(int(avg), 60) 
    hours, minutes = divmod(minutes, 60) 
    return datetime.combine(date(1900, 1, 1), time(hours, minutes, seconds)) 

Demo:

>>> from datetime import datetime, date, time, timedelta 
>>> def avg_time(datetimes): 
...  total = sum(dt.hour * 3600 + dt.minute * 60 + dt.second for dt in datetimes) 
...  avg = total/len(datetimes) 
...  minutes, seconds = divmod(int(avg), 60) 
...  hours, minutes = divmod(minutes, 60) 
...  return datetime.combine(date(1900, 1, 1), time(hours, minutes, seconds)) 
... 
>>> avg_time([datetime.now(), datetime.now() - timedelta(hours=12)]) 
datetime.datetime(1900, 1, 1, 7, 13) 
+0

Ich bin mir nicht sicher, ob ich ohne Timedata auskommen kann. Es ist eine der Spalten in meinem Pandas DataFrame, mit der ich mich befassen muss. Könntest du etwas genauer über die Verwendung der sum() Generatorschleife sein? – user2915556

+0

@ user2915556: da kann * nun * ein besserer Weg sein dies in Pandas zu tun; Ich habe keine Ahnung, ob es da ist, da ich keine Erfahrung mit Pandas habe. Vielleicht könnte das in Ihrer Frage angegeben worden sein (einschließlich einer Beschreibung, wie Ihre Datenrahmen aussehen). Ich habe mir die Freiheit genommen, Ihrer Frage ein Pandas-Tag hinzuzufügen. Ich habe meine Antwort auf die Vermeidung von 'Timedelta'-Objekten aktualisiert. –

+0

Vielen Dank! Beim Ausführen mit Pandas-Daten (avg_time (df ['Date'])) läuft es in 24,3 Sekunden (gegenüber 24,1 der ursprünglichen Version). Aber als ich versuchte, Daten in Liste (df ['Data']. Tolist(), die 27,3 Sekunden dauerte) zu konvertieren es geht 4.12 vs 4.26 – user2915556

0

Ich war auf der Suche nach dem gleichen, aber dann entdeckte ich dies. Eine sehr einfache Möglichkeit, den Durchschnitt der Datetime-Objektliste zu ermitteln.

import datetime 
    #from datetime.datetime import timestamp,fromtimestamp,strftime ----> You can use this as well to remove unnecessary datetime.datetime prefix :) 
    def easyAverage(datetimeList): ----> Func Declaration 
     sumOfTime=sum(map(datetime.datetime.timestamp,datetimeList)) 
     ''' 
     timestamp function changes the datetime object to a unix timestamp sort of a format. 
     So I have used here a map to just change all the datetime object into a unix time stamp form , added them using sum and store them into sum variable. 
     ''' 
     length=len(datetimeList) #----> Self Explanatory 

     averageTimeInTimeStampFormat=datetime.datetime.fromtimestamp(sumOfTime/length) 
     ''' 
     fromtimestamp function returns a datetime object from a unix timestamp. 
     ''' 

     timeInHumanReadableForm=datetime.datetime.strftime(averageTimeInTimeStampFormat,"%H:%M:%S") #----> strftime to change the datetime object to string. 
     return timeInHumanReadableForm 

Oder Sie können in einer einfachen Linie all dies tun:

avgTime=datetime.datetime.strftime(datetime.datetime.fromtimestamp(sum(map(datetime.datetime.timestamp,datetimeList))/len(datetimeList)),"%H:%M:%S") 

Cheers,