Looping Over a Date or Posixct Object Results in a Numeric Iterator

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

?"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

How to iterate over list of Dates without coercion to numeric?

There are two issues here. One is whether the input gets coerced from Date to numeric. The other is whether the output gets coerced to numeric.

Input

For loops coerce Date inputs to numeric, because as @DWin and @JoshuaUlrich point out, for loops take vectors, and Dates are technically not vectors.

> for(d in dates) print(class(d))
[1] "numeric"
[1] "numeric"

On the other hand, lapply and its simplifier offspring sapply have no such restrictions.

> sapply( dates, function(day) class(day) )
[1] "Date" "Date"

Output

However! The output of class() above is a character. If you try actually returning a date object, sapply is not what you want.

lapply does not coerce to a vector, but sapply does:

> lapply( dates, identity )
[[1]]
[1] "2013-01-01"

[[2]]
[1] "2013-01-02"

> sapply( dates, identity )
[1] 15706 15707

That's because sapply's simplification function coerces output to a vector.

Summary

So: If you have a Date object and want to return a non-Date object, you can use lapply or sapply. If you have a non-Date object, and want to return a Date object, you can use a for loop or lapply. If you have a Date object and want to return a Date object, use lapply.

Resources for learning more

If you want to dig deeper into vectors, you can start with John Cook's notes, continue with the R Inferno, and continue with SDA.

Print a date range in a loop with correctly formatted dates

Try:

for (i in as.list(seq(as.Date('2020-04-02'), as.Date('2020-04-30'), by = 'day'))) {
print(i)
}

I don't know why this is necessary, but if you run

for (i in Sys.Date()) {browser();print(i);}
# Called from: top level
# Browse[1]>
debug at #1: print(i)
# Browse[1]>
i
# [1] 18709

you'll see that i is being converted to numeric in the for (.) portion. The as.list helps preserve that class.

Why i am getting error while I am looping dates?

Here are two ways :

  1. Change the date from number to date in loop.
for (i in Weekly_Close_Price$PRICE_DATE){
print(as.Date(i, origin = '1970-01-01'))
}

  1. Loop over the index.
for (i in seq_along(Weekly_Close_Price$PRICE_DATE)) {
print(Weekly_Close_Price$PRICE_DATE[i])
}

R for loop with in type conversion

As suggested by @flodel , the for loop preserve the Type and not the class:

h <- seq(as.Date('20090101','%Y%m%d'),as.Date('20090105','%Y%m%d'),1)
class(h)
[1] "Date"
> typeof(h)
[1] "double"

Work around :

Use the vectorize version :

print(seq(as.Date('20090101','%Y%m%d'),as.Date('20090105','%Y%m%d'),1 ))

or loop over the sequence indices and retrieve the date with [:

for (i in seq_along(h)) {
dt <- h[i]
print(dt)
}


[1] "2009-01-01"
[1] "2009-01-02"
[1] "2009-01-03"
[1] "2009-01-04"
[1] "2009-01-05"

Converting date in For Loop in R - origin must be supplied

The for is creating d as numeric. Here are two approaches.

Below the comments were removed and only the code lines marked ## have been changed.

1) list Use a list like this:

dates <- seq(as.Date("1987-03-29"), as.Date("1991-12-31"), by=1)

for (d in as.list(dates)) { ##
year <- strftime(d, "%Y")
print(year)
}

2) as.Date or convert d back to "Date" class.

dates <- seq(as.Date("1987-03-29"), as.Date("1991-12-31"), by=1)

for (d in dates) {
year <- strftime(as.Date(d, origin = "1970-01-01"), "%Y") ##
print(year)
}

Retrieving date from sequence does not give the value

Your date values are converted to numeric in for() function to use them as index values.

Instead you can use seq_along() to get index values and then print mySeq[i].

for(i in seq_along(mySeq)) {print(mySeq[i])}

How to avoid R converting dates to numeric automatically?

The for loop coerces the sequence to vector, unless it is vector, list, or some other things. date is not a vector, and there is no such thing as vector of dates. So you need as.list to protect it from coercion to vector:

for (d in as.list(date)) print(d)


Related Topics



Leave a reply



Submit