Подтвердить что ты не робот

Seq() для POSIXct

Моя цель - создать вектор временных меток 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"

Один час теряется во время этого преобразования. Что я делаю неправильно?

4b9b3361

Ответ 1

Существует метод seq() для объектов класса "POSIXt", который является суперклассом классов "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"

Ответ 2

Вы должны знать, что при преобразовании с 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 к числовому, вы должны обрабатывать свои данные так, как если бы это время по Гринвичу. (Это намного сложнее, чем это, но это общая идея). Поэтому вам нужно рассчитать смещение следующим образом:

> 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). Также обратите внимание, что поведение данных часового пояса может различаться между системами.

Ответ 3

Эти проблемы с часовым поясом всегда неудобны, но я думаю, что проблема заключается в том, что ваше происхождение вычисляется в неправильном часовом поясе (поскольку строка указывает только дату).

Попробуйте использовать origin <- now - as.numeric(now).

В качестве альтернативы используйте lubridate::origin, которая является строкой "1970-01-01 UTC".


Полное решение, снова используя lubridate.

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

Ответ 4

Альтернативой использованию 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

Ответ 5

У меня нет ответа на вашу проблему, но у меня есть альтернативный способ создания векторов объектов 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.

Ответ 6

Вам нужно использовать seq (from = start, to = end, by = step). Обратите внимание, что на шаге вы можете либо использовать "дни", либо целое число, определяющее, сколько секунд прошло от элемента к элементу.