
本教程详细讲解如何使用pandas在dataframe中,针对每个分组(如团队)的每行数据,高效地判断其后指定时间窗口(例如7秒内)是否存在特定事件。我们将利用`groupby.rolling`结合时间偏移量,实现精确的时间窗口条件查询,并提供示例代码和两种场景(是否包含当前行)的解决方案,以应对复杂的时间序列分析需求。
在数据分析领域,尤其是在处理日志、传感器数据或金融交易等时间序列数据时,经常需要识别在特定时间窗口内发生的模式或事件。Pandas作为Python数据科学的核心库,提供了强大的工具来处理这类任务。本教程将深入探讨如何利用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)要解决“在每个团队的每行数据之后7秒内是否存在事件'2'”的问题,我们将利用以下Pandas功能:
本节目标是判断“在当前行之后7秒内”是否存在事件event == 2,且不包含当前行本身。
创建布尔标志列: 首先,创建一个新的布尔列,标记出event等于2的行。
df_temp = df.assign(is_2_in_7_sec=df['event'].eq(2))
逆序处理与分组滚动: 由于rolling窗口是右闭合的(包含当前点和之前的数据),为了检查“之后”的事件,我们需要对DataFrame进行逆序处理([::-1])。这样,当我们在逆序的DataFrame上应用rolling时,窗口实际上会包含原始顺序中当前行“之后”的数据。
df_reversed = df_temp[::-1]
应用groupby.rolling并使用shift(1)排除当前行:
合并结果: 最后,将计算出的布尔结果合并回原始DataFrame。由于我们进行了逆序和reset_index操作,需要通过merge和set_index来确保结果正确对齐。
# 复制原始DataFrame以保留原始索引,方便后续合并
df_indexed = df.reset_index()
# 步骤1 & 2: 创建布尔标志列并逆序处理
df_temp_reversed = df.assign(is_2_in_7_sec=df['event'].eq(2))[::-1]
# 步骤3: 分组滚动,应用shift(1)排除当前行,并聚合
# 注意:这里groupby的df['team']是原始df的team列,确保分组正确
rolling_result = (
df_temp_reversed.groupby(df['team']) # 使用原始df的team列进行分组
.rolling('7s', on='timeStamp')
['is_2_in_7_sec']
.apply(lambda x: x.shift(1).max(), raw=False) # raw=False 确保x是Series
.eq(1) # 转换为布尔值
.reset_index()
)
# 步骤4: 合并回原始DataFrame
# 需要先重命名rolling_result中的index列,避免与原始df的index冲突
rolling_result = rolling_result.rename(columns={'index': 'original_index'})
out_df_exclude_self = (
df_indexed.merge(
rolling_result,
left_on=['index', 'team', 'timeStamp'], # 匹配原始索引、team和timeStamp
right_on=['original_index', 'team', 'timeStamp'],
how='left'
)
.drop(columns='original_index') # 删除临时列
.set_index('index') # 恢复原始索引
.reindex(df.index) # 确保顺序与原始df一致
)
print("\n结果DataFrame (不包含当前行):")
print(out_df_exclude_self)输出解释: is_2_in_7_sec列显示了在当前行之后7秒内(不包括当前行)是否存在event == 2的事件。例如,对于Team A的第一行(event 1, 14:57:13),其后7秒内(14:57:16)存在一个event 2,所以结果为True。
如果需求是判断“在当前行所在的时间点及其后7秒内”是否存在事件event == 2(即包含当前行本身),则处理会稍微简化。我们不再需要shift(1)来排除当前行。
# 复制原始DataFrame以保留原始索引,方便后续合并
df_indexed = df.reset_index()
# 步骤1 & 2: 创建布尔标志列并逆序处理
df_temp_reversed = df.assign(is_2_in_7_sec=df['event'].eq(2))[::-1]
# 步骤3: 分组滚动,直接使用max()聚合(包含当前行)
rolling_result_include_self = (
df_temp_reversed.groupby(df['team']) # 使用原始df的team列进行分组
.rolling('7s', on='timeStamp')
['is_2_in_7_sec']
.max() # 直接使用max(),因为它会包含当前窗口内的所有值
.astype(bool) # 确保结果是布尔类型
.reset_index()
)
# 步骤4: 合并回原始DataFrame
rolling_result_include_self = rolling_result_include_self.rename(columns={'index': 'original_index'})
out_df_include_self = (
df_indexed.merge(
rolling_result_include_self,
left_on=['index', 'team', 'timeStamp'],
right_on=['original_index', 'team', 'timeStamp'],
how='left'
)
.drop(columns='original_index')
.set_index('index')
.reindex(df.index)
)
print("\n结果DataFrame (包含当前行):")
print(out_df_include_self)输出解释: 与之前不同的是,Team A的event == 2的那一行(14:57:16)现在其is_2_in_7_sec也为True,因为该行本身满足条件。
本教程详细展示了如何利用Pandas的groupby.rolling功能,结合时间偏移和布尔逻辑,在分组时间序列数据中高效地识别特定时间窗口内的事件。通过对DataFrame进行逆序处理,并巧妙运用shift(1),我们成功实现了“在当前行之后”的时间窗口查询。理解这些技术对于进行复杂的时间序列分析和模式检测至关重要,为处理实际业务场景中的时间相关问题提供了强大的工具。
以上就是Pandas时间序列分析:在指定时间窗口内识别特定事件的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号