R: What are dates in a dates vector: dates or numeric values? (difference between x[i] and i)

The elements are Date, the first loop is correct.

Unfortunately R does not consistently have the style of the second loop. I believe that the issue is that the for (i in x) syntax bypasses the Date methods for accessors like [, which it can do because S3 classes in R are very thin and don't prevent you from not using their intended interfaces. This can be confusing because something like for (i in 1:4) print(i) works directly, since numeric is a base vector type. Date is S3, so it is coerced to numeric. To see the numeric objects that are printing in the second loop, you can run this:

x <- as.Date(c("2018-01-01", "2018-01-02", "2018-01-02", "2018-05-06"))
for (i in x) print(i)
#> [1] 17532
#> [1] 17533
#> [1] 17533
#> [1] 17657

which is giving you the same thing as the unclassed version of the Date vector. These numbers are the days since the beginning of Unix time, which you can also see below if you convert them back to Date with that origin.

unclass(x)
#> [1] 17532 17533 17533 17657
as.Date(unclass(x), "1970-01-01")
#> [1] "2018-01-01" "2018-01-02" "2018-01-02" "2018-05-06"

So I would stick to using the proper accessors for any S3 vector types as you do in the first loop.


When you run:

for (i in seq_along(x)) print(class(x[i]))

You're using an iterator i over each element of x. Which means that each time you get the class of each iterated member of x.

However, when you run:

for (i in x) print(class(i))

You're looking for the class of each member. Using the ?Date:

Dates are represented as the number of days since 1970-01-01

Which is the reason why you get numeric as your class.

Moreover, if you'll use print() for each loop you'll get dates and numbers:

for (i in seq_along(x)) print(x[i])

[1] "2018-01-01"
[1] "2018-01-02"
[1] "2018-01-02"
[1] "2018-05-06"

and

for (i in x) print(i)

[1] 17532
[1] 17533
[1] 17533
[1] 17657

Lastly, if you want to test R's logic we can do something like that:

x[1] - as.Date("1970-01-01")

Taking the first element of x ("2018-01-01") and subtract "1970-01-01", which is the first date. Our output will be:

Time difference of 17532 days

If you look at ?'for', you'll see that for(var in seq) is only defined when seq is "An expression evaluating to a vector", and is.vector(x) is FALSE. So the documentation says (maybe not so clearly) that the behavior here is undefined, which is why the behavior is unexpected.

As joran mentions, as.vector(x) returns a numeric vector, same as unclass(x) mentioned by Calum You.

Tags:

Date

R