Преобразование локальных дат и времени из большого набора данных с несколькими часовыми поясами в UTC - PullRequest
1 голос
/ 02 июля 2019

Мне дали огромный набор данных, который содержит поля широты, долготы, локальной даты и местного времени. Я пытаюсь организовать эту информацию в поле времени UTC ISO. У меня проблема с моим кодом, потому что я не знаю, как использовать as.POSIXct (), когда в данных есть несколько часовых поясов. Всякий раз, когда я пытаюсь использовать массив или цикл в части tz =, я получаю сообщение об ошибке.

Я использовал функцию tz_lookup_coords () из пакета lutz для определения часового пояса каждой строки во фрейме данных. Я также смог отфильтровать свои данные в одном часовом поясе и успешно использовал функции as.POSIXct () и format () для получения времени UTC. Однако я хотел бы, чтобы более элегантное решение применял один код ко всему набору данных.

sample<- data.frame(
  "localDate" = c("2015-04-20","2016-07-17","2015-08-06"), 
  "localTime" = c("14:00", "14:46", NA ), 
  "timeZone" = c("Pacific/Pago_Pago", NA , "Pacific/Honolulu")
)

# Change times from local to UTC
sample$localDateTime <- paste(sample$localDate, sample$localTime, sep = " ")
for (i in 1:nrow(sample)) {
  sample[i,]$localDateTime <- as.POSIXct(sample[i,]$localDateTime, tz= sample[i,]$timeZone, "%Y-%m-%d %H:%M")
}
sample$eventDate <- format(sample$localDateTime, tz= "UTC", usetz = TRUE)

Когда я вхожу в один часовой пояс, такой как "Pacific / Honolulu", код прекрасно работает, но он будет обрабатывать каждую строку, как если бы она находилась в одном часовом поясе.

> sample
   localDate localTime          timeZone    localDateTime               eventDate
1 2015-04-20     14:00 Pacific/Pago_Pago 2015-04-20 14:00 2015-04-21 00:00:00 UTC
2 2016-07-17     14:46    Pacific/Saipan 2016-07-17 14:46 2016-07-18 00:46:00 UTC
3 2015-08-06     10:35  Pacific/Honolulu 2015-08-06 10:35 2015-08-06 20:35:00 UTC

Если я попытаюсь использовать что-либо кроме символьной строки в кавычках для части функции tz =, я получу этот код:

Error in strptime(x, format, tz = tz) : invalid 'tz' value

Ответы [ 2 ]

0 голосов
/ 02 июля 2019

Ошибка связана с тем, что столбец timeZone является фактором вместо символьного вектора, используйте stringsAsFactors = FALSE при определении data.frame, чтобы указать timeZone в качестве символьного столбца. Вы также можете избежать циклов, используя векторизованные функции из пакета lubridate:

library(lubridate)

df <- data.frame(
    "localDate" = c("2015-04-20","2016-07-17","2015-08-06"), 
    "localTime" = c("14:00", "14:46", "10:35"), 
    "timeZone" = c("Pacific/Pago_Pago", "Pacific/Saipan", "Pacific/Honolulu"),
    stringsAsFactors = FALSE
)

df$eventDate <- force_tzs(ymd_hm(with(df, paste(localDate, localTime))), tzones = df$timeZone)

df
#>    localDate localTime          timeZone           eventDate
#> 1 2015-04-20     14:00 Pacific/Pago_Pago 2015-04-21 01:00:00
#> 2 2016-07-17     14:46    Pacific/Saipan 2016-07-17 04:46:00
#> 3 2015-08-06     10:35  Pacific/Honolulu 2015-08-06 20:35:00

Редактировать: в случае отсутствия значений проверить для каждой строки, можно ли их преобразовать и, если нет, вернуть NA. Ниже приведен пример решения с использованием базы R:

df <- data.frame(
    "localDate" = c("2015-04-20","2016-07-17","2015-08-06", "2019-01-01", "2019-01-01"), 
    "localTime" = c("14:00", "14:46", "10:35", NA, "00:00"), 
    "timeZone" = c("Pacific/Pago_Pago", "Pacific/Saipan", "Pacific/Honolulu", 
        "Pacific/Honolulu", NA),
    stringsAsFactors = FALSE
)

df$eventDate <- apply(df, 1, function(row) {     
      ifelse(any(is.na(row)), NA_character_,
          format(as.POSIXct(paste(row["localDate"], row["localTime"]), "%Y-%m-%d %H:%M",
              tz = row["timeZone"]), tz = "UTC", usetz = TRUE)
      )
    })
df   
#>    localDate localTime          timeZone               eventDate
#> 1 2015-04-20     14:00 Pacific/Pago_Pago 2015-04-21 01:00:00 UTC
#> 2 2016-07-17     14:46    Pacific/Saipan 2016-07-17 04:46:00 UTC
#> 3 2015-08-06     10:35  Pacific/Honolulu 2015-08-06 20:35:00 UTC
#> 4 2019-01-01      <NA>  Pacific/Honolulu                    <NA>
#> 5 2019-01-01     00:00              <NA>                    <NA>
0 голосов
/ 02 июля 2019
library(lubridate)

sample <- 
  data.frame(
     "localDate" = c("2015-04-20","2016-07-17","2015-08-06"), 
     "localTime" = c("14:00", "14:46", "10:35"), 
     "timeZone" = c("Pacific/Pago_Pago", "Pacific/Saipan", "Pacific/Honolulu")
   )

sample$localDateTime <- 
  paste(sample$localDate, sample$localTime, sep = " ")

list <- 
  list()

for (i in 1:nrow(sample)){
     list[[i]] <- 
       ymd_hm(sample$localDateTime[i], 
              tz = as.character(sample$timeZone[i]))
   }

list   

R> list
[[1]]
[1] "2015-04-20 14:00:00 SST"

[[2]]
[1] "2016-07-17 14:46:00 ChST"

[[3]]
[1] "2015-08-06 10:35:00 HST"
...