Python DataFrame基于列筛选计算日期差及解决total_seconds属性报错
Python处理DataFrame日期差错误的解决方法
问题描述
作为Python新手,处理DataFrame时需要实现以下需求:
- 针对每个
contact_id,计算TYPE_OPER_VALIDATION=3对应的DTHR_OPERATION日期,与TYPE_OPER_VALIDATION=1对应日期的差值 - 当
TYPE_OPER_VALIDATION=3且日期差≤1小时时,新增列填入'connection',否则填'null'
但执行代码时出现"Series' object has no attribute 'total_seconds'"错误,尝试多种方案后仍存在数据类型问题,原代码片段如下:
df_oper_one = merged_table.loc[(merged_table['TYPE_OPER_VALIDATION']==1),['contact_id','TYPE_OPER_VALIDATION','DTHR_OPERATION']] df_oper_three = merged_table.loc[(merged_table['TYPE_OPER_VALIDATION']==3),['contact_id','TYPE_OPER_VALIDATION','DTHR_OPERATION']] connection = [] for row in merged_table['contact_id']: if (df_validation.loc[(df_validation['TYPE_OPER_VALIDATION']==3)]) & ((pd.to_datetime(df_oper_three['DTHR_OPERATION'],format='%Y-%m-%d %H:%M:%S') - pd.to_datetime(df_oper_one['DTHR_OPERATION'],format='%Y-%m-%d %H:%M:%S').total_seconds()) <= 3600): connection.append('connection') # if diff_date.total_seconds() <= 3600: connection.append('connection') else: connection.append('null') merged_table['connection'] = pd.Series(connection)
错误原因
- 错误调用
total_seconds():该方法属于单个Timedelta对象,不能直接对Series调用,需用.dt.total_seconds()实现逐元素计算 - 逻辑漏洞:循环未针对单个
contact_id匹配对应记录,且df_validation变量未定义 - 效率低下:遍历
contact_id的循环不符合Pandas向量化操作的最佳实践
解决方案
步骤1:统一转换日期列类型
先将DTHR_OPERATION转换为datetime类型,避免重复转换:
merged_table['DTHR_OPERATION'] = pd.to_datetime(merged_table['DTHR_OPERATION'], format='%Y-%m-%d %H:%M:%S')
步骤2:按contact_id聚合日期
用pivot将每个contact_id对应的两种类型日期放到同一行:
pivot_df = merged_table.pivot( index='contact_id', columns='TYPE_OPER_VALIDATION', values='DTHR_OPERATION' ).rename(columns={1: 'date_type1', 3: 'date_type3'})
步骤3:计算日期差并生成目标列
计算日期差的秒数,根据条件生成connection列:
import numpy as np # 计算日期差秒数,自动处理缺失值 pivot_df['date_diff_seconds'] = (pivot_df['date_type3'] - pivot_df['date_type1']).dt.total_seconds() # 按条件赋值:存在type3日期且差≤3600秒时填'connection',否则为'null' pivot_df['connection'] = np.where( (pivot_df['date_diff_seconds'] <= 3600) & pivot_df['date_type3'].notna(), 'connection', 'null' )
步骤4:合并回原数据表
将生成的connection列合并到原表,确保仅在TYPE_OPER_VALIDATION=3的行显示结果:
merged_table = merged_table.merge( pivot_df[['connection']], on='contact_id', how='left' ) # 仅保留TYPE_OPER_VALIDATION=3行的结果,其他行设为'null' merged_table['connection'] = np.where( merged_table['TYPE_OPER_VALIDATION'] == 3, merged_table['connection'], 'null' )
说明
- 改用Pandas向量化操作替代循环,大幅提升处理效率
- 确保每个
contact_id的两条记录正确匹配,避免逻辑错误 - 规范处理日期类型转换,从根源解决数据类型问题
内容的提问来源于stack exchange,提问作者Nicolas Eloy
相关产品推荐
相关产品推荐

