23

I would like to use lubridate to calculate age in years given their date of birth and today's date. Right now I have this:

library(lubridate)
today<-mdy(08312015)
dob<-mdy(09071982)
today-dob

which gives me their age in days.

Ignacio
  • 6,566
  • 8
  • 51
  • 99
  • Is dividing by 365.25 not accurate enough? – lenz Aug 31 '15 at 13:56
  • 1
    Dividing by 365.25. Or maybe use `year(today)-year(dob)`. But this just subtracts year 1 minus year 2. – phiver Aug 31 '15 at 13:57
  • Yes, but `(today-dob)/365.25` gives me `Time difference of 32.98015 days` instead of years – Ignacio Aug 31 '15 at 13:58
  • 4
    what you're seeing is really just a label. I often find it easier to change the class of the result: `as.numeric((today-dob)/365.25)`. And for a very minor increase in precision, divide by 365.2425. – Benjamin Aug 31 '15 at 14:06
  • 1
    Note that using `today - dob` is not really the lubridate way to go, but uses basic R functionality (`difftime`). See my answer for a `lubridate` approach. – Paul Hiemstra Aug 31 '15 at 14:29

4 Answers4

33

This is the lubridate approach I would take:

interval(dob, today) / years(1)

Yields the answer of 32 years.

Note that the function will complain that it cannot express the remainder of the fraction of the year. This is because year is not a fixed concept, i.e. 366 in leap years and 365 in non-leap years. You can get an answer with more detail in regard to the number of weeks and days:

interval_period = interval(dob, today)
full_year = interval_period %/% years(1)
remaining_weeks = interval_period %% years(1) %/% weeks(1)
remaining_days = interval_period %% years(1) %% weeks(1) %/% days(1)
sprintf('Your age is %d years, %d weeks and %d days', full_year, remaining_weeks, remaining_days)
# [1] "Your age is 32 years, 51 weeks and 1 days"

Note that I use %/% for division and %% as modulo to get the remaining weeks/days after subtracting the full years/weeks.

llrs
  • 3,112
  • 31
  • 60
Paul Hiemstra
  • 56,833
  • 11
  • 132
  • 142
  • 2
    Thanks, this does what I want. Note `new_interval` is deprecated, use `interval` instead – dpel Feb 26 '16 at 10:02
  • Please also note 'new_interval' is deprecated; use 'interval' instead. Deprecated in version '1.5.0'. – amonk Jun 02 '17 at 15:13
  • What's the difference between new_interval(dob, today) and dob-today and as.period(today - dob, unit = "years")? – skan Dec 20 '17 at 15:34
  • 1
    `new_interval` is deprecated since v1.5.0, now it's just `interval`. – MS Berends Oct 31 '18 at 14:44
5
as.duration(interval(dob,today)) %/% as.duration(years(1))

should do the job without errors.

Shota Shimizu
  • 81
  • 2
  • 6
  • 2
    Thank you for this code snippet, which may provide some immediate help. A proper explanation would [greatly improve](https://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) its educational value by showing why this is a good solution to the problem, and would make it more useful to future readers with similar, but not identical, questions. Please edit your answer to add explanation, and give an indication of what limitations and assumptions apply. – basvk Jul 04 '17 at 11:41
4
as.period(today - dob, unit = "years")

This will give a message that it's only an estimate because it doesn't take into account the exact starting date and end date.

misspelled
  • 306
  • 1
  • 5
1

This is an old question, but I still missing the following clean approach. (Tidyverse is only necessary for the "%>%" operator.)

library(tidyverse)
library(lubridate)

today<-mdy(08312015)
dob<-mdy(09071982)

interval(dob, today) %>%
  as.numeric('years')

# 32.98015 - you have to decide how to deal with the fraction of a year
ACNB
  • 686
  • 7
  • 16