在 pandas 中以更快的方式分组一天中的时间

Posted

技术标签:

【中文标题】在 pandas 中以更快的方式分组一天中的时间【英文标题】:Faster way to groupby time of day in pandas 【发布时间】:2013-06-21 17:40:51 【问题描述】:

我有几天的 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()

只需要几分之一秒。

有没有更快的按时间分组的方法?

知道为什么这么慢吗?

【问题讨论】:

dt.time 没有被 pandas 优化。将 pandas TimeSeries 转换为 datetime.time 数组需要很长时间。 【参考方案1】:

按小时/分钟/.. 属性分组比.time 更快。这是 Jeff 的基线:

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 只是小时和分钟..

【讨论】:

【参考方案2】:

您的“lambda-version”和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

使用当前的 master 两种方法都快得多:

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'

因此,您可以更新到 master 或等待本月发布的 0.11.1。

【讨论】:

你的“ser”是什么?是我的“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 loops, best of 3: 21.2 s per loop1 loops, best of 3: 21.7 s per loop ` @joeb1415 更新了我的答案,似乎是由于熊猫版本(由于我现在在另一台机器上,数字有所变化)。 “all_data”是你的“all_data”。

以上是关于在 pandas 中以更快的方式分组一天中的时间的主要内容,如果未能解决你的问题,请参考以下文章

按一天中的时间分组数据

Pandas groupby 一天中的时间到字典

python pandas 按一天中的小时求和

熊猫方式将一天中的时间(有效的 datetime.time)转换为浮点变量

pandas groupby 一天中的时间,带 15 分钟的垃圾箱

使用 pandas 的滚动窗口计算一天中每个时间的平均值