如何在 Pandas 中显示正确的日期世纪?

Posted

技术标签:

【中文标题】如何在 Pandas 中显示正确的日期世纪?【英文标题】:How to display the correct date century in Pandas? 【发布时间】:2019-09-08 10:08:01 【问题描述】:

我的某一列中有以下数据:

df['DOB']

0    01-01-84
1    31-07-85
2    24-08-85
3    30-12-93
4    09-12-77
5    08-09-90
6    01-06-88
7    04-10-89
8    15-11-91
9    01-06-68
Name: DOB, dtype: object

我想将其转换为数据类型列。 我尝试了以下操作:

print(pd.to_datetime(df1['Date.of.Birth']))
0   1984-01-01
1   1985-07-31
2   1985-08-24
3   1993-12-30
4   1977-09-12
5   1990-08-09
6   1988-01-06
7   1989-04-10
8   1991-11-15
9   2068-01-06
Name: DOB, dtype: datetime64[ns]

我怎样才能得到日期为 1968-01-06 而不是 2068-01-06?

【问题讨论】:

【参考方案1】:

在这种特定的情况下,我会使用这个:

pd.to_datetime(df['DOB'].str[:-2] + '19' + df['DOB'].str[-2:])

请注意,如果您在 1999 年之后有 DOB,这将中断!

输出:

0   1984-01-01
1   1985-07-31
2   1985-08-24
3   1993-12-30
4   1977-09-12
5   1990-08-09
6   1988-01-06
7   1989-04-10
8   1991-11-15
9   1968-01-06
dtype: datetime64[ns]

【讨论】:

获取未定义的错误系列。希望这是一个错字,必须使用列名。 @Madan 是的,我想更改答案以适应问题,但忘记修改第二个参考。固定。 @jezrael 是的,将编辑问题以明确说明 谢谢@jezrael。我不会在我的文件中获得年份 > 1999 的日期。【参考方案2】:

您可以先转换为日期时间,如果年份大于或等于 2020,则减去 100DateOffset 创建的年份:

df['DOB'] = pd.to_datetime(df['DOB'], format='%d-%m-%y')
df.loc[df['DOB'].dt.year >= 2020, 'DOB'] -= pd.DateOffset(years=100)
#same like
#mask = df['DOB'].dt.year >= 2020
#df.loc[mask, 'DOB'] = df.loc[mask, 'DOB'] - pd.DateOffset(years=100)
print (df)
         DOB
0 1984-01-01
1 1985-07-31
2 1985-08-24
3 1993-12-30
4 1977-12-09
5 1990-09-08
6 1988-06-01
7 1989-10-04
8 1991-11-15
9 1968-06-01

或者您可以通过Series.str.replace1920 添加到年份,并通过numpy.where 设置值。

注意:解决方案也适用于 00 多年 2000,直至 2020

s1 = df['DOB'].str.replace(r'-(\d+)$', r'-19\1')
s2 = df['DOB'].str.replace(r'-(\d+)$', r'-20\1')
mask = df['DOB'].str[-2:].astype(int) <= 20
df['DOB'] = pd.to_datetime(np.where(mask, s2, s1))

print (df)
         DOB
0 1984-01-01
1 1985-07-31
2 1985-08-24
3 1993-12-30
4 1977-09-12
5 1990-08-09
6 1988-01-06
7 1989-04-10
8 1991-11-15
9 1968-01-06

如果所有年份都低于2000

s1 = df['DOB'].str.replace(r'-(\d+)$', r'-19\1')
df['DOB'] = pd.to_datetime(s1, format='%d-%m-%Y')
print (df)
         DOB
0 1984-01-01
1 1985-07-31
2 1985-08-24
3 1993-12-30
4 1977-12-09
5 1990-09-08
6 1988-06-01
7 1989-10-04
8 1991-11-15
9 1968-06-01

【讨论】:

能否解释一下这一行:df.loc[df['DOB'].dt.year >= 2020, 'DOB'] -= pd.DateOffset(years=100) @Madan - 首先将值转换为日期时间,然后如果某些年份高于 2020,则使用 dateoffset 减去 100 年【参考方案3】:

另一种解决方案是将 DOB 视为一个日期,仅当它在未来(即“现在”之后)时才将其返回到上一个世纪。示例:

from datetime import datetime, date

df=pd.DataFrame.from_dict('DOB':['01-06-68','01-06-08'])
df['DOB'] = df['DOB'].apply(lambda x: datetime.strptime(x,'%d-%m-%y'))
df['DOB'] = df['DOB'].apply(lambda x: x if x<datetime.now() else date(x.year-100,x.month,x.day))

【讨论】:

【参考方案4】:

一般情况下(在不确定的情况下),最好明确指定年份:

pd.to_datetime(data['Date.of.Birth'].apply(lambda x: '-'.join(x.split('-')[:-1] + ['19' + x.split('-')[2]])))

我使用以下数据框运行它:

    0   1
0   0   01-01-84
1   1   31-07-85
2   2   24-08-85
3   3   30-12-93
4   4   09-12-77
5   5   08-09-90
6   6   01-06-88
7   7   04-10-89
8   8   15-11-91
9   9   01-06-68


pd.to_datetime(data[1].apply(lambda x: '-'.join(x.split('-')[:-1] + ['19' + x.split('-')[2]])))


0   1984-01-01
1   1985-07-31
2   1985-08-24
3   1993-12-30
4   1977-09-12
5   1990-08-09
6   1988-01-06
7   1989-04-10
8   1991-11-15
9   1968-01-06
Name: 1, dtype: datetime64[ns]

【讨论】:

【参考方案5】:

如果只有1920作为开头,你可以使用下面的代码,比如:

df['DOB'] = pd.to_datetime(df['DOB'].str.replace('20([^20]*)$', '19'))

如果其他地方没有20s:

df['DOB'] = pd.to_datetime(df['DOB'].str.replace('20', '19'))

现在:

print(df['DOB'])

是:

0   1984-01-01
1   1985-07-31
2   1985-08-24
3   1993-12-30
4   1977-09-12
5   1990-08-09
6   1988-01-06
7   1989-04-10
8   1991-11-15
9   1968-01-06
dtype: datetime64[ns]

【讨论】:

以上是关于如何在 Pandas 中显示正确的日期世纪?的主要内容,如果未能解决你的问题,请参考以下文章

如何在数据框中为 Pandas 日期时间对象正确设置 Datetimeindex?

如何在 Pandas 中正确旋转或重塑时间序列数据框?

Pandas日期数据处理:如何按日期筛选显示及统计数据

Pandas - 按字段分组并使用显示该字段数量的列

为 pandas.read_csv 指定正确的 dtypes 以获取日期时间和布尔值

如何自定义 Pandas 日期时间戳@ x 轴