使用ifelse()排除日期

时间:2017-10-26 16:19:16

标签: r

我有一个带有数万个条目的日期变量的数据框。我认为某处可能存在数据输入错误,因为我无法将其转换为日期类变量或在lubridate()中处理它。

在这个MWE中,第一个观察(a1)是一个合法的日期,格式是我期望我的日期。其他观察(a2-a7)代表不同类型的数据输入错误。我想测试日期变量中的每个观察,以查看观察是否是预期格式的合法日期。

我尝试使用常规模式和ifelse(),但我无法使代码工作。我想最终得到类似df2的东西(尽管它不一定是数据框),这样我就可以轻松识别可能需要注意的任何日期变量观察的ID。任何帮助将非常感激。

起点:

df1 <- data.frame(varID=c("a1","a2","a3","a4","a5","a6","a7"),varDate=c("01/01/2015","0101/2016","01/012017","35/01/2018","01/17/2019","01/01/20200","abc"))

期望的结果:

df2 <- data.frame(varID=c("a2","a3","a4","a5","a6","a7"),VarIssue=c("format issue","format issue","format issue","format issue","format issue","format issue"))

当前代码:

ifelse(df1$varDate == (^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$),"ok","format issue")

2 个答案:

答案 0 :(得分:2)

两个问题,你不能单独使用Regex,它需要在接受正则表达式模式的函数中调用,并且你需要双重转义代词字符。

在R中你必须使用双重转义:\\d,所以你的模式变成:

 pattern <- '^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\\d\\d$'

我们使用grepl(返回逻辑向量)来检查每一行:

df1$check <-  ifelse(grepl(pattern,df1$varDate)==TRUE,"ok", "format issue")

  varID     varDate        check
1    a1  01/01/2015           ok
2    a2   0101/2016 format issue
3    a3   01/012017 format issue
4    a4  35/01/2018 format issue
5    a5  01/17/2019 format issue
6    a6 01/01/20200 format issue
7    a7         abc format issue

答案 1 :(得分:2)

以下可能是偏离主题的,但如果您遇到日期格式问题,请考虑使用包lubridate,其characterDate转换功能会识别大量格式并且在出现问题的第一个迹象时不要放弃它。

library(lubridate)

mdy(df1$varDate)
#[1] "2015-01-01" "2016-01-01" "2017-01-01" NA           "2019-01-17"
#[6] NA           NA          
#Warning message:
# 3 failed to parse.

正如您所看到的那样3 failed to parse.其他人被正确强制归入Date课程。然后你会使用更简单的ifelse,但结果显然会有很大不同。

df3 <- data.frame(varID = df1$varID)
df3$VarIssue <- ifelse(is.na(mdy(df1$varDate)), "format issue", "ok")
df3
#  varID     VarIssue
#1    a1           ok
#2    a2           ok
#3    a3           ok
#4    a4 format issue
#5    a5           ok
#6    a6 format issue
#7    a7 format issue

只有3 "format issue"