2013-02-22 6 views
6

Ich arbeite mit .csv Daten, die aus Teradata exportiert wurde. Mehrere Spalten waren ursprünglich Zeitstempel mit Zeitzonen, daher möchte ich nach dem Laden der .csv in R diese Spalten (die als Strings geladen sind) in POSIXlt oder POSIXct konvertieren. Ich benutze strptime, aber das Format der Zeitzone aus der .csv-Datei stimmt nicht überein, was strptime erwartet. Zum Beispiel erwartet es aber die .csv hat das Format -04:00 wo ein Doppelpunkt die Stunden und Minuten trennt.Verwenden von strptime% z mit speziellen Zeitzone Format

Ich kann den Doppelpunkt entfernen, aber das ist ein zusätzlicher Schritt und Komplikation, die ich vermeiden möchte, wenn möglich. Gibt es eine Möglichkeit, strptime mitzuteilen, ein anderes Format für die Zeitzone zu verwenden (%z)? Hier

ein Beispiel:

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

Also ich bin auf der Suche dieses letzte Ergebnis zu erzielen, so etwas wie strptime(x,"%Y-%m-%d %H:%M:%OS%zz") verwenden, wo %zz ist ein Brauch Ausdruck für die Zeitzone, die das -04:00 Format erkennt. Oder %zH:%zM könnte noch besser sein.

Wenn dies nicht möglich ist, hat jemand eine glatte/flexible Funktion zum Konvertieren von Zeichenfolgen (verschiedener Formate) in Daten für mehrere Spalten einer data.frame/data.table?

Antwort

3

Es stellt sich heraus lubridate dieses Format verarbeiten kann:

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

Oder in der lokalen Zeitzone anzuzeigen:

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

Für mehr Flexibilität (noch lubridate verwenden):

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

Für eine schnellere Geschwindigkeit (unter lubridate Optionen):

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

Timings:

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

Ich bin gerade auf diese Frage gestoßen, um das Gleiche zu erreichen.

Das einzige, was ich gefunden habe, um es zu beheben, ist die Verwendung von Regex, um den Doppelpunkt zu entfernen, wie Sie erwähnt haben. Sie können die Regex ein wenig straffen, um Fehler beim Ersetzen zu vermeiden.

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

Es ist 2016 und die Welt, die sich immer noch damit zu beschäftigen ... – sehe