循环 Date 或 POSIXct 对象会产生数字迭代器

发布于 2024-12-25 06:49:53 字数 454 浏览 3 评论 0原文

为什么迭代 DatePOSIXct 对象会产生 numeric?例如:

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

POSIXct 也会发生同样的情况:

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

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"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

桃气十足 2025-01-01 06:49:53

?"for" 表示 seqin 之后的部分)是“[A]n 表达式计算一个向量(包括一个列表和表达式)或配对列表或“NULL””。

因此,您的 Date 向量被强制转换为 numeric,因为 Date 对象并不是严格意义上的向量:

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

对于 POSIXct 也是如此。代码>向量:

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

?"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
星星的轨迹 2025-01-01 06:49:53

循环天(字符串):

     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])
      }

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])
      }
胡渣熟男 2025-01-01 06:49:53

使用 for 循环时,您没有选择正确的函数来应用于 Date 向量。更好的方法是为几乎每个循环的日期或因素包装 seq_along 。然后你将做两件事:a) 设置它,以便你期望索引从 1 开始,b) 防止零长度向量发生奇怪的事情。我还认为最好将它与因子一起使用,for 循环会将其转换为字符向量。

参考约书亚的答案(这当然是正确且有帮助的),我认为 is.vector 函数有点标签错误或者可能只是被误解了。更准确的说法是 hasNoAttributesOtherThanName。大多数人认为“矢量”的属性是使用 is.atomicDate 进行测试的,而 POSIXct 对象将返回 TRUE 从那个测试中。

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.

亢潮 2025-01-01 06:49:53

看来实现 for 循环的 C 函数不会复制向量的任何属性。这还包括 class 属性,它应该使 i 看起来是一个 Date 对象。

您可以研究do_for(SEXP, SEXP, SEXP, SEXP)函数的源代码(R的for调用的函数)此处

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.

〆凄凉。 2025-01-01 06:49:53

这是一个老问题,但我是 R 新手,也遇到了同样的问题。由于我的问题将并行处理,因此我使用了 foreach 和与正常的 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"
...

由于我对大多数 R 的内部事物没有经验,因此我不知道为什么 foreach 最终有一种不同的行为,但对我的目的有用,希望对别人。

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.

平定天下 2025-01-01 06:49:53

对日期对象的任何数值运算通常都会返回天数。在此,您要求它为您提供距该纪元的天数。 14245 是 1970-01-01 至 2009-01-01 之间的天数

?日期:

日期表示为数量
自 1970 年 1 月 1 日以来的天数,负数
较早日期的值。他们是
始终按照以下规则打印
现在的公历,甚至
虽然那个日历没有被使用
很久以前(1752 年通过)
英国及其殖民地)。

日期应该是
一个整数,但这不是强制的
在内部表示中。
当以下情况时,小数天数将被忽略:
印刷。可以生产
通过平均法计算的小数天数或
通过添加或减去(参见
行动日期)。

尝试添加 print(day) 来看看我的意思。

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

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 ) )
}
短叹 2025-01-01 06:49:53

本身不是一个解决方案,但当您想要检查循环中的日期时,这是一个有用的技巧:

for( i.date in as.character(Sys.Date()) ){
cat(粘贴("日期:", i.date, "\n"))
只需

事先将其转换为字符即可。大多数过滤器不会打扰。

Not a solution per-se, but a useful trick when you want to check the dates in a loop:

for( i.date in as.character(Sys.Date()) ){
cat(paste("Date:", i.date, "\n"))
}

just transform it as character beforehand. Most filters won't bother.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文