可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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"
回答1:
?"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
回答2:
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])
}
回答3:
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.
回答4:
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.
回答5:
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.
回答6:
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 ) )
}