
本教程详细阐述了如何使用pandas的`groupby`和`rolling`功能,在指定时间窗口内按组(例如团队)检测特定事件的发生。文章通过示例代码演示了两种场景:排除当前行和包含当前行进行时间窗口内事件查找,并提供了关键操作如时间戳转换、dataframe反转与`shift`的详细解释,旨在帮助用户高效处理时序数据中的复杂条件查询。
在数据分析中,我们经常需要处理包含时间序列信息的DataFrame,并根据时间窗口内的条件来标记或聚合数据。一个常见的需求是,针对某个分组(如“团队”),判断在当前事件发生后的特定时间范围内是否发生了另一个特定事件。本教程将深入探讨如何利用Pandas的强大功能,特别是groupby、rolling以及时间序列操作,高效地解决这类问题。
首先,我们需要一个包含事件、分组标识和时间戳的DataFrame。为了确保时间相关的操作能够正确执行,时间戳列必须被转换为Pandas的datetime类型。
import pandas as pd
# 示例数据
data = {
'event': [1, 1, 3, 2, 3, 1, 2, 3, 4, 5],
'team': ['A', 'A', 'B', 'A', 'B', 'C', 'C', 'C', 'D', 'D'],
'timeStamp': ['2023-07-23 14:57:13.357', '2023-07-23 14:57:14.357',
'2023-07-23 14:57:15.357', '2023-07-23 14:57:16.357',
'2023-07-23 14:57:20.357', '2023-07-23 14:57:13.357',
'2023-07-23 14:57:18.357', '2023-07-23 14:57:23.357',
'2023-07-23 14:57:23.357', '2023-07-23 14:57:25.357']
}
df = pd.DataFrame(data)
# 将 'timeStamp' 列转换为 datetime 类型
df['timeStamp'] = pd.to_datetime(df['timeStamp'])
print("原始DataFrame:")
print(df)要解决按团队分组并在时间窗口内查找事件的问题,我们需要结合使用groupby和rolling。
我们的目标是,对于DataFrame中的每一行,判断在当前行发生后7秒内(不包括当前行本身)同一团队中是否存在事件类型为“2”的记录。
为了实现向前看(查找未来事件)并排除当前行,我们将采用以下策略:
# 步骤1: 创建布尔列
df_temp = df.assign(is_2_in_7_sec_raw=df['event'].eq(2))
# 步骤2 & 3: 反转DataFrame,按团队分组,并应用rolling窗口
# 注意:这里对 df_temp 进行 df['team'] 的 groupby 是为了在原始索引上进行分组,
# 但 rolling 操作是在 df_temp 的时间戳上进行的。
# 更直接的方式是先进行 assign 和反转,再 groupby
rolled_results = (df_temp[::-1] # 反转DataFrame以实现“向前看”
.groupby('team')
.rolling('7s', on='timeStamp')
['is_2_in_7_sec_raw']
.apply(lambda x: x.shift(1).max()) # shift(1) 排除当前行,max() 检查是否有 True
.eq(1) # 转换为布尔值
.reset_index())
# 步骤4: 合并结果
# 需要将原始DataFrame的索引重置,以便与 rolled_results 的 level_1 索引(原索引)进行合并
df_output_exclude_self = (df.reset_index()
.merge(rolled_results, how='left', left_on=['team', 'index'], right_on=['team', 'level_1'])
.set_index('index')
.reindex(df.index) # 确保原始顺序
)
# 清理合并后的多余列并重命名
df_output_exclude_self = df_output_exclude_self[['event', 'team', 'timeStamp', 'is_2_in_7_sec_raw']]
df_output_exclude_self = df_output_exclude_self.rename(columns={'is_2_in_7_sec_raw': 'is_2_in_7_sec'})
print("\n场景一:排除当前行,检测未来7秒内是否存在事件'2':")
print(df_output_exclude_self)代码解释:
如果需要包含当前行本身进行检测,逻辑会稍微简化,无需使用 shift(1)。
# 步骤1: 创建布尔列
df_temp_include_self = df.assign(is_2_in_7_sec_raw=df['event'].eq(2))
# 步骤2 & 3: 反转DataFrame,按团队分组,并应用rolling窗口
rolled_results_include_self = (df_temp_include_self[::-1] # 反转DataFrame
.groupby('team')
.rolling('7s', on='timeStamp')
['is_2_in_7_sec_raw']
.max() # 直接取max(),包含当前行
.astype(bool) # 确保为布尔类型
.reset_index())
# 步骤4: 合并结果
df_output_include_self = (df.reset_index()
.merge(rolled_results_include_self, how='left', left_on=['team', 'index'], right_on=['team', 'level_1'])
.set_index('index')
.reindex(df.index)
)
# 清理合并后的多余列并重命名
df_output_include_self = df_output_include_self[['event', 'team', 'timeStamp', 'is_2_in_7_sec_raw']]
df_output_include_self = df_output_include_self.rename(columns={'is_2_in_7_sec_raw': 'is_2_in_7_sec'})
print("\n场景二:包含当前行,检测未来7秒内是否存在事件'2':")
print(df_output_include_self)本教程详细介绍了如何利用Pandas的groupby和rolling功能,结合时间序列处理技巧,在复杂的时间窗口内按分组检测特定事件。通过理解DataFrame反转和shift操作的精妙应用,我们能够灵活地实现“向前看”的事件检测,无论是排除当前行还是包含当前行。掌握这些技术将极大地提升您在处理时序数据时的分析能力。
以上就是Pandas时间窗口内事件检测:按团队分组查找特定事件的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号