如何用Pandas识别CO₂超1000后降至500的时间区间
提取CO₂超标后回落的时间区间
问题描述
拥有包含time时间列和整数测量值co2列的时间序列数据,需要找出CO₂首次大于等于1000的时间,以及从该时间点开始CO₂降至小于等于500的时间,最终生成对应的时间区间并计算时长。现有方法能获取零散的起止时间,但需要更高效的分组处理方式。
示例数据:
import pandas as pd d = {'time': ['2024-06-13 18:18:00','2024-06-13 18:18:01','2024-06-13 18:18:02','2024-06-13 18:18:03','2024-06-13 18:18:04','2024-06-13 18:18:05','2024-06-13 18:18:06'], 'co2': [0,1000,1000,500,1000,1000,500]} df = pd.DataFrame(data=d, index=[0,1,2,3,4,5,6])
期望输出:
| index | start | end |
|---|---|---|
| 1 | 2024-06-13 18:18:01 | 2024-06-13 18:18:03 |
| 2 | 2024-06-13 18:18:04 | 2024-06-13 18:18:06 |
解决方案
通过标记状态变化+分组的方式高效实现,步骤如下:
步骤1:转换时间格式并标记状态
先把time列转为datetime类型方便后续计算,再标记每条数据的状态(超标/回落),最后通过shift()检测状态切换节点生成分组ID:
# 转换time列为datetime格式 df['time'] = pd.to_datetime(df['time']) # 标记状态:1=CO₂≥1000(超标),0=CO₂≤500(回落) df['status'] = df['co2'].apply(lambda x: 1 if x >= 1000 else 0) # 检测状态变化:当前行与上一行状态不同则标记为1 df['state_change'] = (df['status'] != df['status'].shift()).astype(int) # 生成分组ID:累计状态变化次数,将连续相同状态的行归为一组 df['group_id'] = df['state_change'].cumsum()
步骤2:提取区间起止时间并合并结果
筛选超标组的起始时间和对应回落组的结束时间,关联后整理成目标格式:
# 提取每个超标组的首次出现时间(区间起始) start_df = df[df['status'] == 1].groupby('group_id')['time'].first().reset_index() start_df.rename(columns={'time': 'start'}, inplace=True) # 提取每个回落组的最后出现时间(区间结束) end_df = df[df['status'] == 0].groupby('group_id')['time'].last().reset_index() end_df.rename(columns={'time': 'end'}, inplace=True) # 关联超标组和对应的回落组:超标组的group_id+1就是对应回落组的ID result = pd.merge(start_df, end_df, left_on='group_id', right_on=end_df['group_id']-1, how='left') # 整理结果格式,添加自增索引 result = result[['start', 'end']].reset_index(drop=True) result.index += 1 # 让索引从1开始 # 可选:计算区间时长 result['duration'] = result['end'] - result['start']
最终输出
运行后result的内容如下:
| index | start | end | duration |
|---|---|---|---|
| 1 | 2024-06-13 18:18:01 | 2024-06-13 18:18:03 | 00:00:02 |
| 2 | 2024-06-13 18:18:04 | 2024-06-13 18:18:06 | 00:00:02 |
关键说明
- 转换
time列为datetime类型是为了直接计算时间差(时长),避免字符串操作的麻烦。 - 用
shift()检测状态变化,能精准划分连续的超标/回落区间,解决零散时间点匹配混乱的问题。 - 分组后提取首尾时间,确保每个区间的起始是首次超标时间,结束是首次回落至阈值的时间。
内容的提问来源于stack exchange,提问作者MikeJ
相关产品推荐
相关产品推荐

