2016-05-14 16 views
0

Ich habe einen Datenrahmen namens DF mit den Spalten Zeit und Datum. Ich möchte Teilmenge DF basierend auf Werten in diesen Spalten. Für die Daten habe ich eine Liste von Daten in DATEN und unterteile DF-Zeilen, in denen das DF $ -Datum in DATEN vorhanden ist. Für die Zeit möchte ich Teilmenge von 00.04.00 bis 00.06.00. Ich weiß nicht, wie ich Letzteres machen soll.Subset einen Datenrahmen basierend auf einer Zeitsequenz

Idealerweise würde ich gerne Subset sowohl durch Angabe des Bereichs, wie in 00:04:00 bis 00:06:00, als auch durch Angabe des Startpunkts und der Minuten nach vorne schauen, wie in 00.04: 00 und 3 Minuten (zwei verschiedene Methoden). Ich schätze, es kommt darauf an, eine Sequenz von Zeit zu machen und diese Sequenz in einen separaten Vektor zu legen, den ich dann für die Übereinstimmung verwenden kann.

Bitte beachten Sie, dass dies nur ein kurzes reproduzierbares Beispiel ist. Ich suche nach einer allgemeinen Möglichkeit, dies zu tun, weil ich in der Praxis große Zeitspannen unterteilen möchte. Bitte beachten Sie auch, dass es in diesem Beispiel nur ein übereinstimmendes Datum gibt. In der Praxis würde es viele übereinstimmende Daten geben, die mehrere Jahre umfassen. Deshalb glaube ich, dass es nicht möglich ist, POSIXlt für die Zeitsequenz zu verwenden. Vielen Dank.

#DF looks like this: 
    #    DateTime XXX  Time  Date 
    #1371 2016-04-25 00:08:00 14 00:08:00 2016-04-25 
    #1372 2016-04-25 00:07:00 13 00:07:00 2016-04-25 
    #1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
    #1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
    #1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 
    #1376 2016-04-25 00:03:00 4 00:03:00 2016-04-25 
    #1377 2016-04-25 00:02:00 6 00:02:00 2016-04-25 
    #1387 2016-04-24 23:52:00 41 23:52:00 2016-04-24 
    #1388 2016-04-24 23:51:00 93 23:51:00 2016-04-24 
    #1389 2016-04-24 23:50:00 53 23:50:00 2016-04-24 

    #Code for DF, DATES, and to subset DF based on DATES 
    DF <- structure(list(DateTime = structure(list(sec = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), min = c(8L, 7L, 6L, 5L, 4L, 3L, 2L, 1L, 0L, 59L, 58L, 57L, 56L, 55L, 54L, 53L, 52L, 51L, 50L), hour = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L), mday = c(25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 24L, 24L, 24L, 24L, 24L, 24L, 24L, 24L, 24L, 24L), mon = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), year = c(116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L, 116L), wday = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), yday = c(115L, 115L, 115L, 115L, 115L, 115L, 115L, 115L, 115L, 114L, 114L, 114L, 114L, 114L, 114L, 114L, 114L, 114L, 114L), isdst = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), zone = c("EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT", "EDT"), gmtoff = c(NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_)), .Names = c("sec", "min", "hour", "mday", "mon", "year", "wday", "yday", "isdst", "zone", "gmtoff"), class = c("POSIXlt", "POSIXt")), Open = c(14, 13, 14, 3, 2, 4, 6, 4, 15, 15, 23, 24, 33, 14, 65, 54, 41, 93, 53), Time = c("00:08:00", "00:07:00", "00:06:00", "00:05:00", "00:04:00", "00:03:00", "00:02:00", "00:01:00", "00:00:00", "23:59:00", "23:58:00", "23:57:00", "23:56:00", "23:55:00", "23:54:00", "23:53:00", "23:52:00", "23:51:00", "23:50:00"), Date = structure(c(16916, 16916, 16916, 16916, 16916, 16916, 16916, 16916, 16916, 16915, 16915, 16915, 16915, 16915, 16915, 16915, 16915, 16915, 16915), class = "Date")), .Names = c("DateTime", "XXX", "Time", "Date"), row.names = c("1371", "1372", "1373", "1374", "1375", "1376", "1377", "1378", "1379", "1380", "1381", "1382", "1383", "1384", "1385", "1386", "1387", "1388", "1389"), class = "data.frame") 
    DATES <- structure(c(12431, 12432, 10445, 10480, 11487, 12494, 12501, 12508, 13115, 13522, 14529, 15536, 16916, 16935), class = "Date") 
    SELEC <- DF[DF$Date %in% DATES,] 

    #Result of subsetting by Date: 
    #     DateTime XXX  Time  Date 
    # 1371 2016-04-25 00:08:00 14 00:08:00 2016-04-25 
    # 1372 2016-04-25 00:07:00 13 00:07:00 2016-04-25 
    # 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
    # 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
    # 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 
    # 1376 2016-04-25 00:03:00 4 00:03:00 2016-04-25 
    # 1377 2016-04-25 00:02:00 6 00:02:00 2016-04-25 
    # 1378 2016-04-25 00:01:00 4 00:01:00 2016-04-25 
    # 1379 2016-04-25 00:00:00 15 00:00:00 2016-04-25 

    #How the final product would look like if using a larger data base spanning many years: 
    #   DateTime XXX  Time  Date 
    #2016-04-25 00:06:00 13 00:06:00 2016-04-25 
    #2016-04-25 00:05:00 14 00:05:00 2016-04-25 
    #2016-04-25 00:04:00 3 00:04:00 2016-04-25 
    #2014-03-11 00:06:00 94 00:06:00 2014-03-11 
    #2014-03-11 00:05:00 6 00:05:00 2014-03-11 
    #2014-03-11 00:04:00 14 00:04:00 2014-03-11 
    #2011-08-06 00:06:00 13 00:06:00 2011-08-06 
    #2011-08-06 00:05:00 19 00:05:00 2011-08-06 
    #2011-08-06 00:04:00 41 00:04:00 2011-08-06 

