Why does looping over a vector of POSIXct-times change the type in R?

50 Views Asked by At

I am using R on a regular basis and I have stumbled above something weird:

Sys.time() |> class()
times <- Sys.time()+1:3
print(times)
for (tme in times) {
  print(tme)
}
tme %in% times

This gives the output:

> Sys.time() |> class()
[1] "POSIXct" "POSIXt" 
> times <- Sys.time()+1:3
> print(times)
[1] "2024-01-18 10:00:28 CET" "2024-01-18 10:00:29 CET" "2024-01-18 10:00:30 CET"
> for (tme in times) {
+   print(tme)
+ }
[1] 1705568429
[1] 1705568430
[1] 1705568431
> tme %in% times
[1] FALSE

How is such a behaviour justifiable? I find the last line especially hard to justify (tme %in% times == FALSE).

1

There are 1 best solutions below

4
ThomasIsCoding On BEST ANSWER

Reason behind

In for loop, the expression times will be coerced to a vector (when you see the help document by typing ?`for`

An expression evaluating to a vector (including a list and an expression) or to a pairlist or NULL. A factor value will be coerced to a character vector. This can be a long vector.

However, in vector, no attribute will be retained (when typing ?vector and see the description)

vector produces a ‘simple’ vector of the given length and mode, where a ‘simple’ vector has no attribute, i.e., fulfills is.null(attributes(.)).

Workaround

To keep all the attributes, you can convert the values in times into a list, for example, you can use as.list(times) in for loop like below

> for (time in as.list(times)) {
+     print(time)
+ }
[1] "2024-01-18 10:13:39 CET"
[1] "2024-01-18 10:13:40 CET"
[1] "2024-01-18 10:13:41 CET"

or you can use sapply like below

> invisible(sapply(times, print))
[1] "2024-01-18 10:13:39 CET"
[1] "2024-01-18 10:13:40 CET"
[1] "2024-01-18 10:13:41 CET"