【问题标题】:convert data frame column containing different date formats to Date object将包含不同日期格式的数据框列转换为 Date 对象
【发布时间】:2016-02-18 09:45:39
【问题描述】:

我有一个 character 类的数据框列,其中包含不同的日期格式:

foo=data.frame(Date=c("29-Jan-16","29-Jan-16","2/5/2016","2/5/2016"),stringsAsFactors = F)

我想将Date 列转换为Date 类对象的向量。我可以分别正确解析每种格式:

> as.Date( foo$Date, format = "%d-%b-%y" )
[1] "2016-01-29" "2016-01-29" NA           NA          
> as.Date( foo$Date, format = "%m/%d/%Y" )
[1] NA           NA           "2016-02-05" "2016-02-05"

所以我想用ifelsegrepl 加入两个解析指令。请注意,grepl 正确识别了使用第一种格式的行

> grepl("-",foo$Date)
[1]  TRUE  TRUE FALSE FALSE

但是,完整的指令不起作用:

bar = foo
bar$Date=ifelse(grepl("-",foo$Date),
                      as.Date( foo$Date, format = "%d-%b-%y" ),
                      as.Date( foo$Date, format = "%m/%d/%Y" ))

> bar
   Date
1 16829
2 16829
3 16836
4 16836

问题:

  1. 您能帮我了解发生了什么吗?
  2. 即使我设法在您的帮助下修复了我的解决方案,我也了解了更多关于 R 的知识,这很好,但解决方案仍然不是最理想的。原因是填充数据框的“聪明”人可能会选择使用更多的日期格式(以前已经发生过,并且很可能会再次发生)。然后我将不得不嵌套更多ifelse,并创建更复杂的正则表达式。代码很快就会变得令人讨厌和不可读。有没有办法让 R 自动为foo$Date 的每个元素找到正确的数据格式?

【问题讨论】:

    标签: regex r date


    【解决方案1】:

    使用lubridate 会更容易。假设'Date'的格式为日、月、年,我们可以使用dmy

    library(lubridate)
    dmy(foo$Date)
    #[1] "2016-01-29 UTC" "2016-01-29 UTC" "2016-05-02 UTC" "2016-05-02 UTC"
    

    如果顺序有其他变化,我们也可以使用guess_formatsparse_date_time

     with(foo, parse_date_time(Date, 
             orders=guess_formats(Date, c('dby', 'mdy'))))
     #[1] "2016-01-29 UTC" "2016-01-29 UTC" "2016-02-05 UTC" "2016-02-05 UTC"
    

    关于ifelse在OP的代码中的使用,我们在numeric类中得到的输出可以转换回Date

    v1 <- ifelse(grepl("-",foo$Date),
                      as.Date( foo$Date, format = "%d-%b-%y" ),
                      as.Date( foo$Date, format = "%m/%d/%Y" ))
    
    as.Date(v1, origin='1970-01-01')
    #[1] "2016-01-29" "2016-01-29" "2016-02-05" "2016-02-05"
    

    【讨论】:

    • 非常感谢您快速明确的回答!不幸的是,虽然第一种格式确实是日、月、年,但第二种不是:它是月、日和年(4 位数字)。我安装了lubridate 并查看了帮助,但我不熟悉该软件包,我不确定如何组合parse_date_timeguess_formats。你能用它们完成你的解决方案吗?谢谢
    • @DeltaIV 在这种情况下,您可以使用guess_formats,更新答案。
    • @DeltaIV 如果有像2/5/20165/2/2016 这样的日期,第一种情况是m/d/Y' and the second is d/m/Y`,这可能会很困难。
    • 非常感谢!现在可以了。对于疑难案件,希望我的“供应商”不要太疯狂。如果发生这种情况,我可能会发布另一个问题 :) 再次感谢,你真的帮助了我。
    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 2016-08-14
    • 2016-05-03
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多