首页 > 解决方案 > 在数据框中将不同格式的字符串更改为相同格式的日期

问题描述

我有一个看起来像这样的数据框(它有成千上万这样的日期行,范围从 18xx 年到 2019 年)

                date
1   25 February 1987
2     20 August 1974
3     9 October 1984
4          16-Oct-63
5         13-11-1961
6           03/23/87
7         01.01.1995
8      February 1988
9               1988
10 20050101-20051231

我需要将日期列更改为一种日期格式(例如:YYYY-MM-DD 或任何其他格式)。由于 ID 9 只有一些年份值,因此我还必须自动填充它们。这应该总是导致特定年份的最后一天。如果它像 ID 8 一个月和一年,它应该总是填充特定月份的最后一天(并检查它是否是闰年,就像在 1988 年一样,在这种情况下返回类似 1988-02-29 )。如果是最后一行的时间范围,则应始终切断第一部分并将其更改为给定年份的 12 月 31 日。我怎样才能做到这一点?

我考虑过使用 lubridate 包或随时包。使用 lubridate 和 parse_date 或 parse_date_time。这甚至可以工作,但它总是填充几天到一个月的第一天而不是最后一天的缺失值。

library(lubridate)

date <- c("25 February 1987", "20 August 1974", "9 October 1984", "16-Oct-63", "13-11-1961", "03/23/87", "01.01.1995",
          "February 1988", "1988", "20050101-20051231")

df <- as.data.frame(date)

parse_date(df$date)

parse_date_time(x = df$date,
                orders = c("d m y", "d B Y", "d/m/Y","B Y", "Y", "m/d/y",
                           "Ymd-Ymd"),
                locale = "eng")

我的实际结果

(parse_date(df$date)): 

 [1] "1987-02-25 UTC" "1974-08-20 UTC" "1984-10-09 UTC" "2019-10-16 UTC" "2019-11-13 UTC" "1987-03-23 UTC" "1995-01-01 UTC"
 [8] "1988-02-01 UTC" "1988-01-01 UTC" "2005-12-31 UTC"

对于 parse_date_time,由于最后一个命令“Ymd-Ymd”,我实际上得到了一个错误(如果我只是测试:parse_date("20050101-20051231") it results in "2005-12-31 UTC",我真的很想拥有!)

标签: rrstudio

解决方案


使用 lubridate 备忘单 ( https://evoldyn.gitlab.io/evomics-2018/ref-sheets/R_lubridate.pdf ) 并通过 dplyr 反复试验:

df %>% 
        mutate(newdate = parse_date_time(x = date, orders = c("dmy", "mdy", "my", "y")) ) %>% 
        mutate(newdate2 = case_when(
                        newdate > today() ~ newdate - 100*365.25*24*3600,
                        is.na(newdate) ~ paste0(substr(x=date, start = 1, stop = 4), "-", 
                                                substr(x=date, start = 5, stop = 6), "-",
                                                substr(x=date, start = 7, stop = 8) )
                        %>%
                                parse_date_time(., orders = c("dmy", "mdy", "my", "y", "ymd")),
                        TRUE ~ newdate
        )
        )

推荐阅读