正确解析混乱日期需设errors='coerce'避免中断,并优先指定format提速;多格式混合时依赖pandas自动推断更鲁棒;dt.normalize()保留datetime64类型,dt.date转为object;resample前须确保数值列dtype正确且显式选取;时区转换须先tz_localize再tz_convert。

如何用 pd.to_datetime() 正确解析混乱的日期字符串
很多 CSV 或 Excel 里的时间列是字符串,格式五花八门:"2023/05/12"、"12-05-2023"、"2023-05-12 14:30:00.123",甚至混着空值和非法值(如 "N/A")。直接调 pd.to_datetime() 很容易报 ValueError: Unknown string format。
关键不是“能不能转”,而是“怎么控制失败行为 + 明确指定格式”:
- 加
errors='coerce':把无法解析的全转成NaT(时间上的NaN),避免中断;不加的话默认'raise',一错就崩 - 明确传
format参数(比如format='%Y-%m-%d')能提速 3–5 倍,尤其数据量大时;但格式必须严格匹配,"2023-5-12"就会失败(月份/日期没补零) - 遇到多格式混合(如既有
"%Y/%m/%d"又有"%d-%b-%Y"),别硬写 format,改用infer_datetime_format=True(仅对标准 ISO 格式有效)或干脆不设 format,靠 pandas 自推——它会慢一点,但更鲁棒
示例:
df['date'] = pd.to_datetime(df['date_str'], errors='coerce', format='%Y-%m-%d')
为什么 dt.date 和 dt.normalize() 返回结果不同
当你从 datetime64[ns] 列中提取“日期部分”,容易混淆这两个操作:
-
df['ts'].dt.date返回的是 Python 原生date对象组成的Series,类型变成object,后续无法再用.dt访问器,也不能参与向量化时间运算 -
df['ts'].dt.normalize()返回仍是datetime64[ns]类型,只是把时分秒归零(如2023-05-12 14:30:00→2023-05-12 00:00:00),保留了时间索引能力 - 真要只留日期且保持 dtype 可计算,用
.dt.floor('D')或.dt.date.astype('datetime64[D]')(后者在 pandas 2.0+ 更稳)
设置时间索引后 resample() 报 No numeric types to aggregate
常见于你做了 df.set_index('time_col'),但忘记把目标数值列显式指定为聚合对象。pandas 的 resample() 默认尝试对所有数值列聚合,但如果 DataFrame 里混着字符串列、category 列,或数值列名被误设为非数字类型(比如读取时没设 dtype,导致数字被当字符串读进来了),就会报这个错。
- 先确认数值列 dtype:
df['value'].dtype应为float64或int64;如果是object,大概率是含空格或单位(如"12.5 kg"),得先用str.extract(r'(\d+\.?\d*)')提纯 - resample 时显式链式选择列:
df.resample('D')['sales'].sum(),而不是df.resample('D').sum() - 注意频率字符串是否合法:
'D'(日)、'MS'(月首)、'W-FRI'(周五为周结束),错写成'day'或'monthly'会静默失败或报错
时区转换中 tz_localize() 和 tz_convert() 别颠倒顺序
原始时间戳没有时区(naive),想转成带时区(aware)再换目标时区,必须两步走,且顺序不能反:
- 先用
.dt.tz_localize('UTC')给 naive 时间打上“这是 UTC 时间”的标签(不改变数值) - 再用
.dt.tz_convert('Asia/Shanghai')换算成东八区时间(数值会变,+8 小时) - 如果跳过 localize 直接 convert,pandas 会报
TypeError: Cannot convert tz-naive timestamps, use tz_localize to localize - 反过来,对已带时区的时间再调
tz_localize()(比如已为UTC还强设'CST'),会导致时区元数据错误,后续计算全偏
真实场景常遇到“本地时间存库,但没记时区”。这时应按业务约定 localize,例如中国服务器日志默认是 'Asia/Shanghai',而非盲目设 'UTC'。
时间处理最易错的不是语法,而是隐式假设:假设字符串格式统一、假设输入无脏数据、假设所有时间都属于同一时区。一旦漏掉 errors='coerce' 或忘了 tz_localize,问题往往延迟到聚合或画图阶段才暴露,排查成本陡增。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











