有条件地在dplyr链中更改日期的年份部分

时间:2018-03-24 05:38:18

标签: r date dataframe

x <- structure(list(SU_BIRTH_DATE = structure(c(47482, 2884, 11347, 
10449, -1280, 2324), class = "Date")), row.names = c(NA, 6L), class = "data.frame", .Names = "SU_BIRTH_DATE")

 x
  SU_BIRTH_DATE
1    2100-01-01
2    1977-11-24
3    2001-01-25
4    1998-08-11
5    1966-07-01
6    1976-05-13

通过查看数据集,可以清楚地看到许多人使用了拼写错误的出生日期,他们在年份中输入了2100而不是2001年。

我想用2001年替换日期字段的任何2100年部分。

我该怎么做?

x <- x %>% 
  mutate(SU_BIRTH_DATE = if_else(year(SU_BIRTH_DATE) == 2100, year(SU_BIRTH_DATE) = 2001,SU_BIRTH_DATE))
  

错误:意外&#39; =&#39;在:   &#34; x&lt; - x%&gt;%     mutate(SU_BIRTH_DATE = if_else(年(SU_BIRTH_DATE)== 2100,年(SU_BIRTH_DATE)=&#34;

EDIT 转换为字符并使用str_replace然后转换回日期是一个同时起作用的解决方案,但我确信这样做的代码更聪明,代码更少?

   x <- x %>% mutate(SU_BIRTH_DATE = str_replace_all(as.character(SU_BIRTH_DATE), "2100", "2001"),
              SU_BIRTH_DATE = ymd(SU_BIRTH_DATE))

3 个答案:

答案 0 :(得分:1)

您可以使用gsub"2100"替换为"2001",然后转换结果as.Date

x %>% mutate(SU_BIRTH_DATE = as.Date(gsub("2100", "2001", SU_BIRTH_DATE)));
#  SU_BIRTH_DATE
#1    2001-01-01
#2    1977-11-24
#3    2001-01-25
#4    1998-08-11
#5    1966-07-01
#6    1976-05-13

我承认,这与您的str_replace_all方法类似,虽然有点短。

答案 1 :(得分:1)

一种选择是使用year函数形式lubridate来检查并分配回年份。我用自定义函数来解释替换。这样就不会中断dplyr链并且不会转换为character

可以使用custom来避免使用case_when功能。

选项#1

replace_year <- function(x){
  for(i in seq_along(x))
  if(year(x[i]) == 2100){
    year(x[i]) <- 2001
  }
  x
}


x %>% mutate(SU_BIRTH_DATE = replace_year(SU_BIRTH_DATE))

选项#2 :可以避免使用自定义函数case_when

x %>% mutate(SU_BIRTH_DATE = case_when(
  year(SU_BIRTH_DATE) == 2100 ~ `year<-`(SU_BIRTH_DATE, 2001),
  TRUE ~ SU_BIRTH_DATE
  ))

# SU_BIRTH_DATE
# 1    2001-01-01
# 2    1977-11-24
# 3    2001-01-25
# 4    1998-08-11
# 5    1966-07-01
# 6    1976-05-13 

答案 2 :(得分:1)

有时你必须离开dplyr烟斗。如果你想使用with(x, year(SU_BIRTH_DATE[SU_BIRTH_DATE == 2100]) <- 2001) x SU_BIRTH_DATE 1 2001-01-01 2 1977-11-24 3 2001-01-25 4 1998-08-11 5 1966-07-01 6 1976-05-13 分配新的一年(合理的愿望),它将无法在管道内运行良好。这样做:

{{1}}