2013-02-22 22 views
6

Tôi đang làm việc với dữ liệu .csv được xuất từ ​​Teradata. Một số cột ban đầu là dấu thời gian với múi giờ, vì vậy sau khi tải .csv trong R, tôi muốn chuyển đổi các cột này (được nạp dưới dạng chuỗi) thành POSIXlt hoặc POSIXct. Tôi đang sử dụng strptime, nhưng định dạng của múi giờ từ tệp .csv không khớp với những gì strptime đang mong đợi. Ví dụ: nó mong đợi -0400 nhưng .csv có định dạng -04:00 trong đó dấu hai chấm tách biệt giờ và phút.Sử dụng strptime% z với định dạng múi giờ đặc biệt

Tôi có thể loại bỏ dấu hai chấm, nhưng đây là bước bổ sung và biến chứng tôi muốn tránh nếu có thể. Có cách nào để yêu cầu strptime sử dụng định dạng khác cho múi giờ (%z) không?

Dưới đây là một ví dụ:

## 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" 

Vì vậy, tôi đang tìm cách để đạt được kết quả cuối cùng này sử dụng một cái gì đó giống như strptime(x,"%Y-%m-%d %H:%M:%OS%zz"), nơi %zz là một biểu thức tùy chỉnh cho múi giờ công nhận định dạng -04:00. Hoặc %zH:%zM có thể còn tốt hơn nữa.

Nếu điều này là không thể, có ai có chức năng trơn/linh hoạt để chuyển đổi chuỗi (các định dạng khác nhau) thành ngày cho nhiều cột của dữ liệu.frame/data.table không?

Trả lời

3

Hóa ra lubridate có thể xử lý định dạng này:

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

Hoặc, để hiển thị trong múi giờ địa phương:

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

Đối với linh hoạt hơn (vẫn còn sử dụng lubridate):

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

Đối với tốc độ nhanh hơn (trong số lubridate tùy chọn):

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

Thời gian:

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

Tôi vừa xem qua câu hỏi này đang cố gắng đạt được điều tương tự.

Điều duy nhất tôi tìm thấy để sửa chữa nó là sử dụng regex để loại bỏ dấu hai chấm, như bạn đã đề cập. Bạn có thể thắt chặt regex một chút để tránh mắc lỗi trong việc thay thế.

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

Đó là năm 2016 và trên thế giới vẫn còn phải đối phó với điều này ... – sehe

Các vấn đề liên quan