0

I have a dataframe which contains multiple columns with date-values as strings (format: YYYYMMDD).

dt_example <- data.frame ( 
    W03 = "20201130",
    W44 = "19711031",
    P01 = "19740813",
    P04 = "20000506",
    Z02 = "20201231"
  )

Now I want to convert the strings to date-format and tried the following code which works fine:

dt_example_date <- dt_example %>% 
  mutate(
    W03 = as.Date(W03, "%Y%m%d")
    ,W44 = as.Date(W44, "%Y%m%d")
    ,P01 = as.Date(P01, "%Y%m%d")
    ,P04 = as.Date(P04, "%Y%m%d")
    ,Z02 = as.Date(Z02, "%Y%m%d")
  )

But this code is annoying and I want to use "mutate across" instead of mutliple as.Date-conversions.

I've tried several alternatives, but nothing works.

dt_example_date_2 <- dt_example %>% 
  mutate(
    across(
      c("W03","W44","P01","P04","Z02")
      ,as.Date
    )
  )

Result: character string is not in a standard unambiguous format

dt_example_date_2 <- dt_example %>% 
  mutate(
    across(
      c("W03","W44","P01","P04","Z02")
      ,as.Date(format="%y%m%d")
    )
  )

Result: argument "x" missing

dt_example_date_2 <- dt_example %>% 
  mutate(
    across(
      c("W03","W44","P01","P04","Z02")
      ,as.Date(., format="%y%m%d")
    )
  )

Result: do not know how to convert '.' to class “Date”

I didn't get it and don't know, what to do.

How can I pass paramaters to the function used within the across-command?

Greetings Benne

benne
  • 37
  • 4

5 Answers5

4

Try this:

#Code
dt_example_date_2 <- dt_example %>% 
  mutate(
    across(
      c(W03,W44,P01,P04,Z02)
      ,~as.Date(.,format="%Y%m%d")
    )
  )

Output:

dt_example_date_2
         W03        W44        P01        P04        Z02
1 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31

To avoid typing all names you can try this (Many thanks and credits to @latlio):

#Code 2
dt_example_date_2 <- dt_example %>% 
  mutate(
    across(
      everything()
      ,~as.Date(.,format="%Y%m%d")
    )
  )

Same output.

Duck
  • 39,058
  • 13
  • 42
  • 84
2

a) you need to pass the format argument comma-separated.
b) you had a typo in your format (lowercase "y" instead of uppercase).

dt_example %>%
  mutate(across(c("W03","W44","P01","P04","Z02"), as.Date, format = "%Y%m%d"))

gives:

         W03        W44        P01        P04        Z02
1 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31
deschen
  • 10,012
  • 3
  • 27
  • 50
0

Base R solution: You can simply pass the structure directly to as.Date if you convert it to a matrix before.

dt_example_date <- as.Date(as.matrix(dt_example), "%Y%m%d")
# [1] "2020-11-30" "1971-10-31" "1974-08-13" "2000-05-06" "2020-12-31"

str(dt_example_date)
#  Date[1:5], format: "2020-11-30" "1971-10-31" "1974-08-13" "2000-05-06" "2020-12-31"

or preserving dataframe structure:

as.data.frame(sapply(X = dt_example, FUN = as.Date, "%Y%m%d", simplify = F))
#         W03        W44        P01        P04        Z02
#1 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31
Martin
  • 594
  • 5
  • 16
0

You can try across with everything() like below

> dt_example %>%
+   mutate(across(everything(), as.Date, format = "%Y%m%d"))
         W03        W44        P01        P04        Z02
1 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31

A data.table option is

> setDT(dt_example)[, lapply(.SD, as.Date, format = "%Y%m%d")]
          W03        W44        P01        P04        Z02
1: 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31

A base R option using list2DF + Map

> list2DF(Map(as.Date, dt_example, "%Y%m%d"))
         W03        W44        P01        P04        Z02
1 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81
0

You can use lubridate package:

data.frame ( 
  W03 = "20201130",
  W44 = "19711031",
  P01 = "19740813",
  P04 = "20000506",
  Z02 = "20201231"
) %>% 
  mutate(across(everything(), lubridate::ymd))

This gives:

         W03        W44        P01        P04        Z02
1 2020-11-30 1971-10-31 1974-08-13 2000-05-06 2020-12-31

Alvaro Morales
  • 1,845
  • 3
  • 12
  • 21