2013-06-25 6 views
5

У меня есть временной ряд из нескольких дней с 1-минутными данными и хотелось бы усреднить его по всем дням по времени суток.Ускоренный способ группового времени суток в пандах

Это очень медленно:

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

займет почти минуту бежать!

Хотя что-то вроде:

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

занимает лишь доли секунды.

Есть ли более быстрый способ группировки по времени суток?

Любая идея, почему это так медленно?

+0

dt.time не оптимизирован пандами. Требуется много времени, чтобы преобразовать pandas TimeSeries в массив datetime.time. – waitingkuo

ответ

2

И ваш «лямбда-версия» и время собственности введено в version 0.11 кажется медленным в версии 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 

С текущего мастера оба метода значительно быстрее, являются:

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' 

Итак, вы можете либо обновить мастер, либо дождаться 0.11.1, который должен быть выпущен в этом месяце.

+0

Какой у вас «сер»? Это моя «all_data»? Для меня: 'version.version', '% timeit all_data.groupby (lambda x: x.time()). Mean() ', '% timeit all_data.groupby (all_data.index.time) .mean() ' дает: ' '0.11.0'', '1 петли, лучше всего из 3: 21.2 s в loop', ' 1 петли, лучше всего из 3: 21.7 s на loop' ' – joeb1415

+0

@ joeb1415 обновил мой ответ, похоже, из-за версии pandas (числа немного изменились с тех пор, как я нахожусь на другой машине сейчас). «all_data» - это ваш «all_data». – bmu

2

Быстрее группировать атрибуты час/минута/.., а не .time. Вот базовый Джеффа:

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

и без времени это намного быстрее (чем меньше атрибутов, тем быстрее она есть):

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 

Примечание: объекты времени не принимают наносекунды (но это разрешение DatetimeIndex в).

Мы, вероятно, следует преобразовать индекс иметь объекты времени, чтобы сделать это сравнение справедливо:

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

Так это примерно в 10 раз быстрее для максимального разрешения, и вы можете легко сделать его грубее (и быстрее), например, groupby только час и минута.