【问题标题】:How to detect dates and convert to datetime64 data type如何检测日期并转换为 datetime64 数据类型
【发布时间】:2019-08-23 02:57:13
【问题描述】:

我正在使用 pandas.read_csv 从 csv 读取数据。其中一列具有不同格式的日期信息(没有标准 ISO 8601 等)。我想确保 Pandas 可以检测到日期格式,而无需用户进一步输入。老实说,我不确定如何开始。我知道 Pandas 可以infer_datetime_format 但是它不能捕获所有数据变化或可能会引发错误。

我的数据集有几百万行,因此该过程可能非常耗时。我的想法是只加载前 100 行 (nrows=100),然后让函数检测日期格式。从我目前看到的数据集来看,它可能是 dd-mm-yy、dd-mm-yyyy、yyyy-mm-dd(以及 ,.- 分隔符的不同变体)、2019 年 1 月 19 日、2019 年 1 月 1 日、2019 年 1 月 1 日等. 另外我有英文(十二月)和德文(十二月)的文本。

我想过为列中的每个项目运行类似 for 循环的东西,准备不同格式的案例,可能在 try except 块中,让 Pyton 检测前 100 个条目的正确格式。 (使用日期格式构建不同的案例:https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior

这种方法是否有意义?或者你会怎么做?提前致谢!

【问题讨论】:

    标签: python pandas datetime


    【解决方案1】:

    pd.to_datetime 在您尝试推断格式时可能会慢一个数量级。对于混合格式,可以尝试解析多次:

    import pandas as pd
    from functools import reduce
                               # dd-mm-yy    dd-mm-YYYY    YYYY-mm-dd
    df = pd.DataFrame({'date': ['12-01-01', '12-01-2001', '2001-07-05',
                                'Jan 19', 'January 2019', '1 January 2019']})
    

    代码:

    formats = ['%d-%m-%y', '%d-%m-%Y', '%Y-%m-%d', '%b %y', '%B %Y', '%d %B %Y']
    reduce(lambda l,r: l.combine_first(r), 
           [pd.to_datetime(df.date, format=fmt, errors='coerce') for fmt in formats])
    
    0   2001-01-12
    1   2001-01-12
    2   2001-07-05
    3   2019-01-01
    4   2019-01-01
    5   2019-01-01
    Name: date, dtype: datetime64[ns]
    

    如果您指定dayfirst,一般pd.to_datetime 可以灵活地解析大多数这些格式。尽管这仍然比尝试使用指定格式多次解析它要慢。

    pd.to_datetime(df.date, errors='coerce', dayfirst=True)
    #0   2001-01-12
    #1   2001-01-12
    #2   2001-07-05
    #3          NaT
    #4   2019-01-01
    #5   2019-01-01
    #Name: date, dtype: datetime64[ns]
    
    df = pd.concat([df]*10000, ignore_index=True)
    %timeit reduce(lambda l,r: l.combine_first(r), [pd.to_datetime(df.date, format=fmt, errors='coerce') for fmt in formats])
    #287 ms ± 2.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    
    %timeit pd.to_datetime(df.date, errors='coerce', dayfirst=True)
    #5.79 s ± 36.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
    

    因此,即使尝试多次解析它,您仍然会获得巨大的胜利,而且您不会错过一些非标准格式。

    【讨论】:

    • 太好了,这正是我想要的。并感谢您的详尽解释。真的很有帮助!我非常喜欢使用指定格式多次解析的第一个选项。如果无法检测到格式,它将被存储为NaT,对吗?您是否知道有关性能的更多调整(我正在查看大约 1000 万行...)?
    • @pythoneer yes NaT 是 datetime64 空值。至于性能,我不确定其他任何简单的调整。这肯定会比循环遍历行更快,但日期解析确实往往较慢。
    【解决方案2】:

    您可以尝试dateparser,它支持解析多种语言的日期。

    来自他们的文档:

    >>> # parsing ambiguous date
    >>> parse('02-03-2016')  # assumes english language, uses MDY date order
    datetime.datetime(2016, 3, 2, 0, 0)
    >>> parse('le 02-03-2016')  # detects french, uses DMY date order
    datetime.datetime(2016, 3, 2, 0, 0)
    

    【讨论】:

      猜你喜欢
      • 2021-10-01
      • 1970-01-01
      • 2017-07-15
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 2021-05-22
      • 2020-12-16
      相关资源
      最近更新 更多