How can I calculate the age of a person (based off the dob column) and add a column to the dataframe with the new value?
dataframe looks like the following:
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='\s{2,}')
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)
yields
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
column are currently strings. First,
convert them to Timestamps
using pd.to_datetime
.'%m%d%y'
converts the last two digits to years, but
unfortunately assumes 52
means 2052. Since that's probably not
Heather Noel's birthyear, let's subtract 100 years from dob
whenever the dob
is greater than now
. You may want to subtract a few years to now
in the condition df['dob'] < now
since it may be slightly more likely to have a 101 year old worker than a 1 year old worker...dob
from now
to obtain timedelta64[ns]. To
convert that to years, use astype('<m8[Y]')
or astype('timedelta64[Y]')
.Use this one liner when you are trying to find the age from date of birth column with current year
import pandas as pd
df["dob"] = pd.to_datetime(data["dob"])
df["age"] = df["dob"].apply(lambda x : (pd.datetime.now().year - x.year))
# 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')
If you want only the year portion of the age, use @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
Another option is to subtract the year portion and account for the month difference using
(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
If you want the (almost) precise age (including the fractional portion), query total_seconds
and divide.
(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
I found easier solution:
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)
output:
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
What about the following solution:
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']]
First thought is that your years are two digit, which is a not great choice in this day and age. In any case, I'm going to assume that all years like 05
are actually 1905
. This is probably not correct(!) but coming up with the right rule is going to depend a lot on your data.
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()))