熊猫 - 计算每小时平均滚动 10 分钟
Posted
技术标签:
【中文标题】熊猫 - 计算每小时平均滚动 10 分钟【英文标题】:Pandas - calculating hourly mean rolling 10 minutes 【发布时间】:2021-12-10 14:37:56 【问题描述】:我有一个名为 df
的数据集,其中包含以下列:
city
- 计算降水的城市
event_timestamp
- 计算降水的时间戳
precipitation
- 降水值
我使用以下代码计算距离event_timestamp
列最近的 10 分钟标记:
df["ten_ts"] = df["event_timestamp"].dt.floor("10 min")
目标: 现在,我想从每 10 分钟点计算过去 1 小时的平均降水量。换句话说,窗口大小为 1 小时,每步移动 10 分钟,并计算该窗口内的降水平均值。我想为每个城市单独执行此操作。
我无法理解它。我尝试了以下操作,但由于明显的原因它没有给出正确的结果:
df.groupby(["city", "ten_ts"]).rolling('1h', on='event_timestamp')["precipitation_1h"].mean().reset_index()
我也尝试过使用for
循环的传统方法,但这非常慢,并且不时会杀死内核。
我们有什么方法可以在 pandas 中以高效的方式完成此任务?
编辑: 样本数据:
city event_timestamp precipitation ten_ts
0 A 2021-10-20 00:17:00.883183 0.316872 2021-10-20 00:10:00
1 A 2021-10-20 00:31:00.883183 1.159092 2021-10-20 00:30:00
2 A 2021-10-20 00:35:00.883183 0.541236 2021-10-20 00:30:00
3 A 2021-10-20 00:43:00.883183 0.152659 2021-10-20 00:40:00
4 A 2021-10-20 01:02:00.883183 1.943939 2021-10-20 01:00:00
5 A 2021-10-20 01:08:00.883183 0.493529 2021-10-20 01:00:00
6 A 2021-10-20 01:18:00.883183 0.164618 2021-10-20 01:10:00
7 A 2021-10-20 01:41:00.883183 0.710624 2021-10-20 01:40:00
8 A 2021-10-20 01:52:00.883183 3.546142 2021-10-20 01:50:00
9 A 2021-10-20 02:03:00.883183 3.177256 2021-10-20 02:00:00
10 A 2021-10-20 02:10:00.883183 0.185931 2021-10-20 02:10:00
11 A 2021-10-20 02:14:00.883183 2.581290 2021-10-20 02:10:00
12 A 2021-10-20 02:19:00.883183 0.393250 2021-10-20 02:10:00
13 A 2021-10-20 02:31:00.883183 0.189209 2021-10-20 02:30:00
14 A 2021-10-20 02:54:00.883183 1.134576 2021-10-20 02:50:00
15 A 2021-10-20 03:02:00.883183 1.449518 2021-10-20 03:00:00
16 A 2021-10-20 03:17:00.883183 0.756092 2021-10-20 03:10:00
17 A 2021-10-20 03:38:00.883183 0.620969 2021-10-20 03:30:00
18 A 2021-10-20 03:51:00.883183 0.119324 2021-10-20 03:50:00
19 A 2021-10-20 04:20:00.883183 0.937305 2021-10-20 04:20:00
20 B 2021-10-20 00:17:00.883183 0.168311 2021-10-20 00:10:00
21 B 2021-10-20 00:31:00.883183 0.681990 2021-10-20 00:30:00
22 B 2021-10-20 00:35:00.883183 1.699022 2021-10-20 00:30:00
23 B 2021-10-20 00:43:00.883183 0.871516 2021-10-20 00:40:00
24 B 2021-10-20 01:02:00.883183 1.226779 2021-10-20 01:00:00
25 B 2021-10-20 01:08:00.883183 0.266825 2021-10-20 01:00:00
26 B 2021-10-20 01:18:00.883183 2.164368 2021-10-20 01:10:00
27 B 2021-10-20 01:41:00.883183 0.906754 2021-10-20 01:40:00
28 B 2021-10-20 01:52:00.883183 0.447001 2021-10-20 01:50:00
29 B 2021-10-20 02:03:00.883183 0.945931 2021-10-20 02:00:00
30 B 2021-10-20 02:10:00.883183 0.847911 2021-10-20 02:10:00
31 B 2021-10-20 02:14:00.883183 0.134165 2021-10-20 02:10:00
32 B 2021-10-20 02:19:00.883183 0.286801 2021-10-20 02:10:00
33 B 2021-10-20 02:31:00.883183 3.113202 2021-10-20 02:30:00
34 B 2021-10-20 02:54:00.883183 0.168888 2021-10-20 02:50:00
35 B 2021-10-20 03:02:00.883183 0.596178 2021-10-20 03:00:00
36 B 2021-10-20 03:17:00.883183 0.993776 2021-10-20 03:10:00
37 B 2021-10-20 03:38:00.883183 0.142311 2021-10-20 03:30:00
38 B 2021-10-20 03:51:00.883183 0.506697 2021-10-20 03:50:00
39 B 2021-10-20 04:20:00.883183 0.125891 2021-10-20 04:20:00
编辑 2: 根据 Riley 的想法,以下是一个解决方案:
df2 = df.groupby(["city", "ten_ts"]).agg('precipitation': ['sum', 'count']).reset_index()
df2.columns = ["city", "ten_ts", "ppt_sum", "ppt_count"]
df3 = df2.groupby("city").rolling('1H', on="ten_ts")[["ppt_sum", "ppt_count"]].sum().reset_index()
df3["avg_ppt"] = df3["ppt_sum"] / df3["ppt_count"]
【问题讨论】:
你能给我们一些数据吗? 添加示例数据 我想我会尝试 1) 按 ten_ts 分组并求和 2) 按 ten_ts 分组并计数 3) 应用 1 小时滚动来求和并计数 4) 将滚动总和除以滚动计数跨度> @Riley,感谢您的想法。我已为我的问题添加了解决方法。 【参考方案1】:我假设至少 ten_ts 列是 DateTime 类型。 如果不是,就从转换成DateTime开始吧。
然后定义2个函数:
计算当前行组平均降水量的函数 (grp), 时间戳“到”前的最后一小时 (tsTo):
def cntMean(grp, tsTo):
return grp[grp.ten_ts.between(tsTo - pd.Timedelta(60, 'T'), tsTo)].precipitation.mean()
处理当前行组 (grp) 的函数,即计算部分行 该组的结果:
def procGrp(grp):
return pd.DataFrame([(ts, cntMean(grp, ts))
for ts in pd.date_range(grp.ten_ts.min(), grp.ten_ts.max(), freq='10T')],
columns=['Time', 'MeanPrecip'])
而实际的计算只涉及一个单个,虽然 有点链接指令:
result = df.groupby('city').apply(procGrp)\
.reset_index(level=1, drop=True).reset_index()
请注意,apply 返回带有 MultiIndex 的 DataFrame。第一级是城市和 第二个 - 每个部分结果的原始索引。
所以“后处理”步骤是:
首先:删除 1 级索引, 秒:将剩下的唯一索引级别 (city) 转换为“常规”列。【讨论】:
我认为这种方法类似于我们使用 apply 的for
循环方法。对于我拥有的实际数据,大约有 80 个城市和一个多月的数据,这使得使用 for 循环或应用在计算上非常昂贵。我尝试了解决方案,但时间又比预期的要长。以上是关于熊猫 - 计算每小时平均滚动 10 分钟的主要内容,如果未能解决你的问题,请参考以下文章