【问题标题】:Conditionally change the year part of a date within a dplyr chain有条件地更改 dplyr 链中日期的年份部分
【发布时间】:2018-03-24 05:38:17
【问题描述】:
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))

错误:意外的“=”在: "x % 变异(SU_BIRTH_DATE = if_else(年(SU_BIRTH_DATE)== 2100,年(SU_BIRTH_DATE)=“

编辑 转换为字符并使用 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))

【问题讨论】:

  • 您的问题是if_else(以及ifelse)需要true(或yes)参数才能真正成为某种东西。 year&lt;- 不返回任何内容,并且将其括在括号中也无法将您保存在这里,因为它只会返回 2001

标签: r date dataframe


【解决方案1】:

一种选择是使用year 函数形式lubridate 来检查然后分配回溯年份。我使用自定义函数来解释替换。这不会破坏dplyr 链,也不会转换为character

使用case_when可以避免使用custom函数。

选项#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】:

    您可以使用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 方法,尽管时间短一些。

    【讨论】:

      【解决方案3】:

      有时您必须摆脱 dplyr 管道。如果您想使用lubridate::year 来分配新的一年(一个合理的愿望),它在管道内不会很好地运行。改为这样做:

      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
      

      【讨论】:

      • 感谢简单易懂的回答,很难选择接受哪个
      猜你喜欢
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-01
      相关资源
      最近更新 更多