在数据框中将具有不同格式的字符串更改为具有相同格式的日期

时间:2019-05-27 14:56:22

标签: r rstudio

我有一个看起来像这样的数据框(它有类似这样的日期行,范围从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仅包含一些Year值,因此我也必须自动填充它们。这应该始终指向特定年份的最后一天。如果它每个月和一年像ID 8,它应该始终填充特定月份的最后一天(并检查它是否是a年,例如1988年,在这种情况下返回类似1988-02-29 )。如果是与最后一行类似的时间表,则应始终截断第一部分并将其更改为给定年份的12月31日。 我该怎么办?

我考虑过使用lubridate软件包或anytime软件包。使用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"

由于最后的命令“ Ymd-Ymd”(如果我只是测试:parse_date("20050101-20051231") it results in "2005-12-31 UTC",我真的很想这样做!),在parse_date_time时,我最终得到一个错误。

2 个答案:

答案 0 :(得分:0)

使用润滑的备忘单(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
        )
        )

答案 1 :(得分:0)

谢谢。这非常接近。不幸的是,它仍然给我某些条目的错误输出日期。

<androidx.viewpager.widget.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingLeft="30dp"
        android:paddingRight="30dp" />

但是我需要这样:

               date    newdate   newdate2
1   25 February 1987 1987-02-25 1987-02-25
2     20 August 1974 1974-08-20 1974-08-20
3     9 October 1984 1984-10-09 1984-10-09
4          16-Oct-63 2063-10-16 1963-10-16
5         13-11-1961 1961-11-13 1961-11-13
6           03/23/87 1987-03-23 1987-03-23
7         01.01.1995 1995-01-01 1995-01-01
8      February 1988 1988-02-19 1988-02-19
9               1988 1988-01-01 1988-01-01
10 20050101-20051231       <NA> 2005-01-01

这意味着:如果我只有年份和月份:我需要输入特定月份的最后一天,对于2月,要考虑leap年,例如在示例行8中。如果我只有一年,则需要将其更改为给定年份的12月31日。并且如果该条目看起来像第10行,则需要剪切第一部分,只保留给定年份的12月31日,但是对于这种情况,我已经调整了代码的一部分:

               date    newdate   newdate2
1   25 February 1987 1987-02-25 1987-02-25
2     20 August 1974 1974-08-20 1974-08-20
3     9 October 1984 1984-10-09 1984-10-09
4          16-Oct-63 2063-10-16 1963-10-16
5         13-11-1961 1961-11-13 1961-11-13
6           03/23/87 1987-03-23 1987-03-23
7         01.01.1995 1995-01-01 1995-01-01
8      February 1988 1988-02-19 **1988-02-29**
9               1988 1988-01-01 **1988-12-31**
10 20050101-20051231       <NA> **2005-12-31**