2012-05-22 7 views
45

Angenommen, ich habe folgende data.framefooExtrakt Stunden und Sekunden von POSIXct für Zwecke in R Plotten

  start.time duration 
1 2012-02-06 15:47:00  1 
2 2012-02-06 15:02:00  2 
3 2012-02-22 10:08:00  3 
4 2012-02-22 09:32:00  4 
5 2012-03-21 13:47:00  5 

Und class(foo$start.time) kehren

[1] "POSIXct" "POSIXt" 

Ich mag würde ein Grundstück von foo$duration v erstellen. foo$start.time. In meinem Szenario interessiert mich nur die Tageszeit und nicht der tatsächliche Tag des Jahres. Wie wird man die Uhrzeit als Stunden: Sekunden aus POSIXct Klasse des Vektors extrahieren?

+1

die Bibliotheken 'lubridate' und' zoo' könnten für Sie hilfreich sein. aber in der Basis R, 'format (foo $ start.time, format = '% H: M')'. – Justin

+0

Danke. Ein Problem mit 'format (foo $ start.time, format = '% H: M') ist, dass die Ausgabe im Zeichenformat ist. Ich möchte, dass die Ausgabe in irgendeiner Art von numerischem Format ist, so dass sie als x-Achse eines Plots verwendet werden kann. – andrewj

+1

