Looping over a Date or POSIXct object results in a numeric iterator

RDateFor LoopAttributesPosixct

R Problem Overview


Why does iterating through a Date or POSIXct object result in numeric? For example:

test = as.Date("2009-01-01")
print( class( test ) )
# [1] "Date"
for ( day in test )
{
    print( class( day ) )
}
# [1] "numeric"

The same thing happens with POSIXct:

test = as.POSIXct("2009-01-01")
print( class( test ) )
# [1] "POSIXct" "POSIXt"
for ( day in test )
{
    print( class( day ) )
}
# [1] "numeric"

R Solutions


Solution 1 - R

?"for" says that seq (the part after in) is "[A]n expression evaluating to a vector (including a list and an expression) or to a pairlist or 'NULL'".

So your Date vector is being coerced to numeric because Date objects aren't strictly vectors:

is.vector(Sys.Date())
# [1] FALSE
is.vector(as.numeric(Sys.Date()))
# [1] TRUE

The same is true for POSIXct vectors:

is.vector(Sys.time())
# [1] FALSE
is.vector(as.numeric(Sys.time()))
# [1] TRUE

Solution 2 - R

loop through days (strings):

     days <- seq(from=as.Date('2011-02-01'), to=as.Date("2011-03-02"),by='days' )
     for ( i in seq_along(days) )
     {
          print(i)
           print(days[i])
      }

Solution 3 - R

You are not choosing the right function to apply to Date vectors when using for-loops. Better would be wrapping seq_along for pretty much every date or factor that is being looped across. Then you will do two thing: a) set it up so you are expecting an index that starts at 1, and b) protect against strange things that occur with zero length vectors. I also think it would be better to use it with factors, which the for-loops will turn into character vectors.

With reference to Joshua's answer (which is certainly correct and helpful), I think the is.vector function is a bit mislabeled or maybe just misunderstood. It could be more accurately be called hasNoAttributesOtherThanName. The property that most people consider "vectoric" is tested with is.atomic and Date and POSIXct objects will return TRUE from that test.

Solution 4 - R

It seems that the C function that implements the for loop does not copy any of the vector's attributes. This also includes the class attribute, which should make i appear to be a Date object.

You may study the source code of the do_for(SEXP, SEXP, SEXP, SEXP) function (the one called by R's for) here.

Solution 5 - R

It is an old question, but I am a novice on R and faced the same problem. Since my problem would be processed in parallel, I used foreach and saw the behaviour is different when compared with the normal for:

library(foreach)

start_date = as.Date("2013-08-1")
end_date = as.Date("2013-08-13")
days = seq(start_date, end_date, by = "day")

foreach(day = days, .combine='rbind') %dopar% {
  print(class(day))
}

[1] "Date"
[1] "Date"
[1] "Date"
[1] "Date"
...

As I am not experienced with the inner things of most of R, thus I do not know why foreach ends up having a different behaviour but that worked for my purpose, and hopefully might be useful for someone else.

Solution 6 - R

Any numerical operation on date objects generally returns the number of days. In this, you are asking it to provide you with the number of days from the epoch. 14245 which is the number of days between 1970-01-01 - 2009-01-01

From ?Dates:

> Dates are represented as the number of > days since 1970-01-01, with negative > values for earlier dates. They are > always printed following the rules of > the current Gregorian calendar, even > though that calendar was not in use > long ago (it was adopted in 1752 in > Great Britain and its colonies). > > It is intended that the date should be > an integer, but this is not enforced > in the internal representation. > Fractional days will be ignored when > printing. It is possible to produce > fractional days via the mean method or > by adding or subtracting (see > Ops.Date).

Try adding print(day) to see what I mean.

test = as.Date("2009-01-01")
print( class( test ) )
for ( day in test )
{
  print(day)
  print( class( day ) )
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSurajView Question on Stackoverflow
Solution 1 - RJoshua UlrichView Answer on Stackoverflow
Solution 2 - RpleoView Answer on Stackoverflow
Solution 3 - RIRTFMView Answer on Stackoverflow
Solution 4 - RgagolewsView Answer on Stackoverflow
Solution 5 - REduardoView Answer on Stackoverflow
Solution 6 - RBrandon BertelsenView Answer on Stackoverflow