【问题标题】:R - Formatting dates in dataframe - mix of decimal and character valuesR - 格式化数据框中的日期 - 十进制和字符值的混合
【发布时间】:2020-01-02 06:07:09
【问题描述】:

我在数据框中有一个日期列。我已经使用 openxlsx 将这个 df 读入 R。当我使用typeof(df$date) 时,该列被“视为”为字符向量。

该列包含多种格式的日期信息,我希望将其转换为一种格式。

#Example
date <- c("43469.494444444441", "12/31/2019 1:41 PM", "12/01/2019  16:00:00")

#What I want -updated
fixed <- c("2019-04-01", "2019-12-31", "2019-12-01")

我尝试了很多解决方法,包括openxlsx::ConvertToDatelubridate::parse_date_timelubridate::date_decimal

openxlsx::ConvertToDate到目前为止效果最好,但它只需要一种格式并为其他格式强制 NA

更新

我意识到我实际上把上述输出日期之一弄错了。 值 43469.494444444441 应转换为 2019-04-01。

【问题讨论】:

    标签: r lubridate openxlsx


    【解决方案1】:

    这是分两步执行此操作的一种方法。单独更改 excel 日期,并以不同方式更改所有其他日期。如果您有更多的日期格式可以添加到parse_date_time

    temp <- lubridate::parse_date_time(date, c('mdY IMp', 'mdY HMS'))
    temp[is.na(temp)] <- as.Date(as.numeric(date[is.na(temp)]), origin = "1899-12-30")
    
    temp
    #[1] "2019-01-04 11:51:59 UTC" "2019-12-31 13:41:00 UTC" "2019-12-01 16:00:00 UTC"
    as.Date(temp)
    #[1] "2019-01-04" "2019-12-31" "2019-12-01"
    

    【讨论】:

    • 谢谢我喜欢这个解决方案。当我使用 read_excel 时为我工作
    【解决方案2】:

    您可以使用辅助函数来规范化日期,这可能比lubridate 稍快。

    weird origins in MS Excel 依赖于平台。因此,如果数据是从不同平台导入的,您可能需要使用虚拟变量。

    normDate <- Vectorize(function(x) {
    if (!is.na(suppressWarnings(as.numeric(x))))  # Win excel
      as.Date(as.numeric(x), origin="1899-12-30")
    else if (grepl("A|P", x))
      as.Date(x, format="%m/%d/%Y %I:%M %p")
    else
      as.Date(x, format="%m/%d/%Y %R")
    })
    

    对于其他日期格式,只需添加另一个 else if。格式规范可以通过?strptime找到。

    然后只需使用通常来源的as.Date()

    res <- as.Date(normDate(date), origin="1970-01-01")
    # 43469.494444444441   12/31/2019 1:41 PM 12/01/2019  16:00:00 
    #       "2019-01-04"         "2019-12-31"         "2019-12-01"
    class(res)
    # [1] "Date"
    

    编辑:要实现特定的输出格式,请使用format,例如

    format(res, "%Y-%d-%m")
    # 43469.494444444441   12/31/2019 1:41 PM 12/01/2019  16:00:00 
    #       "2019-04-01"         "2019-31-12"         "2019-01-12" 
    
    format(res, "%Y/%d/%m")
    # 43469.494444444441   12/31/2019 1:41 PM 12/01/2019  16:00:00 
    #       "2019/04/01"         "2019/31/12"         "2019/01/12" 
    

    要查找代码,请键入?strptime

    【讨论】:

    • 这似乎效果最好。只有在我的实际 df 中,某些日期的日期和月份不正确,例如10Apr19 报告为 2019-10-04 而不是 2019-04-10
    • as.Date("10Apr19", format="%d%b%y") 能完成这项工作吗?您可以输入?strptime 查找更多格式字符串。
    • 谢谢 jay.sf,日期 10Apr19 在我的 df 中显示为 43469.494444444441 我希望 R 显示为 2019-04-10 但是当我使用上面的代码时它报告为 2019-10-04
    • 谢谢 jay.sf 但是如果你看上面的其他日期现在是不正确的。我认为数据太乱了,无法处理。非常感谢您的帮助:)
    • @AudileF 将format() 包含在公式中会更好吗,即format(as.Date(as.numeric(x), origin="1899-12-30"), "%Y-%d-%m")
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 1970-01-01
    相关资源
    最近更新 更多