Python pandas批量合并xlsx 时长字段转timedelta遇各类报错
问题根源梳理
- 报错的诱因有一半是基础笔误:代码里把列名
AVG HVR错写成了AVG HVG(多写了字母G),直接指向不存在的列;另外实际列名带换行符(比如AVG HVR\n(HH:MM:SS)),直接写不带特殊字符的列名自然触发KeyError。 - 两个目标字段的本质是:Excel存储时长时默认用1900-01-01作为零值日期,把实际时长拼在这个固定日期后面,不是真正的业务日期。读入pandas后字段类型混杂,部分被识别为datetime64的Timestamp对象、部分因为带毫秒被识别为字符串,直接转timedelta自然触发类型不匹配的报错。
可落地的解决方案
第一步:先修正列名匹配逻辑
- 先执行
print(df.columns.tolist())拿到实际的精确列名,不要靠猜测写列名字符串,避免特殊字符(换行、空格)导致的匹配失败。 - 把所有代码里误写的
AVG HVG统一替换成和实际列名一致的名称。
第二步:批量转换为标准timedelta类型
不管字段当前是字符串、还是Timestamp对象,用兼容逻辑统一处理,代码如下:
import pandas as pd # 定义通用转换函数,兼容两类混存的字段值 def duration_converter(value): # 遇到空值直接返回空时间标记 if pd.isna(value): return pd.NaT # 如果是pandas识别出的Timestamp类型,直接计算和1900-01-01的时间差 if isinstance(value, pd.Timestamp): return value - pd.Timestamp("1900-01-01") # 如果是字符串类型,先转成Timestamp再计算时间差 ts = pd.Timestamp(str(value)) return ts - pd.Timestamp("1900-01-01") # 匹配所有需要转换的HVR相关时长列 target_cols = [col for col in df.columns if "HVR" in col and ("AVG" in col or "Longest" in col)] # 逐列应用转换 for col in target_cols: df[col] = df[col].apply(duration_converter)
转换完成后:
- 带毫秒的
1900-01-01 00:18:30.080000会被转为0 days 00:18:30.080000的timedelta类型; - 不带毫秒的
1900-01-01 00:23:09会被转为0 days 00:23:09的timedelta类型; - 导出到Excel时,pandas会自动将timedelta值识别为可计算的时长格式,不需要额外手动调整单元格格式。
可选:读取文件时提前做转换,减少后续处理量
如果想在合并文件的阶段就把字段类型处理好,可以把原来的读取逻辑加上转换器参数:
files = glob.glob(path + "/*.xlsx") df = pd.concat([ pd.read_excel( fp, index_col=0, header=3, # 读取时直接对目标列做转换,避免读入后类型混杂 converters={ col: duration_converter for col in ["AVG HVR", "Longest HVR"] } ).assign(New=os.path.basename(fp)) for fp in files ])
之前尝试失败的原因说明
- 直接运行
pd.to_timedelta(df['AVG HVG'])报错:一方面是列名拼写错误指向不存在的列,另一方面字段里混存了Timestamp对象,纯字符串的timedelta转换逻辑不兼容非字符串的Timestamp类型。 - 用
datetime.combine(date.min, df['AVG HVG'])报错:这个方法只接受单个标量值,不支持直接传入整列Series做批量计算。 - 运行
.dt.strftime报KeyError:写的列名和实际带换行符的列名不匹配,pandas找不到目标列。
内容的提问来源于stack exchange,提问作者voluzy
相关产品推荐
相关产品推荐

