Python实现CSV逐行计算时间差,筛选超15分钟设备延迟记录
解决CSV设备数据超15分钟间隔筛选问题
问题背景
有数千行CSV设备传输数据,设备应每10分钟传输一次,需找出两次读数间隔超过15分钟的记录。现有代码需手动将时间转为浮点数,处理数百个CSV时效率极低;改用datetime模块时出现类型错误:
TypeError: '>' not supported between instances of 'datetime.timedelta' and 'datetime.datetime'
错误原因
两次datetime对象相减得到的是**timedelta(时间间隔)**,但你将阈值定义为datetime(具体时间点),两种类型无法直接比较,导致报错。
修正方案
方案1:修正原循环逻辑(兼容原有代码结构)
import pandas as pd from datetime import datetime, timedelta df = pd.read_csv('file.csv') # 正确转换eventTime列为datetime类型,并赋值回原DataFrame df['eventTime'] = df['eventTime'].apply(lambda x: datetime.strptime(x, "%H:%M:%S")) df2 = pd.DataFrame() device_ids = df["deviceId"].unique().tolist() # 阈值定义为timedelta类型:15分钟 threshold = timedelta(minutes=15) for device_id in device_ids: subset = df[df.deviceId == device_id].sort_values('eventTime') # 确保时间有序 for row in range(len(subset)-1): # 计算当前行与下一行的时间差(后减前得到正间隔) difference = subset.iloc[row+1]['eventTime'] - subset.iloc[row]['eventTime'] if difference > threshold: df2 = pd.concat([df2, subset.iloc[[row, row+1]]]) # 用concat替代append,效率更高 # 去重避免同一记录被多次添加 df2 = df2.drop_duplicates() df2.to_csv('file2.csv', index=False)
方案2:Pandas向量化优化(高效处理大数据)
嵌套循环处理数千行数据效率低下,推荐用Pandas分组+shift方法实现:
import pandas as pd df = pd.read_csv('file.csv') # 转换时间列 df['eventTime'] = pd.to_datetime(df['eventTime'], format="%H:%M:%S") # 按设备分组,获取下一行的时间 df['next_eventTime'] = df.groupby('deviceId')['eventTime'].shift(-1) # 计算时间差 df['time_diff'] = df['next_eventTime'] - df['eventTime'] # 筛选出间隔超过15分钟的行 mask = df['time_diff'] > pd.Timedelta(minutes=15) # 获取符合条件的当前行和下一行 result = pd.concat([df[mask], df[mask.shift(1).fillna(False)]]) # 去重并清理冗余列后保存 result = result.drop_duplicates().drop(columns=['next_eventTime', 'time_diff']) result.to_csv('file2.csv', index=False)
代码说明
- 时间列转换:用
pd.to_datetime替代手动strptime,更简洁高效 - 阈值类型:用
timedelta/pd.Timedelta定义时间间隔,与时间差类型匹配 - 数据有序性:处理前按时间排序,避免因数据乱序导致计算错误
- 效率优化:向量化操作比嵌套循环快数倍,适合处理大规模数据
测试数据验证
用你提供的示例数据测试,若某设备有如下记录:
| eventTime | deviceId |
|---|---|
| 15:30:00 | 11234889 |
| 16:00:00 | 11234889 |
| 16:20:00 | 11234889 |
代码会筛选出15:30:00和16:00:00这两条间隔30分钟的记录。
内容的提问来源于stack exchange,提问作者coghlan
相关产品推荐
相关产品推荐