Es gibt viele Möglichkeiten. Wieder würde ich Sie auf "lubridate" oder [this post] hinweisen (http://stackoverflow.com/questions/7655514/how-do-i-plot-only-the-time-portion-of-a-timestamp- included-a-date) – Justin

Antwort

39

Dies ist eine gute Frage, und hebt einige der Schwierigkeiten im Umgang mit Daten in R hervor. Das lubridate-Paket ist sehr praktisch, daher stelle ich unten zwei Ansätze vor, einen mit Basis (wie von @ RJ- vorgeschlagen) andere mit Lubridat.

Erstellen Sie die (ersten zwei Reihen), um den Datenrahmen in der ursprünglichen Nachricht:

foo <- data.frame(start.time = c("2012-02-06 15:47:00", 
           "2012-02-06 15:02:00", 
           "2012-02-22 10:08:00"), 
        duration = c(1,2,3)) 

Konvertieren in POSIXct und POSIXt Klasse (zwei Möglichkeiten, dies zu tun)

# using base::strptime 
t.str <- strptime(foo$start.time, "%Y-%m-%d %H:%M:%S") 

# using lubridate::ymd_hms 
library(lubridate) 
t.lub <- ymd_hms(foo$start.time) 

Nun Extrakt Zeit als Dezimalstunden

# using base::format 
h.str <- as.numeric(format(t.str, "%H")) + 
       as.numeric(format(t.str, "%M"))/60 

# using lubridate::hour and lubridate::minute 
h.lub <- hour(t.lub) + minute(t.lub)/60 

zeigen, dass diese Ansätze sind gleich:

identical(h.str, h.lub) 

Dann, eines der oben genannten Ansätze wählen Dezimalzahl Stunde foo$hr zuzuweisen:

foo$hr <- h.str 

# If you prefer, the choice can be made at random: 
foo$hr <- if(runif(1) > 0.5){ h.str } else { h.lub } 

dann zeichnen Sie die ggplot2 Paket mit:

library(ggplot2) 
qplot(foo$hr, foo$duration) +  
             scale_x_datetime(labels = "%S:00") 
+0

Danke für den Vorschlag. Wenn jedoch das obige Diagramm gezeichnet wird, behandelt es jeden Zeitpunkt als eine Bezeichnung oder Kategorie und nicht als eine Zahl. Mit anderen Worten, die Punkte sind auf der x-Achse gleich beabstandet. Vergleichen Sie den Unterschied mit dem folgenden, indem Sie das Original 'foo' nehmen und dann die folgenden' foo $ start.time.numeric <- Stunde (foo $ start.time) + Minute (foo $ start.time)/60 'als' zeichnen mit (foo, qplot (start.time.numeric, duration)) ' – andrewj

+0

@andrewj Ich habe meine Antwort auf diese Adresse aktualisiert –

+1

In Bezug auf das Problem, beschreiben Sie, von diesem Beitrag hier, http: // stackoverflow. com/questions/7655514/how-do-i-plot-nur-die-Zeit-Teil-von-Zeitstempel-einschließlich-ein-Datum, versuchen 'qplot (Stunde (foo $ start.time) + Minute (foo $ start.time)/60, foo $ duration) + scale_x_datetime (Etiketten = Datum_format ("% S: 00")) '. Es sieht so aus, als hätte die Änderung von 'scale_x_datetime' einen' labels' Parameter. – andrewj

14

Sie auf Basis R verlassen konnte:

# Using R 2.14.2 
# The same toy data 
foo <- data.frame(start.time = c("2012-02-06 15:47:00", 
           "2012-02-06 15:02:00", 
           "2012-02-22 10:08:00"), 
        duration = c(1,2,3)) 

Si Wenn die nce-Klasse POSIXct Informationen zu Datum und Uhrzeit strukturiert enthält, können Sie sich auf substr verlassen, um die Zeichen in Zeitpositionen innerhalb des POSIXct-Vektors zu extrahieren. Das heißt, da Sie das Format Ihrer POSIXct wissen (wie wäre es, wenn sie gedruckt vorgelegt werden), können Sie Stunden und Minuten extrahieren:

# Extract hour and minute as a character vector, of the form "%H:%M" 
substr(foo$start.time, 12, 16) 

Und dann ist es zu einem beliebigen Datum einfügen, um es zu POSIXct konvertieren zurück. In dem Beispiel verwende ich den ersten Januar 2012, aber wenn Sie kein Datum angeben und stattdessen format verwenden, verwendet R das aktuelle Datum.

# Store time information as POSIXct, using an arbitrary date 
foo$time <- as.POSIXct(paste("2012-01-01", substr(foo$start.time, 12, 16))) 

Und beide plot und ggplot2 wissen, wie aus der Box mal in POSIXct zu formatieren.

# Plot it using base graphics 
plot(duration~time, data=foo) 

# Plot it using ggplot2 (0.9.2.1) 
library(ggplot2) 
qplot(x=time, y=duration, data=foo) 
5

Dieser Code ist viel schneller als in String konvertieren und zurück in numerischen

time <- c("1979-11-13T08:37:19-0500", "2014-05-13T08:37:19-0400"); 
time.posix <- as.POSIXct(time, format = "%Y-%m-%dT%H:%M:%S%z"); 
time.epoch <- as.vector(unclass(time.posix)); 
time.poslt <- as.POSIXlt(time.posix, tz = "America/New_York"); 
time.hour.new.york <- time.poslt$hour + time.poslt$min/60 + time.poslt$sec/3600; 

> time; 
[1] "1979-11-13T08:37:19-0500" "2014-05-13T08:37:19-0400" 
> time.posix; 
[1] "1979-11-13 15:37:19 IST" "2014-05-13 15:37:19 IDT" 
> time.poslt; 
[1] "1979-11-13 08:37:19 EST" "2014-05-13 08:37:19 EDT" 
> time.epoch; 
[1] 311348239 1399984639 
> time.hour.new.york; 
[1] 8.621944 8.621944 
2

Lubridate nicht Tageszeit Daten handhaben, so Hadley empfiehlt das hms-Paket für diese Art von Daten. So etwas wie dies funktionieren würde:

library(lubridate) 
foo <- data.frame(start.time = parse_datetime(c("2012-02-06 15:47:00", 
           "2012-02-06 15:02:00", 
           "2012-02-22 10:08:00")), 
        duration = c(1,2,3)) 


foo<-foo %>% mutate(time_of_day=hms::hms(second(start.time),minute(start.time),hour(start.time))) 

Watch out für 2 mögliche Probleme - 1) lubridate hat eine andere Funktion aufgerufen hms und 2) hms :: hms nimmt die Argumente in umgekehrter Reihenfolge, dass der Name schon sagt (so dass nur Sekunden geliefert werden können)