Efficient and accurate age calculation (in years, months, or weeks) in R given birth date and an arbitrary date

后端 未结 4 861
难免孤独
难免孤独 2020-11-30 06:28

I am facing the common task of calculating the age (in years, months, or weeks) given the date of birth and an arbitrary date. The thing is that quite often I have to do thi

4条回答
  •  情深已故
    2020-11-30 07:07

    Ok, so I found this function in another post:

    age <- function(from, to) {
        from_lt = as.POSIXlt(from)
        to_lt = as.POSIXlt(to)
    
        age = to_lt$year - from_lt$year
    
        ifelse(to_lt$mon < from_lt$mon |
                   (to_lt$mon == from_lt$mon & to_lt$mday < from_lt$mday),
               age - 1, age)
    }
    

    It was posted by @Jim saying "The following function takes a vectors of Date objects and calculates the ages, correctly accounting for leap years. Seems to be a simpler solution than any of the other answers".

    It is indeed simpler and it does the trick I was looking for. On average, it is actually faster than the arithmetic method (about 75% faster).

    mbm <- microbenchmark(
        arithmetic = (givendate - birthdate) / 365.25,
        lubridate = interval(start = birthdate, end = givendate) /
            duration(num = 1, units = "years"),
        eeptools = age_calc(dob = birthdate, enddate = givendate, 
                            units = "years"),
        age = age(from = birthdate, to = givendate),
        times = 1000
    )
    mbm
    autoplot(mbm)
    

    enter image description here enter image description here

    And at least in my examples it does not make any mistake (and it should not in any example; it's a pretty straightforward function using ifelses).

    toy_df <- data.frame(
        birthdate = birthdate,
        givendate = givendate,
        arithmetic = as.numeric((givendate - birthdate) / 365.25),
        lubridate = interval(start = birthdate, end = givendate) /
            duration(num = 1, units = "years"),
        eeptools = age_calc(dob = birthdate, enddate = givendate,
                            units = "years"),
        age = age(from = birthdate, to = givendate)
    )
    toy_df[, 3:6] <- floor(toy_df[, 3:6])
    toy_df
    
        birthdate  givendate arithmetic lubridate eeptools age
    1  1978-12-30 2015-12-31         37        37       37  37
    2  1978-12-31 2015-12-31         36        37       37  37
    3  1979-01-01 2015-12-31         36        37       36  36
    4  1962-12-30 2015-12-31         53        53       53  53
    5  1962-12-31 2015-12-31         52        53       53  53
    6  1963-01-01 2015-12-31         52        53       52  52
    7  2000-06-16 2050-06-17         50        50       50  50
    8  2000-06-17 2050-06-17         49        50       50  50
    9  2000-06-18 2050-06-17         49        50       49  49
    10 2007-03-18 2008-03-19          1         1        1   1
    11 2007-03-19 2008-03-19          1         1        1   1
    12 2007-03-20 2008-03-19          0         1        0   0
    13 1968-02-29 2015-02-28         46        47       46  46
    14 1968-02-29 2015-03-01         47        47       47  47
    15 1968-02-29 2015-03-02         47        47       47  47
    

    I do not consider it as a complete solution because I also wanted to have age in months and weeks, and this function is specific for years. I post it here anyway because it solves the problem for the age in years. I will not accept it because:

    1. I would wait for @Jim to post it as an answer.
    2. I will wait to see if someone else come up with a complete solution (efficient, accurate and producing age in years, months or weeks as desired).

提交回复
热议问题