Python 熊猫的日期时间分析错误的年份

Python 熊猫的日期时间分析错误的年份,python,datetime,pandas,Python,Datetime,Pandas,我遇到了一个几乎可以肯定是我犯的愚蠢错误,但我似乎不知道发生了什么 基本上,我有一系列日期作为字符串,格式为%d-%b-%y”,例如26-Sep-05。当我将它们转换为datetime时,年份有时是正确的,但有时不是 例如: dates = ['26-Sep-05', '26-Sep-05', '15-Jun-70', '5-Dec-94', '9-Jan-61', '8-Feb-55'] pd.to_datetime(dates, format="%d-%b-%y") DatetimeInd

我遇到了一个几乎可以肯定是我犯的愚蠢错误,但我似乎不知道发生了什么

基本上,我有一系列日期作为字符串,格式为
%d-%b-%y”
,例如
26-Sep-05
。当我将它们转换为datetime时,年份有时是正确的,但有时不是

例如:

dates = ['26-Sep-05', '26-Sep-05', '15-Jun-70', '5-Dec-94', '9-Jan-61', '8-Feb-55']

pd.to_datetime(dates, format="%d-%b-%y")
DatetimeIndex(['2005-09-26', '2005-09-26', '1970-06-15', '1994-12-05',
               '2061-01-09', '2055-02-08'],
              dtype='datetime64[ns]', freq=None)

最后两个条目是错误的,这两个条目被返回为2061和2055年。但是对于
15-Jun-70
条目来说,这很好。这是怎么回事?

这似乎是Python库datetime的行为,我做了一个测试,看看截止点是68-69:

datetime.datetime.strptime('31-Dec-68', '%d-%b-%y').date()
>>> datetime.date(2068, 12, 31)

datetime.datetime.strptime('1-Jan-69', '%d-%b-%y').date()
>>> datetime.date(1969, 1, 1)
两位数年份歧义

因此,似乎任何年百分比低于69的都将被认为是2000年的一个世纪,而年百分比高于69的则被认为是1900年

%y
两位数字只能从
00
变为
99
,如果我们开始跨越世纪,这将是不明确的

如果没有重叠,您可以手动处理并注释世纪(消除歧义)

我建议您手动处理您的数据并指定世纪,例如,您可以确定您的数据中任何年份介于17和68之间的都属于1917-1968年(而不是2017-2068年)

如果存在重叠,则无法处理年份信息不足的情况,除非您有一些有序数据和参考

    pddt
0   2005-09-26
1   2005-09-26
2   1970-06-15
3   1994-12-05
4   1961-01-09
5   1955-02-08
如果您有重叠,例如,您有2016年和1916年的数据,并且都记录为“16”,这是不明确的,并且没有足够的信息来解析这一点,除非数据按日期排序,在这种情况下,您可以在解析时使用启发式切换世纪。

2000年(Y2K)问题:Python依赖于平台的C库, 它通常没有2000年发行的,因为所有日期和 时间在内部表示为自纪元起的秒。作用 当给定%y格式代码时,strtime()可以分析两位数的年份。什么时候 解析两位数的年份,并根据POSIX进行转换 和ISO C标准:值69-99映射到1969-1999,值 0-68映射到2000-2068


对于任何想要快速而肮脏的代码片段来修复这些情况的人来说,这对我很有用:

from datetime import timedelta, date
col = 'date'
df[col] = pd.to_datetime(df[col])
future = df[col] > date(year=2050,month=1,day=1)
df.loc[future, col] -= timedelta(days=365.25*100)

根据数据中最早的日期,您可能需要将阈值日期调整得更接近当前日期。

您可以编写一个简单的函数来纠正对错误年份的解析,如下所述:

import datetime

def fix_date(x):

    if x.year > 1989:

        year = x.year - 100

    else:

        year = x.year

    return datetime.date(year,x.month,x.day)


df['date_column'] = data['date_column'].apply(fix_date)

希望这有助于..

此问题的另一个快速解决方案:-

import pandas as pd
import numpy as np
dates = pd.DataFrame(['26-Sep-05', '26-Sep-05', '15-Jun-70', '5-Dec-94', '9-Jan-61', '8-Feb-55'])

for i in dates:
    tempyear=pd.to_numeric(dates[i].str[-2:])
    dates["temp_year"]=np.where((tempyear>=44)&(tempyear<=99),tempyear+1900,tempyear+2000).astype(str)
    dates["temp_month"]=dates[i].str[:-2]
    dates["temp_flyr"]=dates["temp_month"]+dates["temp_year"]
    dates["pddt"]=pd.to_datetime(dates.temp_flyr.str.upper(), format='%d-%b-%Y', yearfirst=False)
    tempdrops=["temp_year","temp_month","temp_flyr",i]
    dates.drop(tempdrops, axis=1, inplace=True)

正如在其他一些答案中提到的,如果两个世纪的日期之间没有重叠,那么这种方法最有效。

您的日期不明确,因此Python不知道是1965年还是2065年。你确定你将来不会有任何约会吗?70和65一样模棱两可——问题部分在于为什么在一个场景中做出一个选择而不是另一个——这就是我所想的。你有没有洞察到为什么会出现这种情况?我在想这可能与Unix时间开始的时间有关,但既然69可以工作,那就不是问题了。