使用 seq() 创建常规的日期时间序列 (POSIXct)

发布于 2024-12-27 14:39:16 字数 434 浏览 2 评论 0原文

我的目标是创建一个 POSIXct 时间戳向量,给定开始、结束和增量(15 分钟、1 小时、1 天)。我希望我可以使用 seq 来实现此目的,但我在数字和 POSIXct 表示之间进行转换时遇到问题:

now <- Sys.time()
now
# [1] "2012-01-19 10:30:39 CET"
as.POSIXct(as.double(now), origin="1970-01-01", tz="CET")
# [1] "2012-01-19 09:30:39 CET"
as.POSIXct(as.double(now), origin=as.POSIXct("1970-01-01", tz="CET"), tz="CET")
# [1] "2012-01-19 09:30:39 CET"

在此转换过程中丢失了一个小时。我做错了什么?

My goal is to create a vector of POSIXct time stamps given a start, an end and a delta (15min, 1hour, 1day). I hoped I could use seq for this, but I have a problem converting between the numeric and POSIXct representation:

now <- Sys.time()
now
# [1] "2012-01-19 10:30:39 CET"
as.POSIXct(as.double(now), origin="1970-01-01", tz="CET")
# [1] "2012-01-19 09:30:39 CET"
as.POSIXct(as.double(now), origin=as.POSIXct("1970-01-01", tz="CET"), tz="CET")
# [1] "2012-01-19 09:30:39 CET"

One hour gets lost during this conversion. What am I doing wrong?

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

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

发布评论

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

