我在R中有两个数据框。一个框架有一个人的出生年份:
YEAR
/1931
/1924
然后另一列显示更近的时间。
RECENT
09/08/2005
11/08/2005
我想要做的是减去年份,以便我可以计算他们的年龄,但是我不知道如何处理这个问题。有什么帮助吗?
答案 0 :(得分:28)
以下函数采用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)
}
答案 1 :(得分:8)
您可以使用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
答案 2 :(得分:5)
我使用自定义函数,请参阅下面的代码,方便在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
}
答案 3 :(得分:2)
你可以做一些格式化:
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
答案 4 :(得分:2)
鉴于您的示例中的数据:
> 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
答案 5 :(得分:1)
根据上一个答案,将列转换为日期对象并减去。必须在字符和数字之间进行一些类型转换:
> 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
注意我假设你的年份列中有斜杠。
此外,在询问有关日期的问题时,请提示是否包括超过第12天的日期,以便我们知道您是月/日/年人还是日/月/年人。
答案 6 :(得分:1)
我认为这可能更直观,不需要格式化或剥离:
as.numeric(as.Date("2002-02-02") - as.Date("1924-08-03")) / 365
给出输出:
77.55342
然后你可以使用floor(),round()或ceiling()来舍入到整数。
答案 7 :(得分:0)
使用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
}
这也是闰年的原因。我只是检查某人是否已过生日。