2017-09-11 4 views
2

Ich möchte eine Liste von E-Mails, die einen zugehörigen "Besitzer" und Daten haben, nehmen und sie mit eingehenden Bestellungen, mit Daten und Werten übereinstimmen. Der übereinstimmende Schlüssel ist eine E-Mail, aber ich möchte, dass sie am nächsten Tag übereinstimmt, da es in einigen Fällen Fälle gibt, in denen eine E-Mail-Adresse zwei verschiedene Besitzer haben kann.Mapping basierend auf dem nächsten Datum

reproduzierbares Beispiel:

require(dplyr) 

e <- c("[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]", "[email protected]") 
d <- c("2017-01-01", "2017-04-05", "2017-04-12", "2017-05-05", "2017-08-05", "2017-12-05") 
p <- c("Jeff", "Sam", "Sam", "Jeff", "Matt", "Matt") 
df <- data_frame(e, d, p) %>% mutate(d=as.Date(d)) 

o <- c("[email protected]", "[email protected]", "[email protected]", "[email protected]") 
d2 <- c("2017-02-02", "2017-04-28", "2017-05-05", "2017-07-01") 
a <- c(600.50, 3000, 4999.99, 2050.6) 
df2 <- data_frame(o, d2, a) %>% mutate(d2 = as.Date(d2)) 

die erste df ist die Karte von E-Mail-Adresse von p Person gehört. Die df2 ist die Bestellungen, die mit diesen E-Mail-Adressen kamen, und ich möchte eine Spalte df2 hinzufügen, die den richtigen "Besitzer" anpinnt, der die ihm zugewiesene E-Mail-Adresse hat und ist in Datum am nächsten.

gewünschtes Ergebnis:

> df2 
# A tibble: 4 x 3 
       o   d2  a  newowner 
      <chr>  <date> <dbl>  <char> 
1 [email protected] 2017-02-02 600.50  "Jeff" 
2 [email protected] 2017-04-28 3000.00  "Sam" 
3 [email protected] 2017-05-05 4999.99  NA 
4 [email protected] 2017-07-01 2050.60  "Jeff" 

Derzeit ist es nicht ein massives Problem - aus 70k Aufzeichnungen „owned“ E-Mail-Adressen, da nur ~ 86 Fälle von Doppelarbeit sind. Das Eigentum ändert sich jedoch in den letzten Monaten des Jahres und könnte daher zu vielen Doppelgleisigkeiten führen, wenn sich die Eigentumsverhältnisse verschieben. Momentan nehme ich den Besitzer aus dem entferntesten Zeitpunkt und überschreibe die anderen Besitzer in diesen 86 Beispielen.

Danke für Ihre Hilfe!

Antwort

1

@ Franks Antwort ist großartig und wie er sagte, hat data.table Rolling Join aber dplyr nicht. Also ich denke data.table ist eine bessere Wahl hier. Wenn Sie jedoch in dplyr bleiben möchten. Hier ist eine Idee.

library(dplyr) 
df3 <- df %>% 
    full_join(df2, by = c("e" = "o")) %>% 
    mutate(Date_ABS_Diff = abs(d - d2)) %>% 
    arrange(e, Date_ABS_Diff) %>% 
    group_by(e) %>% 
    slice(1) %>% 
    select(o = e, d2, a, newowner = p) 
df3 
# A tibble: 4 x 4 
# Groups: o [4] 
       o   d2  a newowner 
      <chr>  <date> <dbl> <chr> 
1 [email protected] 2017-02-02 600.50  Jeff 
2 [email protected] 2017-04-28 3000.00  Sam 
3 [email protected] 2017-05-05 4999.99  <NA> 
4 [email protected] 2017-07-01 2050.60  Jeff 

Dieser Ansatz verwendet full_join alle möglichen Kombinationen von E-Mail zu kombinieren. Danach berechnen Sie die absolute Differenz zwischen den Daten und verwenden Sie arrange und slice, um den Datensatz mit minimalen absoluten Daten auszuwählen.

+0

Nett - ich denke, dass das ist, wohin mein Verstand natürlich gehen würde, obwohl ich mehr über rollende Verbindungen erfahren sollte. Was macht Slice normalerweise? Ich hätte Scheibe mit Filter (! Duplicated (e)) getauscht, die die erste nach der sortierenden aufsteigenden Date_ABS_Diff –

+0

@MattW ergreifen würde. slice wählt Zeilen nach Position aus. Bitte beachten Sie die Dokumentation: https://www.rdocumentation.org/packages/dplyr/versions/0.7.3/topics/slice – www

+0

Ah perfekt. Vielen Dank!Etwas Neues gelernt. –

4

Dies ist ein Standard Roll Update mitmachen data.table:

library(data.table) 
DT = data.table(df) 
DT2 = data.table(df2) 
DT2[DT, on=.(o = e, d2 = d), roll=-Inf, v := i.p ] 

       o   d2  a v 
1: [email protected] 2017-02-02 600.50 Jeff 
2: [email protected] 2017-04-28 3000.00 Sam 
3: [email protected] 2017-05-05 4999.99 NA 
4: [email protected] 2017-07-01 2050.60 Jeff 

Wenn pro Titel, können Sie die nächste Übereinstimmung möchten, verwenden Sie roll = "nearest" statt roll = -Inf.

Dplyr hat keine Rolling Joins und wird nie Update Joins haben, also gibt es dort kein Analog.

+1

vielen Dank Frank! Ich erinnere mich, dass ich mit data.table über Joins in der Vergangenheit gelernt habe, aber ich habe mich an dplyr gewöhnt, weil es leichter zu lernen war. Ich werde dies umsetzen und Sie wissen lassen, wie es geht! - Quick Q: Ist die -Inf am nächsten dran? oder sucht es von einer Seite, früher oder später, am nächsten? –

+0

Ich habe eine andere Anfrage. Wenn ich mir diese anschaue, möchte ich das Datum am nächsten machen, was den absoluten Wert der bisherigen Entfernung bedeutet. Kann Vergangenheit oder Zukunft von Datum sein. Wie würde ich das Roll-Argument anpassen, um dem zu entsprechen? –

+0

@MattW In '? Data.table' sind die Werte für das Argument' roll = 'dokumentiert. Ich denke, "roll =" nearest "' wird tun, was du willst. – Frank

Verwandte Themen