熊猫 - 计算每小时平均滚动 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 分钟的主要内容,如果未能解决你的问题,请参考以下文章

根据当地时间 (HH:MM) 计算 24 小时周期内每分钟的平均销售额

如何在特定小时的滚动平均值的熊猫数据框中添加一列

具有时间偏移熊猫的滚动平均值

平均每五分钟数据作为熊猫数据框中的一个数据点

在熊猫中平均每分钟

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