2013-06-25 8 views
5

Mam serię danych z kilkudniowymi danymi 1-minutowymi i chciałbym ją uśrednić przez wszystkie dni według pory dnia.Szybszy sposób grupowania według pory dnia w pandach

Jest to bardzo powolny:

from datetime import datetime 
from pandas import date_range, Series 
time_ind = date_range(datetime(2013, 1, 1), datetime(2013, 1, 10), freq='1min') 
all_data = Series(randn(len(time_ind)), time_ind) 
time_mean = all_data.groupby(lambda x: x.time()).mean() 

trwa prawie minutę do uruchomienia!

ile coś takiego:

time_mean = all_data.groupby(lambda x: x.minute).mean() 

trwa tylko ułamek sekundy.

Czy istnieje szybszy sposób grupowania według pory dnia?

Każdy pomysł, dlaczego jest tak powolny?

+0

dt.time nie jest zoptymalizowany przez pandy. Wymaga to dużo czasu na przekształcenie pandy TimeSeries w tablicę datetime.time. – waitingkuo

Odpowiedz

2

Zarówno „lambda-wersja” a właściwość czas wprowadzony w version 0.11 wydaje się być powolne w wersji 0.11.0:

In [4]: %timeit all_data.groupby(all_data.index.time).mean() 
1 loops, best of 3: 11.8 s per loop 

In [5]: %timeit all_data.groupby(lambda x: x.time()).mean() 
Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <type 'exceptions.RuntimeError'> ignored 
Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <type 'exceptions.RuntimeError'> ignored 
Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <type 'exceptions.RuntimeError'> ignored 
1 loops, best of 3: 11.8 s per loop 

Z aktualnego mistrza obie metody są znacznie szybsze:

In [1]: pd.version.version 
Out[1]: '0.11.1.dev-06cd915' 

In [5]: %timeit all_data.groupby(lambda x: x.time()).mean() 
1 loops, best of 3: 215 ms per loop 

In [6]: %timeit all_data.groupby(all_data.index.time).mean() 
10 loops, best of 3: 113 ms per loop 
'0.11.1.dev-06cd915' 

Można więc zaktualizować system do wersji master lub poczekać na wersję 0.11.1, która ma zostać wydana w tym miesiącu.

+0

Jaki jest twój "ser"? Czy to moja "all_data"? Dla mnie: 'version.version', '% timeit all_data.groupby (lambda x: x.time()). Mean() ', '% timeit all_data.groupby (all_data.index.time) .mean() ' otrzymujemy: ' '0.11.0'', '1 pętle, najlepiej 3: 21,2 s na loop', ' 1 pętle, najlepiej 3: 21,7 s na loop' ' – joeb1415

+0

@ joeb1415 zaktualizowałem moją odpowiedź, wydaje się, że jest to spowodowane wersją pandy (numery zmieniły się nieco, ponieważ jestem teraz na innej maszynie). "all_data" to Twoja "all_data". – bmu

2

Szybciej grupować według atrybutów godzina/minuta .. niż .time. Oto Jeffa bazowa:

In [11]: %timeit all_data.groupby(all_data.index.time).mean() 
1 loops, best of 3: 202 ms per loop 

i bez czasu jest znacznie szybszy (im mniej atrybutów szybciej to jest):

In [12]: %timeit all_data.groupby(all_data.index.hour).mean() 
100 loops, best of 3: 5.53 ms per loop 

In [13]: %timeit all_data.groupby([all_data.index.hour, all_data.index.minute, all_data.index.second, all_data.index.microsecond]).mean() 
10 loops, best of 3: 20.8 ms per loop 

Uwaga: Przedmioty czas nie akceptują nanosekundy (ale to rozdzielczość DatetimeIndex za).

Powinniśmy prawdopodobnie przekonwertować indeks mieć przedmioty czas, aby dokonać tego porównania godziwej:

In [21]: res = all_data.groupby([all_data.index.hour, all_data.index.minute, all_data.index.second, all_data.index.microsecond]).mean() 

In [22]: %timeit res.index.map(lambda t: datetime.time(*t)) 
1000 loops, best of 3: 1.39 ms per loop 

In [23]: res.index = res.index.map(lambda t: datetime.time(*t)) 

więc jest około 10 razy szybciej maksymalnej rozdzielczości i można łatwo zrobić to grubsze (i szybciej), na przykład groupby tylko godzina i minuta ..

Powiązane problemy