Zach Zach - 2 months ago 29
R Question

How to prevent ifelse() from turning Date objects into numeric objects

I am using the function

ifelse()
to manipulate a date vector. I expected the result to be of class
Date
, and was surprised to get a
numeric
vector instead. Here is an example:

dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04', '2011-01-05'))
dates <- ifelse(dates == '2011-01-01', dates - 1, dates)
str(dates)


This is especially surprising because performing the operation across the entire vector returns a
Date
object.

dates <- as.Date(c('2011-01-01', '2011-01-02', '2011-01-03', '2011-01-04','2011-01-05'))
dates <- dates - 1
str(dates)


Should I be using some other function to operate on
Date
vectors? If so, what function? If not, how do I force
ifelse
to return a vector of the same type as the input?

The help page for
ifelse
indicates that this is a feature, not a bug, but I'm still struggling to find an explanation for what I found to be surprising behavior.

Answer

You may use dplyr::if_else.

From dplyr 0.5.0 release notes: "[if_else] have stricter semantics that ifelse(): the true and false arguments must be the same type. This gives a less surprising return type, and preserves S3 vectors like dates" .

library(dplyr)
dates <- if_else(dates == '2011-01-01', dates - 1, dates)
str(dates)
# Date[1:5], format: "2010-12-31" "2011-01-02" "2011-01-03" "2011-01-04" "2011-01-05"