Pandas按条件计算故障与维护记录日期间隔均值并新增列
Pandas 故障与维护记录天数差计算方案
需求规则
- 数据覆盖多个设备ID(
machineID)与4类组件(comp1、comp2、comp3、comp4),需按「machineID+组件编号」维度分组,逐组计算故障日期与对应维护日期的天数差 - 第一步先对维护DataFrame的重复日期做去重处理
- 单条故障仅匹配早于故障日期的同设备同组件维护记录,支持单故障匹配多条维护记录
- 所有匹配到的维护记录与故障记录的天数差取平均值,作为新列
day_dif追加到故障DataFrame中
示例数据
故障DataFrame样例
datetime machineID failure 0 2021-02-04 1 comp3 1 2021-03-21 1 comp1 2 2021-04-05 1 comp4 3 2021-05-05 1 comp3 4 2021-05-20 1 comp2 5 2021-06-04 1 comp4 6 2021-06-19 1 comp2 7 2021-08-03 1 comp3 8 2021-08-03 1 comp4 9 2021-11-01 1 comp4
维护DataFrame样例
datetime machineID comp 0 2020-07-01 1 comp4 1 2020-09-14 1 comp1 2 2020-09-14 1 comp2 3 2020-11-13 1 comp3 4 2021-01-05 1 comp1 5 2021-01-20 1 comp1 6 2021-02-04 1 comp3 7 2021-02-19 1 comp3 8 2021-03-06 1 comp3 9 2021-03-21 1 comp1
计算逻辑示例
以索引为1的故障记录为例:该记录machineID为1,故障日期2021-03-21,故障组件comp1,匹配到同维度下3条早于故障日期的维护记录,对应日期为2020-09-14、2021-01-05、2021-01-20,天数差分别为188天、75天、60天,平均值为(188+75+60)/3=108天,最终写入效果如下:
datetime machineID failure day_dif 1 2021-03-21 1 comp1 108 days
其余组件计算逻辑完全一致。
报错原因说明
之前方案运行触发NotImplementedError与AssertionError,核心原因是低版本pandas(Python3.6对应版本)直接对包含object类型字段的分组对象调用max()聚合时,无法对非数值、非日期的object类型字段做聚合计算,触发类型不支持错误。维护表字段类型如下:
<class 'pandas.core.frame.DataFrame'> Int64Index: 1038 entries, 0 to 1046 Data columns (total 5 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Asset 1038 non-null object 1 Type 1038 non-null object 2 datetime 1038 non-null datetime64[ns] 3 machineID 1038 non-null int64 4 comp 1038 non-null object dtypes: datetime64[ns](1), int64(1), object(3) memory usage: 48.7+ KB
可运行实现代码
import pandas as pd # 预处理:统一日期格式 failures['datetime'] = pd.to_datetime(failures['datetime']) maint['datetime'] = pd.to_datetime(maint['datetime']) # 步骤1:维护数据去重,同设备+同组件+同维护日期仅保留1条,避免重复计算 # 用drop_duplicates替代groupby max,从根源规避object类型聚合报错 maint_dedup = maint.drop_duplicates(subset=['machineID', 'comp', 'datetime']).reset_index(drop=True) # 步骤2:关联合并故障与维护数据,匹配同设备同组件的记录 fail_renamed = failures.rename(columns={'failure': 'comp'}) merged = fail_renamed.merge( maint_dedup[['machineID', 'comp', 'datetime']], on=['machineID', 'comp'], how='left', suffixes=('_fail', '_maint') ) # 步骤3:过滤掉维护日期晚于/等于故障日期的无效匹配 merged = merged[merged['datetime_maint'] < merged['datetime_fail']] # 步骤4:计算天数差,按单条故障记录维度求平均值 merged['day_diff_val'] = (merged['datetime_fail'] - merged['datetime_maint']).dt.days avg_diff = merged.groupby(level=0)['day_diff_val'].mean() # 步骤5:结果写回原故障表,格式化day_dif字段 failures['day_dif'] = avg_diff.apply(lambda x: f"{int(round(x))} days" if pd.notna(x) else pd.NA)
代码避坑说明
- 去重环节不使用全字段groupby聚合,仅通过
drop_duplicates针对业务需要的三个维度去重,完全避开object字段聚合的报错问题 - 关联后先做时间条件过滤,再计算差值,符合需求中「仅保留早于故障日期维护记录」的规则
- 提前强制转换日期字段类型,避免字符串格式日期导致的计算错误
- 对无匹配维护记录的故障行,自动填充为空值,不会抛出异常
内容的提问来源于stack exchange,提问作者PeakyBlinder
相关产品推荐
相关产品推荐

