首页 > 解决方案 > 处理日期不正确的数据,例如 2 月 30 日

问题描述

在尝试处理大量以 CSV 格式提供的银行账户对账单时,我意识到有些日期不正确(2 月 30 日,这是不可能的)。

所以这个片段失败 [1] 告诉我某些日期不正确:

        df_from_csv = pd.read_csv(   csv_filename
                                   , encoding='cp1252'
                                   , sep=";"
                                   , thousands='.', decimal=","
                                   , dayfirst=True
                                   , parse_dates=['Buchungstag', 'Wertstellung']  
                                 )

我当然可以预处理这些 CSV 文件,并将 2 月 30 日替换为 2 月 28 日(或当年 2 月结束的任何时间)。

但是有没有办法在熊猫中做到这一点,同时导入?像“如果此列失败,请将其设置为 X”?

样本行

775945;28.02.2018;30.02.2018;;901;"Zinsen"

如您所见,日期30.02.2018不正确,因为没有 2 月 30 日。但这似乎是德国的一个已知问题。见[2]。


[1] 这是错误消息:

ValueError: day is out of range for month

[2] https://de.wikipedia.org/wiki/30._Februar

标签: pythonpandas

解决方案


这是我解决它的方法:

我添加了一个自定义日期解析器:

import calendar

def mydateparser(dat_str):
    """Given a date like `30.02.2020` create a correct date `28.02.2020`"""
    if dat_str.startswith("30.02"):
        (d, m, y) = [int(el) for el in dat_str.split(".")]
        # This here will get the first and last days in a given year/month:
        (first, last) = calendar.monthrange(y, m)
        # Use the correct last day (`last`) in creating a new datestring:
        dat_str = f"{last:02d}.{m:02d}.{y}"
    return pd.datetime.strptime(dat_str, "%d.%m.%Y")

# and used it in `read_csv`
for csv_filename in glob.glob(f"{path}/*.csv"):
    # read csv into DataFrame
    df_from_csv = pd.read_csv(csv_filename,
                              encoding='cp1252',
                              sep=";",
                              thousands='.', decimal=",",
                              dayfirst=True,
                              parse_dates=['Buchungstag', 'Wertstellung'],
                              date_parser=mydateparser
                             )

这使我可以修复那些不正确的“30.02.XX”日期,并允许 pandas 将这两个日期列 ( ['Buchungstag', 'Wertstellung']) 转换为日期,而不是对象。


推荐阅读