我正在使用lubridate
和dplyr
包来处理日期变量并分别创建一个新的日期变量。
library(lubridate)
library(dplyr)
让df
成为我的数据框。我有两个变量date1
和date2
。我想创建一个新变量date
,使其取值为date1
。如果缺少date1
,则会取代date2
的值。
df <- data.frame(date1 = c("24/01/2016",NA,"22/07/2016"),
date2 = c("31/01/2016","09/02/2017",NA),
stringsAsFactors=FALSE)`
以上命令给出:
date1 date2
1 24/01/2016 31/01/2016
2 <NA> 09/02/2017
3 22/07/2016 <NA>
我尝试了以下内容,我认为可以给我所需的结果。但是,新的date
变量在数字中。
df %>%
mutate_at(vars(date1,date2),dmy) %>%
mutate(date=ifelse(is.na(date1),date2,date1))
date1 date2 date
1 2016-01-24 2016-01-31 16824
2 <NA> 2017-02-09 17206
3 2016-07-22 <NA> 17004
我想:
date1 date2 date
1 2016-01-24 2016-01-31 2016-01-24
2 <NA> 2017-02-09 2017-02-09
3 2016-07-22 <NA> 2016-07-22
如何解决这个问题?
答案 0 :(得分:7)
使用dplyr::if_else
代替base::ifelse
,根据?if_else
,类型更安全,
与基础ifelse()相比,此函数更严格。它检查 真假都属于同一类型。这种严格使得 输出类型更可预测,并使其更快。
df %>%
mutate_at(vars(date1,date2),dmy) %>%
mutate(date=if_else(is.na(date1),date2,date1))
# date1 date2 date
#1 2016-01-24 2016-01-31 2016-01-24
#2 <NA> 2017-02-09 2017-02-09
#3 2016-07-22 <NA> 2016-07-22
另一种选择是使用coalesce
,如果不是date1
,则会从NA
获取值,否则从date2
获取值:
df %>%
mutate_at(vars(date1,date2),dmy) %>%
mutate(date = coalesce(date1, date2))
# date1 date2 date
#1 2016-01-24 2016-01-31 2016-01-24
#2 <NA> 2017-02-09 2017-02-09
#3 2016-07-22 <NA> 2016-07-22
如果你想保留原始代码,只需将as.Date
包裹在ifelse
左右,因为ifelse
剥离了结果类,只保留基础数据,即自1970-01-01以来的天数:
df %>%
mutate_at(vars(date1,date2),dmy) %>%
mutate(date=as.Date(ifelse(is.na(date1),date2,date1), origin = "1970-01-01"))