熊猫从日期获取年龄(例如:出生日期)
Posted
技术标签:
【中文标题】熊猫从日期获取年龄(例如:出生日期)【英文标题】:Pandas get the age from a date (example: date of birth) 【发布时间】:2015-01-03 12:19:23 【问题描述】:如何计算一个人的年龄(基于 dob 列)并使用新值向数据框中添加一列?
数据框如下所示:
lname fname dob
0 DOE LAURIE 03011979
1 BOURNE JASON 06111978
2 GRINCH XMAS 12131988
3 DOE JOHN 11121986
我尝试了以下操作:
now = datetime.now()
df1['age'] = now - df1['dob']
但是,收到以下错误:
TypeError: 不支持的操作数类型 -: 'datetime.datetime' 和 'str'
【问题讨论】:
【参考方案1】:首先想到的是你的年龄是两位数,在这个时代这不是一个很好的选择。无论如何,我将假设像05
这样的所有年份实际上都是1905
。这可能不正确(!),但提出正确的规则很大程度上取决于您的数据。
from datetime import date
def age(date1, date2):
naive_yrs = date2.year - date1.year
if date1.replace(year=date2.year) > date2:
correction = -1
else:
correction = 0
return naive_yrs + correction
df1['age'] = df1['dob'].map(lambda x: age(date(int('19' + x[-2:]), int(x[:2]), int(x[2:-2])), date.today()))
【讨论】:
unutbu 的答案肯定会比我的更快,因为它使用了我懒得学习的 numpy 日期魔法。【参考方案2】:import datetime as DT
import io
import numpy as np
import pandas as pd
pd.options.mode.chained_assignment = 'warn'
content = ''' ssno lname fname pos_title ser gender dob
0 23456789 PLILEY JODY BUDG ANAL 0560 F 031871
1 987654321 NOEL HEATHER PRTG SRVCS SPECLST 1654 F 120852
2 234567891 SONJU LAURIE SUPVY CONTR SPECLST 1102 F 010999
3 345678912 MANNING CYNTHIA SOC SCNTST 0101 F 081692
4 456789123 NAUERTZ ELIZABETH OFF AUTOMATION ASST 0326 F 031387'''
df = pd.read_csv(io.StringIO(content), sep='\s2,')
df['dob'] = df['dob'].apply(':06'.format)
now = pd.Timestamp('now')
df['dob'] = pd.to_datetime(df['dob'], format='%m%d%y') # 1
df['dob'] = df['dob'].where(df['dob'] < now, df['dob'] - np.timedelta64(100, 'Y')) # 2
df['age'] = (now - df['dob']).astype('<m8[Y]') # 3
print(df)
产量
ssno lname fname pos_title ser gender \
0 23456789 PLILEY JODY BUDG ANAL 560 F
1 987654321 NOEL HEATHER PRTG SRVCS SPECLST 1654 F
2 234567891 SONJU LAURIE SUPVY CONTR SPECLST 1102 F
3 345678912 MANNING CYNTHIA SOC SCNTST 101 F
4 456789123 NAUERTZ ELIZABETH OFF AUTOMATION ASST 326 F
dob age
0 1971-03-18 00:00:00 43
1 1952-12-08 18:00:00 61
2 1999-01-09 00:00:00 15
3 1992-08-16 00:00:00 22
4 1987-03-13 00:00:00 27
-
您的
dob
列当前似乎是字符串。第一的,
使用pd.to_datetime
将它们转换为Timestamps
。
'%m%d%y'
格式将最后两位数字转换为年份,但
不幸的是,假设52
表示 2052。因为那可能不是
Heather Noel 的生日,让我们从dob
中减去 100 年
只要dob
大于now
。您可能希望在 df['dob'] < now
条件下将 now
减去几年,因为 101 岁的工人比 1 岁的工人更有可能...
你可以从now
中减去dob
得到timedelta64[ns]。到
将其转换为年,使用 astype('<m8[Y]')
或 astype('timedelta64[Y]')
。
【讨论】:
在 .py 文件中运行时,我从上面的代码中收到以下错误。这是什么意思 SettingWithCopyWarning: 试图在 DataFrame 的切片副本上设置一个值。尝试使用 .loc[row_index,col_indexer] = value 代替 df1['dob'] = pd.to_datetime(df1['dob'], format='%m%d%y') c:\users\davidl~1\ appdata\local\temp\1\tmpxt4mqz.py:37:尝试使用 .loc[row_index,col_indexer] = value 代替 df1['dob'] = df1['dob'].where(df1['dob'] 该警告不是错误,而是代码可能分配给数据副本而不是DataFrame中的原始数据的警告。请参阅 this answer 和 the docs。我认为在上述代码的上下文中这是一个误报,但我不确定你为什么会看到警告,因为当我运行上面的代码时,我没有看到任何警告。当你运行上面的代码时,你看到警告了吗? 对不起,上面的代码出现 ValueError。 当我在你发布的 CSV 数据上运行你的代码时,我得到了正确的结果,没有错误。 我没有 Python2 和 pandas 来测试这个了,但如果我没记错的话,read_table
和 read_csv
都需要 BytesIO
并且如果通过 @987654343 会引发一些错误@.【参考方案3】:
我找到了更简单的解决方案:
import pandas as pd
from datetime import datetime
from datetime import date
d = 'col0': [1, 2, 6],
'col1': [3, 8, 3],
'col2': ['17.02.1979', '11.11.1993', '01.08.1961']
df = pd.DataFrame(data=d)
def calculate_age(born):
born = datetime.strptime(born, "%d.%m.%Y").date()
today = date.today()
return today.year - born.year - ((today.month, today.day) < (born.month, born.day))
df['age'] = df['col6'].apply(calculate_age)
print(df)
输出:
col0 col1 col3 age
0 1 3 17.02.1979 39
1 2 8 11.11.1993 24
2 6 3 01.08.1961 57
【讨论】:
在这个日期不能正常工作,例如'20-03-2020'【参考方案4】:# Data setup
df
lname fname dob
0 DOE LAURIE 1979-03-01
1 BOURNE JASON 1978-06-11
2 GRINCH XMAS 1988-12-13
3 DOE JOHN 1986-11-12
# Make sure to parse all datetime columns in advance
df['dob'] = pd.to_datetime(df['dob'], errors='coerce')
如果您只想要年龄的年份部分,请使用@unutbu's solution。 . .
now = pd.to_datetime('now')
now
# Timestamp('2019-04-14 00:00:43.105892')
(now - df['dob']).astype('<m8[Y]')
0 40.0
1 40.0
2 30.0
3 32.0
Name: dob, dtype: float64
另一种选择是减去年份部分并使用
(now.year - df['dob'].dt.year) - ((now.month - df['dob'].dt.month) < 0)
0 40
1 40
2 30
3 32
Name: dob, dtype: int64
如果您想要(几乎)精确的年龄(包括小数部分),请查询 total_seconds
并除以。
(now - df['dob']).dt.total_seconds() / (60*60*24*365.25)
0 40.120446
1 40.840501
2 30.332630
3 32.418872
Name: dob, dtype: float64
【讨论】:
【参考方案5】:下面的解决方案怎么样:
import datetime as dt
import numpy as np
import pandas as pd
from dateutil.relativedelta import relativedelta
df1['age'] = [relativedelta(pd.to_datetime('now'), d).years for d in df1['dob']]
【讨论】:
【参考方案6】:当您尝试从出生日期列中查找当前年份的年龄时,请使用这一行
import pandas as pd
df["dob"] = pd.to_datetime(data["dob"])
df["age"] = df["dob"].apply(lambda x : (pd.datetime.now().year - x.year))
【讨论】:
以上是关于熊猫从日期获取年龄(例如:出生日期)的主要内容,如果未能解决你的问题,请参考以下文章