You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame日期转换异常问题排查与解决求助

问题描述

尝试转换DataFrame的['Date','Value Dt']两列为日期格式时出现异常:2023年5月1日至12日的部分日期被错误按%m/%d/%Y解析,其余日期(包括5月13日后)则正常按%d/%m/%Y解析。使用的转换代码如下:

columns_to_convert_to_date= ['Date','Value Dt']
regex_pattern = r'\d{2}/\d{2}/\d{4}'
for column in columns_to_convert_to_date:
        full_bank_df_hdfc[column] = full_bank_df_hdfc[column].apply(lambda x: pd.to_datetime(x, format='%d/%m/%Y', errors='coerce') if re.match(regex_pattern, str(x)) else pd.to_datetime(x, errors='coerce'))

单独使用pd.to_datetime(full_bank_df_hdfc['Date'],format='%d/%m/%y', errors='coerce')能得到目标输出,但会将已有的datetime格式行转为NaT。

异常原因分析
  • 混合日期格式触发自动推断错误:原始数据中5月1日-12日的日期字符串为%m/%d/%Y格式,其余日期为%d/%m/%Y格式。当日期的日部分≤12时,pd.to_datetime的自动推断逻辑会优先按%m/%d/%Y解析(受系统locale或默认规则影响);而日部分>12时,无法按%m/%d/%Y解析,只能按%d/%m/%Y解析,因此5月13日后恢复正常。
  • 现有代码的缺陷:对所有匹配正则的字符串强制用%d/%m/%Y解析,会把%m/%d/%Y格式的日期(如05/01/2023)错误解析为2023-01-05;单独指定格式时,pd.to_datetime会将已有的datetime对象转为字符串再解析,因格式不匹配被强制转为NaT。
解决方法

方法一:自定义解析函数,分类型处理

先判断数据类型,对字符串类型先尝试%d/%m/%Y解析,失败则尝试%m/%d/%Y,直接保留已有的datetime值:

import pandas as pd
import re

columns_to_convert_to_date = ['Date','Value Dt']
regex_pattern = r'\d{2}/\d{2}/\d{4}'

def parse_date(x):
    if isinstance(x, pd.Timestamp):
        return x
    x_str = str(x)
    if re.match(regex_pattern, x_str):
        # 优先尝试目标格式,失败则尝试备选格式
        dt = pd.to_datetime(x_str, format='%d/%m/%Y', errors='coerce')
        if pd.isna(dt):
            dt = pd.to_datetime(x_str, format='%m/%d/%Y', errors='coerce')
        return dt
    else:
        return pd.to_datetime(x_str, errors='coerce')

for column in columns_to_convert_to_date:
    full_bank_df_hdfc[column] = full_bank_df_hdfc[column].apply(parse_date)

方法二:利用多格式解析(Pandas 1.3.0+)

pd.to_datetime的format参数支持传入格式列表,会按顺序尝试解析,同时通过掩码过滤字符串类型的行,避免破坏已有的datetime值:

import pandas as pd

columns_to_convert_to_date = ['Date','Value Dt']

for column in columns_to_convert_to_date:
    # 仅对字符串类型的行应用多格式解析
    str_mask = full_bank_df_hdfc[column].apply(lambda x: isinstance(x, str))
    full_bank_df_hdfc.loc[str_mask, column] = pd.to_datetime(
        full_bank_df_hdfc.loc[str_mask, column],
        format=['%d/%m/%Y', '%m/%d/%Y'],
        errors='coerce'
    )
    # 对非字符串非datetime的类型尝试自动解析
    other_mask = ~str_mask & ~full_bank_df_hdfc[column].apply(lambda x: isinstance(x, pd.Timestamp))
    full_bank_df_hdfc.loc[other_mask, column] = pd.to_datetime(
        full_bank_df_hdfc.loc[other_mask, column],
        errors='coerce'
    )

补充说明:方法二更简洁,适用于Pandas版本≥1.3.0的环境,会优先使用%d/%m/%Y解析,失败时自动尝试%m/%d/%Y,无需额外的正则判断。

内容的提问来源于stack exchange,提问作者Amirul Islam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:27:53