Рассчитать возраст в R - PullRequest
       9

Рассчитать возраст в R

12 голосов
/ 31 августа 2010

У меня есть два фрейма данных в R. В одном фрейме указан год рождения людей:

YEAR
/1931
/1924

, а затем другой столбец показывает более позднее время.

RECENT
09/08/2005
11/08/2005

То, что я хочу сделать, это вычесть годы, чтобы я мог рассчитать их возраст в количестве лет, однако я не уверен, как к этому приблизиться. Любая помощь, пожалуйста?

Ответы [ 8 ]

28 голосов
/ 22 августа 2014

Следующая функция берет векторы объектов Date и вычисляет возраст, правильно учитывая високосные годы.Кажется, это более простое решение, чем любой другой ответ.

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)
}
8 голосов
/ 01 сентября 2010

Вы можете решить это с помощью пакета lubridate.

> library(lubridate)

Я не думаю, что / 1931 - распространенный класс дат. Поэтому я предполагаю, что все записи являются символьными строками.

> RECENT <- data.frame(recent = c("09/08/2005", "11/08/2005"))
> YEAR <- data.frame(year = c("/1931", "/1924"))

Во-первых, давайте уведомим R, что последние даты являются датами. Я предполагаю, что даты указаны в порядке месяц / день / год, поэтому я использую mdy (). Если они в порядке дня / месяца / года, просто используйте dmy ().

> RECENT$recent <- mdy(RECENT$recent)
      recent
1 2005-09-08
2 2005-11-08

Теперь давайте превратим годы в числа, чтобы мы могли с ними кое-что посчитать.

> YEAR$year <- as.numeric(substr(YEAR$year, 2, 5))

Теперь просто посчитай. year () извлекает значение года из последних дат.

> year(RECENT$recent) - YEAR
  year
1   74
2   81

p.s. если ваши записи года фактически являются полными датами, вы можете получить разницу в годах с помощью

> YEAR1 <- data.frame(year = mdy("01/08/1931","01/08/1924"))
> as.period(RECENT$recent - YEAR1$year, units = "year")
[1] 74 years and 8 months   81 years and 10 months
5 голосов
/ 28 ноября 2017

Я использую пользовательскую функцию, см. Код ниже, удобный для использования в mutate и довольно гибкий (вам понадобится пакет lubridate).

Примеры

get_age("2000-01-01")
# [1] 17
get_age(lubridate::as_date("2000-01-01"))
# [1] 17
get_age("2000-01-01","2015-06-15")
# [1] 15
get_age("2000-01-01",dec = TRUE)
# [1] 17.92175
get_age(c("2000-01-01","2003-04-12"))
# [1] 17 14
get_age(c("2000-01-01","2003-04-12"),dec = TRUE)
# [1] 17.92176 14.64231

Функция

#' Get age
#' 
#' Returns age, decimal or not, from single value or vector of strings
#' or dates, compared to a reference date defaulting to now. Note that
#' default is NOT the rounded value of decimal age.
#' @param from_date vector or single value of dates or characters
#' @param to_date date when age is to be computed
#' @param dec return decimal age or not
#' @examples
#' get_age("2000-01-01")
#' get_age(lubridate::as_date("2000-01-01"))
#' get_age("2000-01-01","2015-06-15")
#' get_age("2000-01-01",dec = TRUE)
#' get_age(c("2000-01-01","2003-04-12"))
#' get_age(c("2000-01-01","2003-04-12"),dec = TRUE)
get_age <- function(from_date,to_date = lubridate::now(),dec = FALSE){
  if(is.character(from_date)) from_date <- lubridate::as_date(from_date)
  if(is.character(to_date))   to_date   <- lubridate::as_date(to_date)
  if (dec) { age <- lubridate::interval(start = from_date, end = to_date)/(lubridate::days(365)+lubridate::hours(6))
  } else   { age <- lubridate::year(lubridate::as.period(lubridate::interval(start = from_date, end = to_date)))}
  age
}
2 голосов
/ 31 августа 2010

Учитывая данные в вашем примере:

> m <- data.frame(YEAR=c("/1931", "/1924"),RECENT=c("09/08/2005","11/08/2005"))
> m
   YEAR     RECENT
1 /1931 09/08/2005
2 /1924 11/08/2005

Извлечение года с помощью функции strptime:

> strptime(m[,2], format = "%m/%d/%Y")$year - strptime(m[,1], format = "/%Y")$year
[1] 74 81
2 голосов
/ 31 августа 2010

Вы можете сделать форматирование:

as.numeric(format(as.Date("01/01/2010", format="%m/%d/%Y"), format="%Y")) - 1930

С вашими данными:

> yr <- c(1931, 1924)
> recent <- c("09/08/2005", "11/08/2005")
> as.numeric(format(as.Date(recent, format="%m/%d/%Y"), format="%Y")) - yr
[1] 74 81

Поскольку у вас есть данные в data.frame (я предполагаю, что они называются df), они будут выглядеть примерно так:

as.numeric(format(as.Date(df$recent, format="%m/%d/%Y"), format="%Y")) - df$year
1 голос
/ 03 сентября 2015

Я думаю, что это может быть немного более интуитивно понятно и не требует форматирования или удаления:

as.numeric(as.Date("2002-02-02") - as.Date("1924-08-03")) / 365

дает вывод:

77.55342

Затем вы можете использовать floor (), round () или потолок () для округления до целого числа.

1 голос
/ 31 августа 2010

Исходя из предыдущего ответа, конвертируйте столбцы в объекты даты и вычитайте. Необходимо некоторое преобразование типов между символьным и числовым:

> foo=data.frame(RECENT=c("09/08/2005","11/08/2005"),YEAR=c("/1931","/1924"))
> foo
      RECENT  YEAR
1 09/08/2005 /1931
2 11/08/2005 /1924
> foo$RECENTd = as.Date(foo$RECENT, format="%m/%d/%Y")
> foo$YEARn = as.numeric(substr(foo$YEAR,2,999))
> foo$AGE = as.numeric(format(foo$RECENTd,"%Y")) - foo$YEARn
> foo
      RECENT  YEAR    RECENTd YEARn AGE
1 09/08/2005 /1931 2005-09-08  1931  74
2 11/08/2005 /1924 2005-11-08  1924  81

Примечание. Я предположил, что у вас есть этот слеш в столбце года.

Кроме того, совет, когда вы задаете вопросы о датах, должен включать день после двенадцатого, чтобы мы знали, являетесь ли вы человеком месяца / дня / года или человеком дня / месяца / года.

0 голосов
/ 23 октября 2017

Действительно надежный способ, который также поддерживает векторы с использованием пакета lubridate:

age <- function(date.birth, date.ref = Sys.Date()) {
  if (length(date.birth) > 1 & length(date.ref) == 1) {
    date.ref <- rep(date.ref, length(date.birth))
  }

  date.birth.monthdays <- paste0(month(date.birth), day(date.birth)) %>% as.integer()
  date.ref.monthdays <- paste0(month(date.ref), day(date.ref)) %>% as.integer()

  age.calc <- 0

  for (i in 1:length(date.birth)) {
    if (date.birth.monthdays[i] <= date.ref.monthdays[i]) {
      # didn't had birthday
      age.calc[i] <- year(date.ref[i]) - year(date.birth[i])
    } else {
      age.calc[i] <- year(date.ref[i]) - year(date.birth[i]) - 1
    }
  }
  age.calc
}

Это также относится к високосным годам. Я просто проверяю, был ли у кого-то день рождения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...