Как создать коэффициент день / ночь из переменной POSIXct - PullRequest
0 голосов
/ 12 января 2019

У меня есть таблица данных со столбцом даты / времени POSIXct. Я хотел бы создать столбец, который определяет «день» или «ночь» на основе метки времени POSIXct. День определяется по местному времени с 05:30:00 до 20:00.

Я попытался создать новую переменную, используя оператор ifelse, основанный на столбце «время суток», созданном с использованием strptime, но в итоге получил странные результаты.

Вот простой пример - настройка его в качестве таблицы данных, соответствующей моему реальному набору данных.

library(data.table)

SightingTime = c("2017-07-31 09:56:27 UTC", "2017-07-31 10:36:30 UTC", "2017-08-01 00:07:20 UTC","2017-08-01 01:31:00 UTC", "2017-08-01 10:38:23 UTC", "2017-08-01 21:13:06 UTC", "2017-08-02 15:13:30 UTC", "2017-08-02 18:05:28 UTC", "2017-08-02 21:04:08 UTC")
x=data.table(SightingTime)

Сначала я извлекаю время дня из переменной даты / времени - я хочу это по местному времени, потому что я укажу восход / закат по местному времени.

x$TOD = strftime(x$SightingTime, format="%H:%M:S",tz="America/Halifax")

Я не уверен, почему новая переменная TOD все еще находится в UTC, хотя я указываю другой часовой пояс.

Затем попытайтесь создать новую переменную с помощью оператора ifelse

x$daynight = with(x,
           ifelse(TOD > 05:30:00 & TOD < 20:00:00, "Day", "Night")) 

Я явно ошибся в этом бите, так как я получаю предупреждающие сообщения И результаты в столбце «день / ночь» не имеют смысла.

Я надеюсь, что-то вроде этого.

             SightingTime      TOD daynight
1: 2017-07-31 09:56:27 UTC 06:56:27    Day
2: 2017-07-31 10:36:30 UTC 07:36:30    Day
3: 2017-08-01 00:07:20 UTC 21:07:20    Night
4: 2017-08-01 01:31:00 UTC 22:31:00    Night
5: 2017-08-01 10:38:23 UTC 07:38:23    Day
6: 2017-08-01 21:13:06 UTC 08:13:06    Day
7: 2017-08-02 15:13:30 UTC 12:13:30    Day
8: 2017-08-02 18:05:28 UTC 15:05:28    Day
9: 2017-08-02 21:04:08 UTC 18:04:08    Day

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Другой подход может заключаться в том, чтобы сначала сгенерировать последовательность времени с 05:30:00 до 20:00:00 по секундам, а затем сравнить, лежит ли «TOD» в этом интервале:

time <- strftime(seq(from=as.POSIXct("1992-5-7 05:30:00", "%Y-%m-%d %H:%M:%S", tz = "America/Halifax"), 
                     to=as.POSIXct("1992-5-7 20:00:00", "%Y-%m-%d %H:%M:%S", tz = "America/Halifax"),
                     by= "secs"), 
                 format="%H:%M:%S", tz = "America/Halifax")

x$SightingTime <- as.POSIXct(x$SightingTime, format = "%Y-%m-%d %H:%M:%S", tz = "UTC")
x$TOD <- strftime(x$SightingTime, format="%H:%M:%S", tz="America/Halifax")
x$daynight <- with(x, ifelse(TOD %in% time, "Day", "Night"))

          SightingTime      TOD daynight
1: 2017-07-31 09:56:27 06:56:27      Day
2: 2017-07-31 10:36:30 07:36:30      Day
3: 2017-08-01 00:07:20 21:07:20    Night
4: 2017-08-01 01:31:00 22:31:00    Night
5: 2017-08-01 10:38:23 07:38:23      Day
6: 2017-08-01 21:13:06 18:13:06      Day
7: 2017-08-02 15:13:30 12:13:30      Day
8: 2017-08-02 18:05:28 15:05:28      Day
9: 2017-08-02 21:04:08 18:04:08      Day

И вы можете переписать его в tidyverse дружественный код:

x %>%
 mutate(SightingTime = as.POSIXct(SightingTime, format = "%Y-%m-%d %H:%M:%S", tz = "UTC"),
        TOD = strftime(SightingTime, format="%H:%M:%S", tz="America/Halifax"),
        daynight = ifelse(TOD %in% time, "Day", "Night"))

         SightingTime      TOD daynight
1 2017-07-31 09:56:27 06:56:27      Day
2 2017-07-31 10:36:30 07:36:30      Day
3 2017-08-01 00:07:20 21:07:20    Night
4 2017-08-01 01:31:00 22:31:00    Night
5 2017-08-01 10:38:23 07:38:23      Day
6 2017-08-01 21:13:06 18:13:06      Day
7 2017-08-02 15:13:30 12:13:30      Day
8 2017-08-02 18:05:28 15:05:28      Day
9 2017-08-02 21:04:08 18:04:08      Day
0 голосов
/ 13 января 2019

Данные

library(data.table)

SightingTime_chr = c("2017-07-31 09:56:27 UTC", "2017-07-31 10:36:30 UTC", "2017-08-01 00:07:20 UTC","2017-08-01 01:31:00 UTC", "2017-08-01 10:38:23 UTC", "2017-08-01 21:13:06 UTC", "2017-08-02 15:13:30 UTC", "2017-08-02 18:05:28 UTC", "2017-08-02 21:04:08 UTC")
x = data.table(SightingTime_chr)

код

Несколько вещей были не совсем верны с вашим преобразованием в datetime (формат, например):

x$SightingTime = as.POSIXct(x$SightingTime_chr, format = "%Y-%m-%d %H:%M:%S", tz = "UTC")
attributes(x$SightingTime)$tzone <- "America/Halifax"

Сначала я преобразовал бы строки символов в POSIXct, а затем преобразовал в часовой пояс Америки / Галифакса, поскольку первоначальный вектор, похоже, находится в дате и времени UTC (пропустите второй шаг, если я # m ошибаюсь).

x$TOD <- format(x$SightingTime, format="%H%M%S")

x$daynight = with(x, ifelse(TOD > "053000" & TOD < "200000", "Day", "Night")) 

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

x$daynight
[1] "Day"   "Day"   "Night" "Night" "Day"   "Day"   "Day"   "Day"   "Day" 

Теперь результаты отображаются правильно.

Альтернативный

Из этого ответа мы можем получить элегантное решение, если мы хотим больше, чем просто ночь / день:

nightday <- function(datetime) {
  paste(
    c("Night", "Morning", "Afternoon", "Evening", "Night")[
      cut(as.numeric(format(datetime, "%H%M")), c(0, 530, 1100, 1700 ,2000, 2359))
      ]
  )
}
nightday(x$SightingTime)
[1] "Morning"   "Morning"   "Night"     "Night"     "Morning"   "Evening"   "Afternoon" "Afternoon" "Evening"  
...