2013-02-22 7 views
6

Я работаю с CSV-данными, которые были экспортированы из Teradata. Несколько столбцов были первоначально временными метками с часами, поэтому после загрузки .csv в R я хотел бы преобразовать эти столбцы (которые загружаются как строки) в POSIXlt или POSIXct. Я использую strptime, но формат часового пояса из CSV-файла не соответствует ожидаемому strptime. Например, он ожидает -0400, но CSV имеет формат -04:00, где двоеточие отделяет часы и минуты.Использование strptime% z со специальным форматом часового пояса

Я могу удалить двоеточие, но это дополнительный шаг и осложнение, которое я хотел бы избежать, если это возможно. Есть ли способ сообщить strptime использовать другой формат для часового пояса (%z)?

Вот пример:

## Example data: 
x <- c("2011-10-12 22:17:13.860746-04:00", "2011-10-12 22:17:13.860746+00:00") 
format <- "%Y-%m-%d %H:%M:%OS%z" 

## Doesn't work: 
strptime(x,format) 
## [1] NA NA 

## Ignores the timezone: 
as.POSIXct(x) 
## [1] "2011-10-12 22:17:13 EDT" "2011-10-12 22:17:13 EDT" 

## Remove the last colon: 
x2 <- gsub("(.*):", "\\1", x) 
x2 
## [1] "2011-10-12 22:17:13.860746-0400" "2011-10-12 22:17:13.860746+0000" 

## This works, but requires extra processing (removing the colon) 
strptime(x2,format) 
## [1] "2011-10-12 22:17:13" "2011-10-12 18:17:13" 

Поэтому я ищу, чтобы достичь этого последнего результата, используя что-то вроде strptime(x,"%Y-%m-%d %H:%M:%OS%zz"), где %zz обычай выражение для часового пояса, который распознает формат -04:00. Или %zH:%zM может быть даже лучше.

Если это невозможно, может ли кто-нибудь использовать функцию slick/flexible для преобразования строк (различных форматов) в даты для нескольких столбцов data.frame/data.table?

ответ

3

Оказывается lubridate может обрабатывать этот формат:

library(lubridate) 
ymd_hms(x) 
## [1] "2011-10-13 02:17:13 UTC" "2011-10-12 22:17:13 UTC" 

Или, чтобы отобразить в локальной временной зоне:

with_tz(ymd_hms(x)) 
## [1] "2011-10-12 22:17:13 EDT" "2011-10-12 18:17:13 EDT" 

Для большей гибкости (до сих пор используют lubridate):

parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z") 

Для более быстрой скорости (среди lubridate вариантов):

lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO") 

Тайминги:

microbenchmark(
    ymd_hms(x), 
    parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z"), 
    lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO"), 
    strptime(gsub("(.*):", "\\1", x), format) 
) 

## Unit: microseconds 
##            expr  min  lq  mean median  uq  max neval 
##           ymd_hms(x) 1523.819 1578.495 1715.14577 1629.5385 1744.3695 2850.393 100 
##   parse_date_time(x, "%Y-%m-%d %H:%M:%OS%z") 1108.676 1150.633 1273.77301 1190.3315 1264.8050 5947.204 100 
## lubridate:::.strptime(x, "%Y-%m-%d %H:%M:%OS%OO") 89.838 103.390 112.45338 107.8425 115.2265 216.512 100 
##  strptime(gsub("(.*):", "\\\\1", x), format) 46.716 58.294 71.90934 69.9415 86.5860 105.044 100 
2

Я только что наткнулся на этот вопрос, пытаясь достичь того же.

Единственное, что я нашел, чтобы исправить это - использовать регулярное выражение для удаления двоеточия, как вы уже упоминали. Вы можете немного затянуть регулярное выражение, чтобы избежать ошибок при замене.

x2 <- gsub('^([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]+[+-][0-9]{2}):([0-9]{2})$', 
      '\\1\\2', 
      x) 
# [1] "2011-10-12 22:17:13.860746-0400" "2011-10-12 22:17:13.860746+0000" 
+4

Это 2016 и мир по-прежнему приходится иметь дело с этим ... – sehe