Pandas to_datetime函数行为随Series元素顺序变化的问题
Pandas to_datetime(dayfirst=True) 解析结果随元素顺序变化的问题
问题现象
在验证「日[任意分隔符]月[任意分隔符]年」格式的日期时,使用pd.to_datetime(dayfirst=True, errors='coerce')会出现结果随Series元素顺序变化的异常:
当首元素为数字日期时:
import pandas as pd foo = pd.Series(['01-01-2023','JAN-01-2023']) print(pd.to_datetime(foo, dayfirst=True, errors='coerce').notnull()) # 输出: # 0 True # 1 False # dtype: bool
当首元素为带月份缩写的日期时:
foo = pd.Series(['JAN-01-2023','01-01-2023']) print(pd.to_datetime(foo, dayfirst=True, errors='coerce').notnull()) # 输出: # 0 True # 1 True # dtype: bool
原因分析
这不是bug,而是pd.to_datetime的批量解析逻辑导致的:
- 批量处理时,pandas会优先根据第一个可成功解析的元素推断全局日期格式,后续所有元素都会沿用这个格式解析。
- 第一个案例中,首元素
01-01-2023结合dayfirst=True被推断为DD-MM-YYYY格式,第二个元素JAN-01-2023不符合该格式(首段是月份缩写而非数字日期),因此被强制转为NaT,返回False。 - 第二个案例中,首元素
JAN-01-2023被明确识别为MMM-DD-YYYY格式,此时dayfirst=True的优先级被覆盖,后续的01-01-2023会按MM-DD-YYYY解析,自然能通过验证。
高性能解决方案
避免使用逐行apply的低性能方案,可通过显式指定所有目标格式让pandas严格按规则解析,而非自动推断:
import pandas as pd from functools import reduce def validate_dates(series): # 定义所有符合「日[分隔符]月[分隔符]年」的格式,可按需扩展分隔符和格式 target_formats = [ '%d-%m-%Y', '%d-%b-%Y', '%d/%m/%Y', '%d/%b/%Y', '%d.%m.%Y', '%d.%b.%Y' ] # 用每种格式尝试解析,保留能成功解析的结果 parsed_dates = [pd.to_datetime(series, format=f, errors='coerce') for f in target_formats] # 合并所有解析结果,填充NaN combined_dates = reduce(lambda x, y: x.fillna(y), parsed_dates) return combined_dates.notnull() # 测试不同顺序的Series foo1 = pd.Series(['01-01-2023','JAN-01-2023']) foo2 = pd.Series(['JAN-01-2023','01-01-2023']) print(validate_dates(foo1)) print(validate_dates(foo2)) # 两个测试统一输出: # 0 True # 1 False # dtype: bool
该方案保持了pandas的矢量化处理性能,同时严格遵循「日在前」的格式规则,不受元素顺序影响。
内容的提问来源于stack exchange,提问作者Raul Macedo
相关产品推荐
相关产品推荐

