Cyrus Mohammadian
Cyrus Mohammadian

Reputation: 5193

Convert strings to dates only for numeric values in R

Suppose I have a vector of values mixed between numeric and string, such as in the following:

df<-structure(c("Location", "SKU", "Manufacturer", "Size", 
            "State", "43488", "43489", "43490", 
            "43491"), .Names = c("col1","col2","col3","col4","col5","col6","col7","col8","col9"))

I would like to convert only the numeric values (originally excel dates) into the R date format and leave the remaining variables as is. The vector I'm working with is just one row in a larger data.frame so I would prefer to avoid splitting the dates from the strings and coalescing afterward. So far I tried the following:

as.Date(as.numeric(df), origin = "1899-12-30")
[1] NA           NA           NA           NA           NA           "2019-01-23" "2019-01-24" "2019-01-25" "2019-01-26"

But this converts the character strings to NA.

Upvotes: 1

Views: 85

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388982

We could find out the indices which has numbers in it and then convert only those values to date.

inds <- grepl("\\d+", df)
df[inds] <- format(as.Date(as.numeric(df[inds]), origin = "1899-12-30"))

df
#      col1           col2           col3           col4           col5 
#"Location"          "SKU" "Manufacturer"         "Size"        "State"

#      col6           col7           col8           col9 
#"2019-01-23"   "2019-01-24"   "2019-01-25"   "2019-01-26" 

A variation to the above answer using ifelse without creating an additional variable (inds)

ifelse(grepl("\\d+", df), format(as.Date(as.numeric(df), origin = "1899-12-30")), df)

Upvotes: 2

billydh
billydh

Reputation: 1035

Try this:
- create a function to check whether a value can be coerced to numeric type or not
- if true, then convert it to numeric and format it to date
- if false, then return the value as is

df<-structure(c("Location", "SKU", "Manufacturer", "Size", 
                "State", "43488", "43489", "43490", 
                "43491"), .Names = c("col1","col2","col3","col4","col5","col6","col7","col8","col9"))

convert_num_to_date = function(x){
  if (is.na(as.numeric(x))) {
    return(x)
  } else {
    x = format(as.Date(as.numeric(x), origin = "1899-12-30"))
    return(x)
  }
}

df = sapply(df, convert_num_to_date)

Upvotes: 1

Related Questions