如何防止 pandas.to_datetime() 函数将 0001-01-01 转换为 2001-01-01

Posted

技术标签:

【中文标题】如何防止 pandas.to_datetime() 函数将 0001-01-01 转换为 2001-01-01【英文标题】:How do I prevent pandas.to_datetime() function from converting 0001-01-01 to 2001-01-01 【发布时间】:2016-05-25 07:42:14 【问题描述】:

我对使用 pymssql 查询并读入 Pandas 数据框的数据库具有只读访问权限。其中一个变量包含日期,其中一些存储为 0001 年 1 月 1 日午夜(即 0001-01-01 00:00:00.0000000)。我不知道为什么要包含这些日期——据我所知,SQL Server 不会将它们识别为有效日期,它们可能是由于某些默认数据输入造成的。尽管如此,这就是我必须解决的问题。这可以重新创建为数据框,如下所示:

import numpy as np
import pandas as pd

tempDF = pd.DataFrame( 'id': [0,1,2,3,4],
                        'date': ['0001-01-01 00:00:00.0000000',
                                 '2015-05-22 00:00:00.0000000',
                                 '0001-01-01 00:00:00.0000000',
                                 '2015-05-06 00:00:00.0000000',
                                 '2015-05-03 00:00:00.0000000'])

数据框如下所示:

print(tempDF)
                          date  id
0  0001-01-01 00:00:00.0000000   0
1  2015-05-22 00:00:00.0000000   1
2  0001-01-01 00:00:00.0000000   2
3  2015-05-06 00:00:00.0000000   3
4  2015-05-03 00:00:00.0000000   4

...具有以下数据类型:

print(tempDF.dtypes)

date    object
id       int64
dtype: object
print(tempDF.dtypes)

但是,我通常使用以下方法将数据框中的日期字段转换为日期时间格式:

tempDF['date'] = pd.to_datetime(tempDF['date'])

但是,我偶然发现 0001-01-01 日期已转换为 2001-01-01。

print(tempDF)

        date  id
0 2001-01-01   0
1 2015-05-22   1
2 2001-01-01   2
3 2015-05-06   3
4 2015-05-03   4

我意识到原始数据库中的日期不正确,因为 SQL Server 没有将 0001-01-01 视为有效日期。但至少在 0001-01-01 格式中,这样的缺失数据在我的 Pandas 数据框中很容易识别。但是,当 pandas.to_datetime() 将这些日期更改为处于可行范围内时,很容易错过此类异常值。

如何确保 pd.to_datetime 不会错误地解释异常日期?

【问题讨论】:

【参考方案1】:

如果您提供format,则无法识别这些日期:

In [92]: pd.to_datetime(tempDF['date'], format="%Y-%m-%d %H:%M:%S.%f", errors='coerce')
Out[92]:
0          NaT
1   2015-05-22
2          NaT
3   2015-05-06
4   2015-05-03
Name: date, dtype: datetime64[ns]

默认情况下会出错,但通过传递errors='coerce',它们会转换为 NaT 值(coerce=True 用于旧版 pandas)。

pandas 将这些“0001-01-01”日期转换为“2001-01-01”而不提供format 的原因是因为这是dateutil 的行为:

In [32]: import dateutil

In [33]: dateutil.parser.parse("0001-01-01")
Out[33]: datetime.datetime(2001, 1, 1, 0, 0)

【讨论】:

完美。感谢您的解决方案和额外的推理。

以上是关于如何防止 pandas.to_datetime() 函数将 0001-01-01 转换为 2001-01-01的主要内容,如果未能解决你的问题,请参考以下文章

007.pandas.to_datetime()

007.pandas.to_datetime()

使用具有正确语法的 pandas to_datetime() 方法,无法识别的值类型:str?

Python Pandas:当日期小于 13 时,pandas.to_datetime() 正在切换日期和月份

使用 pandas.to_datetime 转换时指定日期格式

pandas to_datetime()