gsub 用于处理数据中 r 中的日期
gsub for dealing with dates in r in data
我正在处理非常大的大学生数据集,其中日期的形式为
%d/%m/%y
我需要计算年龄。
我的数据从数据库中提取时看起来像这样:
data <- data.table(DOB=c("12/12/01", "8/05/80", "2/11/99"),
started =c("5/10/10", "4/01/12", "27/08/11"))
问题是计算年龄时没有指定整年。
我试过将年份更改为数字:
data$DOB<-as.Date(data$DOB, "%d/%m/%y")
data$start<-as.Date(data$start, "%d/%m/%y")
data$DOB<-as.numeric(format(data$DOB,"%Y"))
data$start<-as.numeric(format(data$start,"%Y"))
data$age<-data$start-data$dob
显然这不起作用,因为我需要添加 20 和 19。
有没有一种方法可以使用 gsub 在所有 dob 小于或等于 15 的前面放置一个“20”,在所有 dob 大于 15 的前面放置一个“19”。
我认为我的数据集中没有任何 85 岁的人。
data<-data.frame(DOB=c('12/12/01', '8/05/80', '2/11/99'),
started =c('5/10/10', '4/01/12', '27/08/11'))
library(stringr)
toFourYear <- function(x){
x <- str_split(x, "/")
x <- lapply(x,
function(t){
t[3] <- if (as.numeric(t[3]) < 15) paste0("20", t[3]) else paste0("19", t[3])
t
})
x <- vapply(x, paste0, character(1), collapse = "/")
x
}
data$DOB <- toFourYear(data$DOB)
data$started <- toFourYear(data$started)
这对你有用吗?
以及使用基础 R 的 substr
和 nchar
函数的类似方法。
library(data.table)
dt <-data.table(DOB=c("12/12/01", "8/05/80", "2/11/99"),
started =c("5/10/10", "4/01/12", "27/08/11"))
dt
# DOB started
# 1: 12/12/01 5/10/10
# 2: 8/05/80 4/01/12
# 3: 2/11/99 27/08/11
WholeYear = function(x){
v1 = substr(x, 1, nchar(x)-2)
v2 = substr(x, nchar(x)-1, nchar(x))
ifelse(as.numeric(v2) <= 15, paste0(v1,"20",v2), paste0(v1,"19",v2))
}
dt$DOB = sapply(dt$DOB, WholeYear)
dt$started = sapply(dt$started, WholeYear)
dt
# DOB started
# 1: 12/12/2001 5/10/2010
# 2: 8/05/1980 4/01/2012
# 3: 2/11/1999 27/08/2011
或者,避免使用额外的 pkg 并进行矢量化日期与字符串操作:
dat <- data.table(DOB=c("12/12/01", "8/05/80", "2/11/99"),
started =c("5/10/10", "4/01/12", "27/08/11"))
#' Convert a vector of date strings (with 2-digit years) into dates, taking
#' into account a "cutoff" year to demark when a date belongs in one
#' century or another.
#'
#' @param d vector of character strings
#' @param format date string format for the 'd'
#' @param cutoff_year 2-digit year where dates in 'd' will be considered
#' part of one century or another
#' @param output_format date format for the output character vector
as_date_with_cutoff <- function(d, format="%d/%m/%y",
cutoff_year=15, output_format="%d/%m/%Y") {
d <- as.Date(d, format)
d <- as.Date(ifelse(d < sprintf("19%s-12-31", cutoff_year),
format(d, "19%y-%m-%d"), format(d)))
as.character(format(d, output_format))
}
# orig
dat
## DOB started
## 1: 12/12/01 5/10/10
## 2: 8/05/80 4/01/12
## 3: 2/11/99 27/08/11
dat$DOB <- as_date_with_cutoff(dat$DOB)
dat$started <- as_date_with_cutoff(dat$started)
# converted
dat
## DOB started
## 1: 12/12/2001 05/10/2010
## 2: 08/05/1980 04/01/2012
## 3: 02/11/1999 27/08/2011
我正在处理非常大的大学生数据集,其中日期的形式为
%d/%m/%y
我需要计算年龄。
我的数据从数据库中提取时看起来像这样:
data <- data.table(DOB=c("12/12/01", "8/05/80", "2/11/99"),
started =c("5/10/10", "4/01/12", "27/08/11"))
问题是计算年龄时没有指定整年。
我试过将年份更改为数字:
data$DOB<-as.Date(data$DOB, "%d/%m/%y")
data$start<-as.Date(data$start, "%d/%m/%y")
data$DOB<-as.numeric(format(data$DOB,"%Y"))
data$start<-as.numeric(format(data$start,"%Y"))
data$age<-data$start-data$dob
显然这不起作用,因为我需要添加 20 和 19。
有没有一种方法可以使用 gsub 在所有 dob 小于或等于 15 的前面放置一个“20”,在所有 dob 大于 15 的前面放置一个“19”。
我认为我的数据集中没有任何 85 岁的人。
data<-data.frame(DOB=c('12/12/01', '8/05/80', '2/11/99'),
started =c('5/10/10', '4/01/12', '27/08/11'))
library(stringr)
toFourYear <- function(x){
x <- str_split(x, "/")
x <- lapply(x,
function(t){
t[3] <- if (as.numeric(t[3]) < 15) paste0("20", t[3]) else paste0("19", t[3])
t
})
x <- vapply(x, paste0, character(1), collapse = "/")
x
}
data$DOB <- toFourYear(data$DOB)
data$started <- toFourYear(data$started)
这对你有用吗?
以及使用基础 R 的 substr
和 nchar
函数的类似方法。
library(data.table)
dt <-data.table(DOB=c("12/12/01", "8/05/80", "2/11/99"),
started =c("5/10/10", "4/01/12", "27/08/11"))
dt
# DOB started
# 1: 12/12/01 5/10/10
# 2: 8/05/80 4/01/12
# 3: 2/11/99 27/08/11
WholeYear = function(x){
v1 = substr(x, 1, nchar(x)-2)
v2 = substr(x, nchar(x)-1, nchar(x))
ifelse(as.numeric(v2) <= 15, paste0(v1,"20",v2), paste0(v1,"19",v2))
}
dt$DOB = sapply(dt$DOB, WholeYear)
dt$started = sapply(dt$started, WholeYear)
dt
# DOB started
# 1: 12/12/2001 5/10/2010
# 2: 8/05/1980 4/01/2012
# 3: 2/11/1999 27/08/2011
或者,避免使用额外的 pkg 并进行矢量化日期与字符串操作:
dat <- data.table(DOB=c("12/12/01", "8/05/80", "2/11/99"),
started =c("5/10/10", "4/01/12", "27/08/11"))
#' Convert a vector of date strings (with 2-digit years) into dates, taking
#' into account a "cutoff" year to demark when a date belongs in one
#' century or another.
#'
#' @param d vector of character strings
#' @param format date string format for the 'd'
#' @param cutoff_year 2-digit year where dates in 'd' will be considered
#' part of one century or another
#' @param output_format date format for the output character vector
as_date_with_cutoff <- function(d, format="%d/%m/%y",
cutoff_year=15, output_format="%d/%m/%Y") {
d <- as.Date(d, format)
d <- as.Date(ifelse(d < sprintf("19%s-12-31", cutoff_year),
format(d, "19%y-%m-%d"), format(d)))
as.character(format(d, output_format))
}
# orig
dat
## DOB started
## 1: 12/12/01 5/10/10
## 2: 8/05/80 4/01/12
## 3: 2/11/99 27/08/11
dat$DOB <- as_date_with_cutoff(dat$DOB)
dat$started <- as_date_with_cutoff(dat$started)
# converted
dat
## DOB started
## 1: 12/12/2001 05/10/2010
## 2: 08/05/1980 04/01/2012
## 3: 02/11/1999 27/08/2011