2017-10-19 1 views
1

ich zur Zeit mit folgenden Datenstrukturen zu tun habe:Matching-Werten zwischen Datenrahmen basierend auf überlappende Termine

Attribute df:

ID Begin_A  End_A  Interval       Value 
1 5 1990-03-01 2017-03-10 1990-03-01 UTC--2017-03-10 UTC Cat1 
2 10 1993-12-01 2017-12-02 1993-12-01 UTC--2017-12-02 UTC Cat2 
3 5 1991-03-01 2017-03-03 1991-03-01 UTC--2017-03-03 UTC Cat3 
4 10 1995-12-05 2017-12-10 1995-12-05 UTC--2017-12-10 UTC Cat4 

Buchungen df:

ID Begin_A  End_A      Interval 
1 5 2017-03-03 2017-03-05 2017-03-03 UTC--2017-03-05 UTC 
2 6 2017-05-03 2017-05-05 2017-05-03 UTC--2017-05-05 UTC 
3 8 2017-03-03 2017-03-05 2017-03-03 UTC--2017-03-05 UTC 
4 10 2017-12-05 2017-12-06 2017-12-05 UTC--2017-12-06 UTC 

Wie bereits erwähnt in der folgende Beitrag: Matching values conditioned on overlapping Intervals and ID, ich beabsichtige, die folgenden Daten Umstrukturierung zu tun: Nehmen Sie die ID aus Buchungen, filtern Sie alle Zeilen des Attributs Datenrahmen, wo die Attribute ID m atches die Buchungsnummer. Überprüfen Sie, welche der Zeilen mit übereinstimmender Attribut-ID auch überlappende Zeitintervalle haben (int_overlaps von lubridate). Dann nehmen Sie den entsprechenden Wert aus der Spalte Wert und drucken Sie jeden in der Spalte Attribute_value.

Das beabsichtigte Ergebnis würde wie folgt aussehen:

ID Begin_A  End_A  Interval      Attribute_value 
5 2017-03-03 2017-03-05 2017-03-03 UTC--2017-03-05 UTC Cat1,Cat3 
6 2017-05-03 2017-05-05 2017-05-03 UTC--2017-05-05 UTC NA 
8 2017-03-03 2017-03-05 2017-03-03 UTC--2017-03-05 UTC NA 
10 2017-12-05 2017-12-06 2017-12-05 UTC--2017-12-06 UTC Cat4 

