我在R中有两个数据框.一个框架有一个人的出生年份:
YEAR
/1931
/1924
Run Code Online (Sandbox Code Playgroud)
然后另一列显示更近的时间.
RECENT
09/08/2005
11/08/2005
Run Code Online (Sandbox Code Playgroud)
我想做的是减去这些年份,以便我可以计算他们的年龄,但是我不知道如何处理这个问题.有什么帮助吗?
Jim*_*Jim 32
以下函数采用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)
}
Run Code Online (Sandbox Code Playgroud)
小智 8
您可以使用lubridate包解决这个问题.
> library(lubridate)
Run Code Online (Sandbox Code Playgroud)
我不认为/ 1931是一个普通的日期类.所以我假设所有条目都是字符串.
> RECENT <- data.frame(recent = c("09/08/2005", "11/08/2005"))
> YEAR <- data.frame(year = c("/1931", "/1924"))
Run Code Online (Sandbox Code Playgroud)
首先,让我们通知R最近的日期是日期.我假设日期是月/日/年订单,所以我使用mdy().如果他们在日/月/年订单中使用dmy().
> RECENT$recent <- mdy(RECENT$recent)
recent
1 2005-09-08
2 2005-11-08
Run Code Online (Sandbox Code Playgroud)
现在,让我们把年份变成数字,这样我们就可以用它们做一些数学运算.
> YEAR$year <- as.numeric(substr(YEAR$year, 2, 5))
Run Code Online (Sandbox Code Playgroud)
现在就算数学吧.year()提取最近日期的年份值.
> year(RECENT$recent) - YEAR
year
1 74
2 81
Run Code Online (Sandbox Code Playgroud)
如果您的年份条目实际上是完整日期,您可以获得与年份不同的年份
> 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
Run Code Online (Sandbox Code Playgroud)
我使用自定义函数,请参见下面的代码,便于在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
Run Code Online (Sandbox Code Playgroud)
功能
#' 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
}
Run Code Online (Sandbox Code Playgroud)
您可以进行一些格式化:
as.numeric(format(as.Date("01/01/2010", format="%m/%d/%Y"), format="%Y")) - 1930
Run Code Online (Sandbox Code Playgroud)
用你的数据:
> 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
Run Code Online (Sandbox Code Playgroud)
由于您的数据位于 data.frame 中(我假设它被称为df),因此它会更像这样:
as.numeric(format(as.Date(df$recent, format="%m/%d/%Y"), format="%Y")) - df$year
Run Code Online (Sandbox Code Playgroud)