如何检测日期并将其转换为datetime64数据类型

时间:2019-04-01 21:12:57

标签: python pandas datetime

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

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

我考虑过要为该列中的每个项目运行诸如for循环之类的东西,准备具有不同格式的案例,也许在try except块中,并让Pyton为前100个检测正确的格式条目。 (使用https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior中的日期格式构建不同的案例)

这种方法甚至有意义吗?或者你会怎么做?预先感谢!

2 个答案:

答案 0 :(得分:0)

您可以尝试使用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)

答案 1 :(得分:0)

当您让

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]

通常,如果您指定pd.to_datetimedayfirst可以灵活地解析大多数格式。尽管这仍然比尝试使用指定格式解析几次要慢。

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)

因此,即使尝试对其进行多次解析,您仍然会赢得巨大的胜利,而且您不会错过某些非标准格式。