python - 基于时间戳间隔的求和频率
问题描述
我有一个包含时间戳和计数器列的数据框。时间戳以 1 分钟的间隔分开。计数器指示在时间戳发生的事件数。在每个时间戳,我想计算接下来十分钟的事件数。因此,在时间戳 2018-01-03 00:00:00,事件数将为 3。
我创建了一个函数,我将数据帧的每一行传递给该函数,并在接下来的 10 分钟内重新运行事件数。我得到了正确的答案,但运行时间非常高,我想要一种更快的方法来做到这一点,因为我打算在大型数据集上运行它。我认为这可以通过有效使用 groupby 和 transform 来快速实现,但我不知道该怎么做。任何帮助,将不胜感激。谢谢!
a = pd.DataFrame()
a['timestamp'] = pd.date_range('2018-01-03 00:00:00', '2018-01-03 00:20:00', freq='01min').to_list()
a['counter'] = 0
a['counter'][5] = 2
a['counter'][7]= 1
a['counter'][16] = 3
数据框如下所示:
timestamp counter
0 2018-01-03 00:00:00 0
1 2018-01-03 00:01:00 0
2 2018-01-03 00:02:00 0
3 2018-01-03 00:03:00 0
4 2018-01-03 00:04:00 0
5 2018-01-03 00:05:00 2
6 2018-01-03 00:06:00 0
7 2018-01-03 00:07:00 1
8 2018-01-03 00:08:00 0
9 2018-01-03 00:09:00 0
10 2018-01-03 00:10:00 0
11 2018-01-03 00:11:00 0
12 2018-01-03 00:12:00 0
13 2018-01-03 00:13:00 0
14 2018-01-03 00:14:00 0
15 2018-01-03 00:15:00 0
16 2018-01-03 00:16:00 3
17 2018-01-03 00:17:00 0
18 2018-01-03 00:18:00 0
19 2018-01-03 00:19:00 0
20 2018-01-03 00:20:00 0
我将以下函数应用于 df 的每一行,它计算接下来 10 分钟内的事件数
def count_events(a, time_diff):
temp_df = a[(a['timestamp'] > time_diff)& (a['timestamp'] <=(time_diff + pd.Timedelta(minutes=10)))]
events = sum(temp_df['counter'])
return events
for i in range(len(a)):
a['no_of_events'][i] = count_events(a, a['timestamp'][i])
输出是(这是正确的输出):
timestamp counter no_of_events
0 2018-01-03 00:00:00 0 3
1 2018-01-03 00:01:00 0 3
2 2018-01-03 00:02:00 0 3
3 2018-01-03 00:03:00 0 3
4 2018-01-03 00:04:00 0 3
5 2018-01-03 00:05:00 2 1
6 2018-01-03 00:06:00 0 4
7 2018-01-03 00:07:00 1 3
8 2018-01-03 00:08:00 0 3
9 2018-01-03 00:09:00 0 3
10 2018-01-03 00:10:00 0 3
11 2018-01-03 00:11:00 0 3
12 2018-01-03 00:12:00 0 3
13 2018-01-03 00:13:00 0 3
14 2018-01-03 00:14:00 0 3
15 2018-01-03 00:15:00 0 3
16 2018-01-03 00:16:00 3 0
17 2018-01-03 00:17:00 0 0
18 2018-01-03 00:18:00 0 0
19 2018-01-03 00:19:00 0 0
20 2018-01-03 00:20:00 0 0
解决方案
正如人们在评论中建议的那样,滚动是最好的方法。似乎您想从线开始向前滚动,但要向rolling
后滚动。您可以使用反转数据帧的行来解决此问题,.iloc[::-1]
并在滚动操作后再次使用它以将它们放回正确的顺序。
b = a.iloc[::-1].rolling(10, on='timestamp', min_periods=1).sum().iloc[::-1]
b
是:
timestamp counter
0 2018-01-03 00:00:00 3.0
1 2018-01-03 00:01:00 3.0
2 2018-01-03 00:02:00 3.0
3 2018-01-03 00:03:00 3.0
4 2018-01-03 00:04:00 3.0
5 2018-01-03 00:05:00 3.0
6 2018-01-03 00:06:00 1.0
7 2018-01-03 00:07:00 4.0
8 2018-01-03 00:08:00 3.0
9 2018-01-03 00:09:00 3.0
10 2018-01-03 00:10:00 3.0
11 2018-01-03 00:11:00 3.0
12 2018-01-03 00:12:00 3.0
13 2018-01-03 00:13:00 3.0
14 2018-01-03 00:14:00 3.0
15 2018-01-03 00:15:00 3.0
16 2018-01-03 00:16:00 3.0
17 2018-01-03 00:17:00 0.0
18 2018-01-03 00:18:00 0.0
19 2018-01-03 00:19:00 0.0
20 2018-01-03 00:20:00 0.0
编辑
要排除当前时间戳,您可以使用shift将计数器列移动 1 个位置。做就是了:
a['counter'] = a['counter'].shift(-1)
使用前rolling
。
推荐阅读
- hyperledger-composer - 关于Hyperledger Fabric composer:执行cmd composer card list时出错
- html - 3 列与移动浏览器上的页脚重叠
- javascript - Array , Modification 独立拆分数组中的单词
- mysql - 如何使用最新的时间戳记录和间隔平均数据?
- bash - 为什么我的 ERR 陷阱会针对 TERM 信号执行?
- firebase - 如何从firebase函数将一个对象访问到查询数据库中的另一个对象?
- php - woocommerce Rest api的php错误
- ios - 如何在viewDidLoad之外设置按钮的标题文本
- java - 将字符串转换为 BigDecimal 并添加逗号分隔符
- spring-boot - Spring Cloud Stream IntegrationFlow with Rabbitmq 消息传递,消费者提供 ASCII 数字作为消息有效负载