Antwort

0

Möglichkeit 1: lexicographic Vergleich

Wenn alle Zeitwerte als Nullen aufgefüllt 24 Stunden Strings mit den gleichen Trennzeichen gespeichert sind, wie %H:%M:%S, dann kann ein lexikographischer Vergleich verwendet werden, um den Filter anzuwenden.

DF[DF$Date%in%DATES & DF$Time>='00:04:00' & DF$Time<='00:06:00',]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Lexikographische Lösungen sind natürlich nicht ideal, weil sie sich nicht auf zeitbasierte Mathematik, wie Addieren, Subtrahieren verleihen, multiplizieren, dividieren usw.

Bessere Lösungen beinhalten die Umwandlung der Zeitwerte zu einem numerischen Typ, der Zeitspannen als Offset von einer expliziten oder unspezifizierten Basiszeit codiert. Dies ist, wie beliebt Datum/Zeit Bibliotheken Typen wie boost date_time für C kodieren ++, Joda-Time für Java und POSIXct, difftime und lubridate für R.


Möglichkeit 2: Handbuch Numerik

Es ist Es ist möglich, die Strings selbst zu analysieren, um Zahlen zu konstruieren, die die Zeitdauern repräsentieren, und einen numerischen Vergleich zu verwenden, um den Filter anzuwenden.

hmsToDouble <- function(hms) as.double(substr(hms,1,2))*3600 + as.double(substr(hms,4,5))*60 + as.double(substr(hms,7,8)); 
DF[DF$Date%in%DATES & hmsToDouble(DF$Time)>=hmsToDouble('00:04:00') & hmsToDouble(DF$Time)<=hmsToDouble('00:06:00'),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Möglichkeit 3: POSIXt

können wir Vektoren POSIXt erzeugen (das heißt, POSIXct oder POSIXlt) -Werten und vektorisiert Vergleiche mit diesen Vektoren verwendet werden.

DF[DF$Date%in%DATES & DF$DateTime>=as.POSIXct(paste0(DF$Date,' 00:04:00')) & DF$DateTime<=as.POSIXct(paste0(DF$Date,' 00:06:00')),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Möglichkeit 4: difftime

Die einzige in R Dauer Datentyp eingebaute Zeit ist die difftime-Typ, der ein wenig heikel sein kann, mit zu arbeiten. Aber für dieses Problem ist es ziemlich einfach.

DF[DF$Date%in%DATES & as.difftime(DF$Time)>=as.difftime('00:04:00') & as.difftime(DF$Time)<=as.difftime('00:06:00'),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 

Möglichkeit 5: lubridate

Das lubridate Paket weithin als das beste Paket sein für Datum/Uhrzeit in R. Handhabung Es hat eine Dauer Art liefert, die Dauer der regulären Spielzeit darstellt, und einen Periodentyp, der es ermöglicht, Zählungen verschiedener irregulärer Zeiteinheiten darzustellen. Historisch gesehen haben Datums-/Zeitbibliotheken manchmal versagt, weil ihnen die Unterscheidung zwischen unregelmäßigen Zeiträumen und regulären Zeitdauern fehlte.

In der folgenden Lösung rufen die hms() Aufrufe Instanzen des Periodentyps auf, daher vergleichen wir tatsächlich separate Zeiteinheiten. In Bezug auf die tatsächliche Speicherung der separaten Zeiteinheiten besteht das Design von Lubridate darin, die Sekundenwerte als die tatsächliche Nutzlast des Doppelvektors und die verbleibenden Einheiten (Minuten, Stunden, Tage, Monate und Jahre) als Attribute zu speichern das Objekt.

library(lubridate); 
DF[DF$Date%in%DATES & hms(DF$Time)>=hms('00:04:00') & hms(DF$Time)<=hms('00:06:00'),]; 
##     DateTime XXX  Time  Date 
## 1373 2016-04-25 00:06:00 14 00:06:00 2016-04-25 
## 1374 2016-04-25 00:05:00 3 00:05:00 2016-04-25 
## 1375 2016-04-25 00:04:00 2 00:04:00 2016-04-25 
0

Wie wäre es damit?

DF$Time <- strptime(DF$Time,format = '%H:%M:%S') 

timeCondition <- (DF$Time >= strptime('00:04:00',format = '%H:%M:%S')) & (DF$Time <= strptime('00:06:00',format = '%H:%M:%S')) 

SELEC <- DF[timeCondition & DF$Date %in% DATES,] 

Welche gibt:

   DateTime XXX    Time  Date 
1373 2016-04-25 00:06:00 14 2016-05-14 00:06:00 2016-04-25 
1374 2016-04-25 00:05:00 3 2016-05-14 00:05:00 2016-04-25 
1375 2016-04-25 00:04:00 2 2016-05-14 00:04:00 2016-04-25