我遇到的事情几乎肯定是我的一个愚蠢的错误,但我似乎无法弄清楚发生了什么。
基本上,我将一系列日期作为"%d-%b-%y"
格式的字符串,例如26-Sep-05
。当我将它们转换为日期时,这一年有时是正确的,但有时它不是。
例如:
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
条目。这里发生了什么?
答案 0 :(得分:10)
这似乎是Python库日期时间的行为,我做了一个测试,看看截止点是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)
两位数年份歧义
所以似乎%y年低于69的任何东西将归因于2000年的一个世纪,而69岁以上的东西将被归结为1900
%y
两位数字只能从00
变为99
,如果我们开始跨越几个世纪,这将是不明确的。
如果没有重叠,您可以手动处理它并注释世纪(消除歧义)
我建议您手动处理数据并指定世纪,例如您可以决定数据中年份在17到68之间的任何内容都归因于1917 - 1968年(而不是2017年 - 2068年)。
如果您有重叠,则无法处理年份信息不足,除非例如你有一些有序数据和参考
如果你有重叠,例如你有2016年和1916年的数据,两者都记录为'16',这是不明确的,没有足够的信息来解析这个,除非数据是按日期排序的,在这种情况下你可以使用启发式来切换世纪解析它。
答案 1 :(得分:4)
对于那些寻找快速而脏的代码片段来修复这些案例的人来说,这对我有用:
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)
您可能需要根据数据中最早的日期将阈值日期调整到接近现在。
答案 2 :(得分:3)
2000年(Y2K)问题: Python依赖于平台的C库, 因为所有日期和日期都没有2000年的问题 时间在内部表示为自纪元以来的秒数。功能 当给定%y格式代码时,strptime()可以解析2位数年份。什么时候 解析2位数年份,根据POSIX转换它们 和ISO C标准:值 69-99 映射到 1969-1999 和值 0-68 映射到 2000-2068 。
答案 3 :(得分:1)
您可以编写一个简单的函数来更正此错误年份的解析,如下所述:
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)
希望这会有所帮助。
答案 4 :(得分:1)
另一个快速解决问题的方法:-
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)
输出如下,这里我已使用 pd.to_datetime
从对象将输出转换为熊猫日期时间格式 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
如其他一些答案所述,如果两个世纪的日期之间没有重叠,则效果最好。