2013-02-22 58 views
6

我正在使用從Teradata導出的.csv數據。幾列最初是帶時區的時間戳,所以在R中加載.csv之後,我想將這些列(它們作爲字符串加載)轉換爲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可能會更好。

如果這是不可能的,是否有人有一個光滑/靈活的函數用於將字符串(各種格式)轉換爲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 2016-07-09 23:22:06