评论(6

慈悲佛祖 2025-01-03 14:39:16

"POSIXt" 类的对象有一个 seq() 方法,该类是 "POSIXlt"" 的超类POSIXct" 类。因此,您不需要进行任何转换。

> now <- Sys.time()
> tseq <- seq(from = now, length.out = 100, by = "mins")
> length(tseq)
[1] 100
> head(tseq)
[1] "2012-01-19 10:52:38 GMT" "2012-01-19 10:53:38 GMT"
[3] "2012-01-19 10:54:38 GMT" "2012-01-19 10:55:38 GMT"
[5] "2012-01-19 10:56:38 GMT" "2012-01-19 10:57:38 GMT"

There is a seq() method for objects of class "POSIXt" which is the super class of the "POSIXlt" and "POSIXct" classes. As such you don't need to do any conversion.

> now <- Sys.time()
> tseq <- seq(from = now, length.out = 100, by = "mins")
> length(tseq)
[1] 100
> head(tseq)
[1] "2012-01-19 10:52:38 GMT" "2012-01-19 10:53:38 GMT"
[3] "2012-01-19 10:54:38 GMT" "2012-01-19 10:55:38 GMT"
[5] "2012-01-19 10:56:38 GMT" "2012-01-19 10:57:38 GMT"
本宫微胖 2025-01-03 14:39:16

您必须注意,当从 POSIXct 转换为数字时,R 会考虑时区,但始终从 GMT 原点开始计数:

> xgmt <- as.POSIXct('2011-01-01 14:00:00',tz='GMT')
> xest <- as.POSIXct('2011-01-01 14:00:00',tz='EST')
> (as.numeric(xgmt) - as.numeric(xest)) / 3600
[1] -5

如您所见,EST 时间被认为比 GMT 时间早五个小时,这是两个时区之间的时差。这是内部保存的值。

as.POSIXCT() 函数只是添加一个包含时区的属性。它不会改变该值,因此您会得到以 GMT 时间显示的时间,但有一个属性告诉它是 EST。这也意味着,一旦从 POSIXct 转换为数字时间,您就应该将数据视为 GMT 时间。 (它比这要复杂得多,但这是总体思路)。因此,您必须按如下方式计算偏移量:

> nest <- as.numeric(xest)
> origin <- as.POSIXct('1970-01-01 00:00:00',tz='EST')
> offset <- as.numeric(origin)
> as.POSIXct(nest-offset,origin=origin)
[1] "2011-01-01 14:00:00 EST"

无论您所在区域的时区如何(在我的情况下,实际上是 CET),这都有效。另请注意,时区数据的行为在系统之间可能有所不同。

You have to be aware that when converting from POSIXct to numeric, R takes the timezone into account but always starts counting from a GMT origin :

> xgmt <- as.POSIXct('2011-01-01 14:00:00',tz='GMT')
> xest <- as.POSIXct('2011-01-01 14:00:00',tz='EST')
> (as.numeric(xgmt) - as.numeric(xest)) / 3600
[1] -5

As you see, the time in EST is conceived to be five hours earlier than the time in GMT, which is the time difference between both timezones. It's that value that is saved internally.

The as.POSIXCT() function just adds an attribute containing the timezone. It doesn't alter the value, so you get the time presented in GMT time, but with an attribute telling it is EST. This also means that once you go from POSIXct to numeric, you should treat your data as if it's GMT time. (It's a whole lot more complex than that, but it's the general idea). So you have to calculate the offset as follows:

> nest <- as.numeric(xest)
> origin <- as.POSIXct('1970-01-01 00:00:00',tz='EST')
> offset <- as.numeric(origin)
> as.POSIXct(nest-offset,origin=origin)
[1] "2011-01-01 14:00:00 EST"

This works whatever the timezone is in your locale (in my case, that's actually CET). Also note that behaviour of timezone data can differ between systems.

莳間冲淡了誓言ζ 2025-01-03 14:39:16

这些时区问题总是很棘手,但我认为问题在于您的原产地是在错误的时区中计算的(因为字符串仅指定日期)。

尝试使用origin <- now - as.numeric(now)

或者,使用lubridate::origin,它是字符串“1970-01-01 UTC”


完整的解决方案,再次使用lubridate

start <- now()
seq(start, start + days(3), by = "15 min")

These time zone issues are always fiddly, but I think the problem is that your origin is being calculated in the wrong time zone (since the string only specifies the date).

Try using origin <- now - as.numeric(now).

Alternatively, use lubridate::origin, which is the string "1970-01-01 UTC".


A full solution, again using lubridate.

start <- now()
seq(start, start + days(3), by = "15 min")
椒妓 2025-01-03 14:39:16

我没有解决您的问题,但我确实有另一种方法来创建 POSIXct 对象的向量。例如,如果您想从现在开始创建一个包含 1000 个时间戳的向量,delta_t 为 15 分钟:

now = Sys.time()
dt = 15 * 60 # in seconds
timestamps = now + seq(0, 1000) * dt
> head(timestamps)
[1] "2012-01-19 11:17:46 CET" "2012-01-19 11:32:46 CET"
[3] "2012-01-19 11:47:46 CET" "2012-01-19 12:02:46 CET"
[5] "2012-01-19 12:17:46 CET" "2012-01-19 12:32:46 CET"

技巧是您可以将秒向量添加到 POSIXct目的。

I do not have an answer to your problem, but I do have an alternative way of creating vectors of POSIXct objects. If, for example, you want to create a vector of 1000 timestamps from now with a delta_t of 15 minutes:

now = Sys.time()
dt = 15 * 60 # in seconds
timestamps = now + seq(0, 1000) * dt
> head(timestamps)
[1] "2012-01-19 11:17:46 CET" "2012-01-19 11:32:46 CET"
[3] "2012-01-19 11:47:46 CET" "2012-01-19 12:02:46 CET"
[5] "2012-01-19 12:17:46 CET" "2012-01-19 12:32:46 CET"

The trick is you can add a vector of seconds to a POSIXct object.

北斗星光 2025-01-03 14:39:16

使用 seq.POSIXt 的替代方法是 xts::timeBasedSeq,它允许您将序列指定为字符串:

library(xts)
now <- Sys.time()
timeBasedSeq(paste("2012-01-01/",format(now),"/H",sep=""))  # Hourly steps
timeBasedSeq(paste("2012-01-01/",format(now),"/d",sep=""))  # Daily steps

An alternative to using seq.POSIXt is xts::timeBasedSeq, which allows you to specify the sequence as a string:

library(xts)
now <- Sys.time()
timeBasedSeq(paste("2012-01-01/",format(now),"/H",sep=""))  # Hourly steps
timeBasedSeq(paste("2012-01-01/",format(now),"/d",sep=""))  # Daily steps
爱本泡沫多脆弱 2025-01-03 14:39:16

您需要使用 seq(from=start,to=end, by=step)。请注意,在步骤中,您可以使用“天”或一个整数来定义从一个项目到另一个项目经过的秒数。

You need to use seq(from=start,to=end, by=step). Note that in step you can either use "days" or an integer defining how many seconds elapse from item to item.

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