2

Desire to convert class of multi cols without knowing the location .

This is the dataset

# Dataset name call : df . # It is a example , real data has many columns
# that you cannot have a clear index by one sight.

A.Date      Price  B.Date       C.Date      Size    D.Date
2017-01-01   502   2017-01-03   2017-11-01   45.4   2016-10-01
2015-01-31   602   2017-02-03   2013-07-11   65.4   2016-03-24

I have a code like below :

 df[,grepl("Date",colnames(df))] <-
 lapply(df[,grepl("Date",colnames(df))],function(x) as.Date(x))

But its turn out error :

Error in strptime(x, f) : input string is too long

Even i tried this code :

 DateCol <- grep("Date",names(df)) 
 df[,c(DateCol)] <- as.Date(df[,c(DateCol)])

It goes by error again like Error in as.Date.default(df[, c(DateCol)]) : 'df[, c(DateCol)]' class “Date” cannot be defined

What is wrong with the code and what is the solution ?

MKR
  • 19,739
  • 4
  • 23
  • 33
rane
  • 901
  • 4
  • 12
  • 24
  • Can you show the `class` of the columns. The second solution will not work because `as.Date` needs a `vector` or column as input. I have doubts about the `class` of the 'Date' columns – akrun Mar 28 '18 at 03:32
  • All Date columns class are " Character" . thankyou neilfws – rane Mar 28 '18 at 03:58
  • sorry that i forget to mention one important point that , some of the Date cols cannot be converted. Because its contain : "2017-01-01 ; 2018-01-01 " in one element . So the solution should avoid these type of col but convert the normal type. – rane Mar 28 '18 at 04:08

2 Answers2

1

If your xxx.Date columns are character then

library(dplyr)

txt <- "A.Date      Price  B.Date       C.Date      Size    D.Date
2017-01-01   502   2017-01-03   2017-11-01   45.4   2016-10-01
2015-01-31   602   2017-02-03   2013-07-11   65.4   2016-03-24"

dat <- read.table(text = txt, header = TRUE)

res <- dat %>% 
  mutate_if(is.character, as.Date)
str(res)  

> str(res)
'data.frame':   2 obs. of  6 variables:
 $ A.Date: Date, format: "2017-01-01" ...
 $ Price : int  502 602
 $ B.Date: Date, format: "2017-01-03" ...
 $ C.Date: Date, format: "2017-11-01" ...
 $ Size  : num  45.4 65.4
 $ D.Date: Date, format: "2016-10-01" ...

Created on 2018-03-27 by the reprex package (v0.2.0).

Tung
  • 26,371
  • 7
  • 91
  • 115
  • Thankyou Tung. But what arguments should fill after "is.character" and "as.Date" ? *Error in mutate_impl(.data, dots) : Evaluation error: character string is not in a standard unambiguous format. – rane Mar 28 '18 at 04:03
  • You don't need any argument. `mutate_if` checks if the columns are characters then converts them to `Date`. Try restart your R session (Ctrl + Shift + F10 in RStudio), then run my code only – Tung Mar 28 '18 at 04:20
  • 1
    Thank you Tung , your approach work . THe Error occur it was because some of the Date column contain double date like : "2019-01-31;2017-02-02", making all the answer the viewer not work. My problem that couldn't raise question properly to solve my situation that need apply to all columns contain "Date" and also drop multi date columns . – rane Mar 28 '18 at 06:10
1

Although, @Tung has been provided a good solution still I feel dplyr::mutate_at should be more appropriate choice in this case since columns expected to be changed to Date contains Date as part of their names. Hence if dataframe contains other character types columns then mutate_at will provide flexibiltiy to choose columns.

grep("Date",names(.), value = TRUE) provides list of columns wihch contains Date as part of their name.

mutate_at applies as.Date function to convert those columns to Date type.

library(dplyr)

df %>%
  mutate_at(vars(grep("Date",names(.), value = TRUE)), funs(as.Date))

#      A.Date Price     B.Date    C.Date Size     D.Date
#1 2017-01-01   502 2017-01-03 2017-11-01 45.4 2016-10-01
#2 2015-01-31   602 2017-02-03 2013-07-11 65.4 2016-03-24
MKR
  • 19,739
  • 4
  • 23
  • 33
  • Thankyou MKR , This is an good example for apply grep in mutate_at. They are work in one operation. – rane Apr 02 '18 at 01:17