2017-05-19 2 views
0

Ich habe zwei Datenrahmen, die ich zusammenführen muss. Die Felder, die ich zusammenführen möchte, sind IP-Adresse und Uhrzeit (% H:% M). Ich suche nach einer genauen Übereinstimmung im IP-Adressfeld, aber im Zeitfeld möchte ich eine unscharfe Übereinstimmung innerhalb von 5 Minuten (+/-). Zum Beispiel hatte, wenn ich den folgenden 2 Datenrahmen:Fuzzy Merge 2 Datenrahmen auf Zeit in r

> df1 
    users1 IPs1  times1 
1 user1 192.168.1.1 11:05 
2 user2 192.168.1.2 20:31 
3 user3 192.168.1.3 01:19 

> df2 
    users2 IPs2   times2 
1 userx 192.168.1.2 20:33 
2 usery 192.168.1.3 01:19 
3 userz 192.168.1.1 11:01 

Und ich wollte, dass der Datenrahmen fusionieren, dass user1 mit userz korreliert zu zeigen, user2 korreliert mit userx und user3 korreliert mit Usery. Wie könnte ich das tun? Mit der Zusammenführungsfunktion würde ich Benutzer3 Korrelationen nur mit usery basierend auf genauen Zeittreffern erhalten.

+0

Können Sie bitte erwartete Ausgabe zu Ihrer Frage hinzufügen? – yeedle

+0

Können Sie die Ausgabe von 'dput (df1)' und 'dput (df2)' für einfach reproduzierbare Daten einfügen? –

Antwort

1

Sie können das fuzzyjoin-Paket verwenden, um unscharf zu verschmelzen. Eine der fuzzyjoin Funktionen ist difference_join, die Sie basierend auf der absoluten Differenz zwischen Spalten in zwei Tabellen verknüpfen können. Das einzige Problem ist, times1 und times2 sind Faktoren oder Zeichenvektoren, nicht numerisch. Also habe ich hms verwendet, um sie in numerische Spalten zu verwandeln, und dann links verbunden, unscharf über einen Unterschied von 5 Minuten (5 * 60 Sekunden) und gefiltert, wenn IPs identisch sind.


library(tidyverse) 
library(fuzzyjoin) 
library(hms) 

hms <- Vectorize(hms) 
df1 <- df1 %>% 
    separate(times1, c("hours", "minutes")) %>% 
    mutate_at(c("hours", "minutes"), as.integer) %>% 
    mutate(times = hms(0, minutes, hours)) 

df2 <- df2 %>% 
    separate(times2, c("hours", "minutes")) %>% 
    mutate_at(c("hours", "minutes"), as.integer) %>% 
    mutate(times = hms(0, minutes, hours)) 


difference_full_join(df1, df2, by = "times", max_dist = 5*60) %>% 
    filter(IPs1 == IPs2) 
#> users1  IPs1 hours.x minutes.x times.x users2  IPs2 hours.y 
#> 1 user1 192.168.1.1  11   5 39900 userz 192.168.1.1  11 
#> 2 user2 192.168.1.2  20  31 73860 userx 192.168.1.2  20 
#> 3 user3 192.168.1.3  1  19 4740 usery 192.168.1.3  1 
#> minutes.y times.y 
#> 1   1 39660 
#> 2  33 73980 
#> 3  19 4740 
+1

Vielen Dank! Entschuldigung, es hat so lange gedauert, bis ich zu dir zurückkam, aber das Leben ist diese Woche passiert. Dies funktionierte perfekt (nachdem ich herausgefunden hatte, dass ich meine Datenstrings als Faktoren importiert hatte). Ich schätze die Hilfe und das motiviert mich wirklich weiter zu lernen. –

Verwandte Themen