unmark1
unmark1

Reputation: 342

Date comparison R

I am doing a date comparison in R and the output class is awkward, as I was expecting a date object, but I am receiving a numeric. Can you explain why? What is the logic behind it?

library(data.table)
library(lubridate)

dt <- data.table(date_hist = ymd(seq.Date(as.Date("2018-01-01"), by = "month", length.out = 24)))
dt[,date_aux := ifelse(date_hist>max(date_hist),ymd(as.Date(max(date_hist),format = "%Y-%m-%d")),ymd(as.Date(date_hist,format = "%Y-%m-%d")))]

    date_hist date_aux
 1: 2018-01-01    17532
 2: 2018-02-01    17563
 3: 2018-03-01    17591
 4: 2018-04-01    17622
 5: 2018-05-01    17652
 6: 2018-06-01    17683
 7: 2018-07-01    17713
 8: 2018-08-01    17744
 9: 2018-09-01    17775
10: 2018-10-01    17805
11: 2018-11-01    17836
12: 2018-12-01    17866
13: 2019-01-01    17897
14: 2019-02-01    17928
15: 2019-03-01    17956
16: 2019-04-01    17987
17: 2019-05-01    18017
18: 2019-06-01    18048
19: 2019-07-01    18078
20: 2019-08-01    18109
21: 2019-09-01    18140
22: 2019-10-01    18170
23: 2019-11-01    18201
24: 2019-12-01    18231
     date_hist date_aux

sapply(dt,class)
date_hist  date_aux 
   "Date" "numeric"

Upvotes: 1

Views: 550

Answers (1)

akrun
akrun

Reputation: 887108

Instead of ifelse use fifelse

library(data.table)
dt[, date_aux := fifelse(date_hist>max(date_hist),ymd(as.Date(max(date_hist),
     format = "%Y-%m-%d")),ymd(as.Date(date_hist,format = "%Y-%m-%d")))]

str(dt)
#Classes ‘data.table’ and 'data.frame': 24 obs. of  2 variables:
# $ date_hist: Date, format: "2018-01-01" "2018-02-01" "2018-03-01" "2018-04-01" ...
# $ date_aux : Date, format: "2018-01-01" "2018-02-01" "2018-03-01" "2018-04-01" ...

with ifelse, the dates are converted to its storage mode i.e. numeric

If we check the source code, it is at the last few lines of assignment that creates the issue

...
ans <- test
len <- length(ans)
ypos <- which(test)
npos <- which(!test)
if (length(ypos) > 0L) 
    ans[ypos] <- rep(yes, length.out = len)[ypos]
if (length(npos) > 0L) 
    ans[npos] <- rep(no, length.out = len)[npos]
ans
...

With a simple example

v1 <- Sys.Date() -  1:5
v2 <- Sys.Date() + 1:5
ans <- v1 > Sys.Date() - 2 # logical vector
ypos <- which(ans)
npos <- which(!ans)
ans[ypos] <- rep(v2, length.out = length(ans))[ypos] Datess
ans
#[1] 18335     0     0     0     0

assigning Date class on the logical vector coerces the Date to convert to numeric

Upvotes: 3

Related Questions