JOC sofern bereits eine Teilantwort auf diese Frage hier :(https://stackoverflow.com/a/46819541/8259308). Diese Lösung erlaubt es nicht, lange Perioden zwischen Begin_A und End_A im Attribute Datenrahmen, da ein Vektor mit einzelnen Terminen mit diesem Befehl erstellt wird:

complete(Date = full_seq(Date, period = 1), ID) %>% 

Seit meinen ursprünglichen Daten-Set eine sehr große Menge von Beobachtungen mit langer Zeit hat Frames im Datenrahmen Attribute ist R nicht in der Lage, diese große Menge an Beobachtungen zu verarbeiten. Meine Idee war, entweder die oben erwähnte Linie zu modifizieren, um die Sprünge in Daten auf Monate zu reduzieren (was auch die Genauigkeit verringern würde) oder einen neuen Ansatz zu versuchen. Der folgende Code erzeugt den Datenrahmen präsentierte oben:

library(lubridate) 
library(tidyverse) 
# Attributes data frame: 
date1 <- as.Date(c('1990-3-1','1993-12-1','1991-3-1','1995-12-5')) 
date2 <- as.Date(c('2017-3-10','2017-12-2','2017-3-3','2017-12-10')) 
attributes <- data.frame(matrix(NA,nrow=4, ncol = 5)) 
names(attributes) <- c("ID","Begin_A", "End_A", "Interval", "Value") 
attributes$ID <- as.numeric(c(5,10,5,10)) 
attributes$Begin_A <-date1 
attributes$End_A <-date2 
attributes$Interval <-attributes$Begin_A %--% attributes$End_A 
attributes$Value<- as.character(c("Cat1","Cat2","Cat3","Cat4")) 

### Bookings data frame: 

date1 <- as.Date(c('2017-3-3','2017-5-3','2017-3-3','2017-12-5')) 
date2 <- as.Date(c('2017-3-5','2017-5-5','2017-3-5','2017-12-6')) 
bookings <- data.frame(matrix(NA,nrow=4, ncol = 4)) 
names(bookings) <- c("ID","Begin_A", "End_A", "Interval") 
bookings$ID <- as.numeric(c(5,6,8,10)) 
bookings$Begin_A <-date1 
bookings$End_A <-date2 
bookings$Interval <-bookings$Begin_A %--% bookings$End_A 

Dies ist die Lösung für den vorherigen Beitrag von JOC bereitgestellt:

library(tidyverse) 

attributes2 <- attributes %>% 
    select(-Interval) %>% 
    gather(Type, Date, ends_with("_A")) %>% 
    select(-Type) %>% 
    group_by(Value) %>% 
    complete(Date = full_seq(Date, period = 1), ID) %>% 
    ungroup() 

bookings2 <- bookings %>% 
    select(-Interval) %>% 
    gather(Type, Date, ends_with("_A")) %>% 
    select(-Type) %>% 
    group_by(ID) %>% 
    complete(Date = full_seq(Date, period = 1)) %>% 
    ungroup() 

bookings3 <- bookings2 %>% 
    left_join(attributes2, by = c("ID", "Date")) %>% 
    group_by(ID) %>% 
    summarise(Attribute_value = toString(sort(unique(Value)))) %>% 
    mutate(Attribute_value = ifelse(Attribute_value %in% "", NA, Attribute_value)) 

bookings4 <- bookings %>% left_join(bookings3, by = "ID") 
bookings4 
    ID Begin_A  End_A      Interval Attribute_value 
1 5 2017-03-03 2017-03-05 2017-03-03 UTC--2017-03-05 UTC  Cat1, Cat3 
2 6 2017-05-03 2017-05-05 2017-05-03 UTC--2017-05-05 UTC   <NA> 
3 8 2017-03-03 2017-03-05 2017-03-03 UTC--2017-03-05 UTC   <NA> 
4 10 2017-12-05 2017-12-06 2017-12-05 UTC--2017-12-06 UTC   Cat4 
+3

Check out 'data.table :: foverlaps', die zur Durchführung Überlappung schließt sich speziell ausgelegt ist. – Mako212

Antwort

1

Sie data.table betrachten können, die für erlaubt „Nicht-Equi-Joins“ , dh Verbindungen basierend auf >=, >, <= und <. In demselben Aufruf können Aggregatoperationen für die Gruppen in dem LHS-Datensatz ausgeführt werden, die jeder Zeile in dem RHS-Datensatz (i) entspricht (by = .EACHI).

d1[d2, on = .(id = id, end >= begin), 
     .(i.begin, i.end, val_str = toString(val)), by = .EACHI] 

# id  end i.begin  i.end val_str 
# 1: 5 2017-03-03 2017-03-03 2017-03-05 Cat3, Cat1 
# 2: 6 2017-05-03 2017-05-03 2017-05-05   NA 
# 3: 8 2017-03-03 2017-03-03 2017-03-05   NA 
# 4: 10 2017-12-05 2017-12-05 2017-12-06  Cat4 

Datenaufbereitung:

d1 <- data.frame(id = c(5, 10, 5, 10), 
       begin = as.Date(c('1990-3-1','1993-12-1','1991-3-1','1995-12-5')), 
       end = as.Date(c('2017-3-10','2017-12-2','2017-3-3','2017-12-10')), 
       val = c("Cat1", "Cat2", "Cat3", "Cat4")) 

d2 <- data.frame(id = c(5, 6, 8, 10), 
       begin = as.Date(c('2017-3-3','2017-5-3','2017-3-3','2017-12-5')), 
       end = as.Date(c('2017-3-5','2017-5-5','2017-3-5','2017-12-6'))) 

library(data.table) 
setDT(d1) 
setDT(d2) 
Verwandte Themen