2017-05-05 3 views
1

Ich habe zwei Datenrahmen: 'Sonden' und 'Ereignisse'. Der folgende Code erzeugt reproduzierbare Beispiele dieser Datenrahmen. Probes.subset ist ein Datenrahmen aller Beobachtungen von Sonden, die die Datumszeiträume in Ereignissen schneiden. Der folgende Code generiert 6 Ereignisse ... in Wirklichkeit habe ich fast 200 diskrete Ereignisse.Bedingter Join für mehrere Zeiträume

Ziel: Ich muss die Event.name von Events, zu jeder entsprechenden Beobachtung in Probespset basierend auf dem Timestamp, so dass jede Beobachtung mit dem richtigen Ereignis zugeordnet ist.

I have previously tried a FOR loop aber das ist unglaublich langsam und endet nicht, da meine Daten über 180.000 Zeilen lang sind. Ich habe das Gefühl, dass dies gelöst werden kann, indem ich eine Funktion schreibe und etwas wie "Anwenden" benutze, aber ich bin ein vollkommener Neuling für Funktionen in R und keine von denen, die ich erstellt habe, funktionieren.

library(dplyr) 

# Generate Probes data 
start <- as.POSIXct("01/06/2016 01:00", format = "%d/%m/%Y %H:%M") 
end <- start + as.difftime(1, units = "days") 

Timestamp <- seq(from = start, to = end, by = "10 mins") 
Value <- round(runif(145) * 100, 2) 

Probes <- data.frame(Timestamp, Value) 

# Generate Events data 
Event.name <- seq(1, 6) 

Event.start <- as.POSIXct(c("01/06/2016 01:20", "01/06/2016 05:00", 
          "01/06/2016 06:30", "01/06/2016 12:00", 
          "01/06/2016 17:40", "01/06/2016 19:20"), 
          format = "%d/%m/%Y %H:%M") 

Event.end <- as.POSIXct(c("01/06/2016 02:00", "01/06/2016 05:30", 
          "01/06/2016 07:20", "01/06/2016 14:00", 
          "01/06/2016 18:10", "01/06/2016 21:40"), 
          format = "%d/%m/%Y %H:%M") 

Events <- data.frame(Event.name, Event.start, Event.end) 

# Subset probes data to fall within Events bounds 
Probes.subset <- Probes %>% 
    mutate(InRange = Timestamp %in% unlist(Map(
    `:`, 
    Events$Event.start, 
    Events$Event.end 
))) %>% 
    filter(InRange == "TRUE") 
+0

[Eine ähnliche Frage] (http://stackoverflow.com/questions/23095896/merging-two-dataframes-on- a-date-range-in-r) behandelt das Zusammenfügen von Datumsbereichen, aber ihr Beispiel hat eine gemeinsame Spalte zwischen den Datenrahmen. Ich kann ihre Frage nicht kommentieren, da meine Vertretung zu niedrig ist. – Ciaran

+0

Erzeugt dies das gewünschte Ergebnis? 'unlist (lapply (Probes_setset $ Timestamp, function (x) was (x> = Ereignisse $ Event.start & x <= Events $ Event.end))). Sie können dies einer Spalte in "ProbesSet" zuweisen. – Gopala

+0

@Gopala - Ich habe versucht, das auszuführen, aber bekomme den folgenden Fehler: 'Fehler in' $ <-. Data.frame' ('* tmp *', "Event" , Wert = c (1L, 1L, 1L, 1L,: Ersetzung hat 43 Zeilen, Daten haben 54' – Ciaran

Antwort

4

In SQL können Sie as verwenden einen Aliasnamen für Ihre verschiedenen Datensätze angeben, während Beitritt. Auf diese Weise können Sie aus jedem Datensatz eine bestimmte Spalte auswählen. Die Annahme, dass Code Antwort könnten Sie tun:

library(sqldf) 
res <- sqldf("SELECT l.*, r.`Event.name` 
     FROM Probes as l 
     LEFT JOIN Events as r 
     ON l.Timestamp BETWEEN r.`Event.start` AND r.`Event.end`") 

head(res) 
#   Timestamp Value Event.name 
#1 2016-06-01 01:00:00 60.73   NA 
#2 2016-06-01 01:10:00 14.01   NA 
#3 2016-06-01 01:20:00 17.14   1 
#4 2016-06-01 01:30:00 43.64   1 
#5 2016-06-01 01:40:00 27.05   1 
#6 2016-06-01 01:50:00 57.10   1 

Eine Anmerkung - ich würde über Ihre Daten einrichten, da in Zeile 5 von Events vorsichtig sein, Sie eine Startzeit> Endzeit haben.


Auch eine schnelle data.table Lösung wäre foverlaps zu verwenden:

library(data.table) 
setDT(Probes)[,Time2 := Timestamp] #Clean data 
setDT(Events)[, `:=`(start = min(Event.start, Event.end), end = max(Event.start, Event.end)), by = (seq_len(nrow(Events)))] 

setkey(setDT(Events), start, end) 
res2 <- foverlaps(setDT(Probes), Events, by.x = c("Timestamp", "Time2"), nomatch = NA)[, c("Time2", "Event.start", "Event.end", "start","end") := NULL] 
+0

Ah habe ich gefunden Nachdem ich es gepostet habe, versuche es jetzt! – Ciaran

+0

Das hat perfekt funktioniert! Vielen Dank für deine Hilfe, das war schon eine ganze Weile ein Kopfzerbrechen. Ich werde jetzt meinen Kopf mit SQL innerhalb von R bekommen ... immer noch ein Neuling! +1 – Ciaran

+1

Kein Problem! Ich finde SQL kann für diese Art von Joins groß sein. Auch wenn Sie concern ned über die Geschwindigkeit, die ich bearbeitet habe, um eine schnelle "data.table" -Methode einzuschließen. Obwohl die Syntax nicht sehr freundlich ist –