2016-05-17 7 views
1

Sagen wir, ich habe eine data.table (kann auch data.frame sein, spielt für mich keine Rolle), die numerische Spalten a, b, c, d und e hat. Jede Zeile der Tabelle repräsentiert einen Artikel und a-e sind numerische Merkmale der Artikel.Suche nach "ähnlichen" Zeilen durch eine bedingte Verknüpfung mit sqldf

Was ich herausfinden möchte ist, welche Artikel ähnlich sind, basierend auf den Spalten a, b und c. Ich definiere "ähnlich", indem a, b und c maximal +/- 1 variieren können. Das heißt, Artikel x ist ähnlich wie Artikel y, wenn weder a, b noch c um mehr als 1 abweichen. Ihre Werte für d und e spielen keine Rolle und können erheblich abweichen.

Ich habe schon ein paar Ansätze versucht, aber nicht das gewünschte Ergebnis erhalten. Was ich erreichen möchte, ist, eine Ergebnistabelle zu erhalten, die nur solche Zeilen enthält, die mindestens einer anderen Zeile ähneln. Außerdem müssen Duplikate ausgeschlossen werden.

Insbesondere frage ich mich, ob dies mit der sqldf Bibliothek möglich ist. Meine Idee ist es, den Tisch unter den gegebenen Bedingungen mit sich selbst zu verbinden, aber ich verstehe es nicht richtig. Irgendwelche Ideen (nicht unbedingt sqldf)?

Antwort

1

Angenommen, unser Eingabedatenrahmen ist der integrierte 11x8 anscombe Datenrahmen. Die ersten drei Spaltennamen sind x1, x2 und . Dann hier sind einige Lösungen.

1) sqldf Dieses die Paare von Zeilennummern von ähnlichen Zeilen zurückgibt:

library(sqldf) 

ans <- anscombe 
ans$id <- 1:nrow(ans) 

sqldf("select a.id, b.id 
     from ans a 
     join ans b on abs(a.x1 - b.x1) <= 1 and 
        abs(a.x2 - b.x2) <= 1 and 
        abs(a.x3 - b.x3) <= 1") 

weiteren hinzufügen Bedingung and a.id < b.id wenn jede Zeile nicht mit sich selbst gekoppelt werden sollte, und wenn wir das Gegenteil von jedem ausschließen möchten pair oder füge and not a.id = b.id hinzu, um Selbstpaare einfach auszuschließen.

2) dist Dies liefert eine Matrix, deren m i, j-te Element ist 1, wenn Zeilen i und j ähnlich sind und 0, wenn nicht, basierend auf den Spalten 1, 2 und 3.

# matrix of pairs (1 = similar, 0 = not) 
m <- (as.matrix(dist(anscombe[1:3], method = "maximum")) <= 1) + 0 

geben:

1 2 3 4 5 6 7 8 9 10 11 
1 1 0 0 1 1 0 0 0 0 0 0 
2 0 1 0 1 0 0 0 0 0 1 0 
3 0 0 1 0 0 1 0 0 1 0 0 
4 1 1 0 1 0 0 0 0 0 0 0 
5 1 0 0 0 1 0 0 0 1 0 0 
6 0 0 1 0 0 1 0 0 0 0 0 
7 0 0 0 0 0 0 1 0 0 1 1 
8 0 0 0 0 0 0 0 1 0 0 1 
9 0 0 1 0 1 0 0 0 1 0 0 
10 0 1 0 0 0 0 1 0 0 1 0 
11 0 0 0 0 0 0 1 1 0 0 1 

Wir konnten m[lower.tri(m, diag = TRUE)] <- 0 in den Selbstpaare und die Rückseite jedes Paares auszuschließen, wenn gewünscht oder diag(m) <- 0 nur Selbstpaare auszuschließen.

Wir können einen Datenrahmen ähnlicher Zeilennummer Paare wie folgt erstellen. Um die Ausgabe kurz zu halten, haben wir Selbstpaare und die Rückseite jedes Paares ausgeschlossen.

# two-column data.frame of pairs excluding self pairs and reverses 
subset(as.data.frame.table(m), c(Var1) < c(Var2) & Freq == 1)[1:2] 

geben:

Var1 Var2 
34  1 4 
35  2 4 
45  1 5 
58  3 6 
91  3 9 
93  5 9 
101 2 10 
106 7 10 
117 7 11 
118 8 11 

Hier ist ein Netzwerk Graph der oben genannten. Beachten Sie, dass Antwort weiter nach dem Diagramm:

# network graph 
library(igraph) 
g <- graph.adjacency(m) 
plot(g) 

screenshot

# raster plot 
library(ggplot2) 
ggplot(as.data.frame.table(m), aes(Var1, Var2, fill = factor(Freq))) + 
     geom_raster() 

screenshot

+0

Große Antwort und sehr hilfreich, vor allem die Sqldf Beispiel. Es gibt noch eine Sache, die mich stört: Nach der Implementierung der sqldf-Lösung sind manche Lösungen mehrdeutig, weil sie eine Teilmenge einer anderen Lösung darstellen. Beispiel: a.id = 1 hat 10, 11 und 123 als b.id-Einträge. Zur gleichen Zeit hat a.id = 10 11 und 123 als b.id-Einträge. Ich möchte nicht die letzten zwei Zeilen angezeigt, da sie implizit von den ersten drei Zeilen abgedeckt werden. Gibt es eine Möglichkeit, dieses Problem direkt in der SQL-Anweisung zu lösen, oder müssen wir das später tun? Ich kann leider nur an letzteres denken. – snow8732

+0

Nur weil Zeile 1 Zeile 10 und Zeile 11 ähnlich ist, folgt Zeile 10 nicht Zeile 11. Betrachten wir zum Beispiel die Situation 1 = (0, 0, 0), Zeile 10 = (-1, 0, 0) und Zeile 11 = (1, 0, 0). Hier sind Zeile 10 und Zeile 11 nicht ähnlich, obwohl sie beide Zeile 1 ähneln. –

+0

Sie haben Recht. Dennoch würde Fall 1 = (0, 0, 0), Zeile 10 = (1, 0, 0) und Zeile 11 = (0,5, 0, 0) zu dem Fall führen, den ich in meinem letzten Kommentar beschrieben habe. Ich brauche einen Weg, um diese Teilmengen von Lösungen zu entfernen. – snow8732

0

Ich bin ziemlich neu in R, also nicht zu viel erwarten.

Was ist, wenn Sie aus Ihren Werten (die im Grunde Vektoren sind) eine Matrix mit dem Abstand von den zwei Werten erstellen. So können Sie diejenigen Kombinationen finden, die einen Unterschied von weniger als 1 voneinander haben. Über diesen Weg finden Sie die passenden (a) -Paare. Wiederholen Sie dies mit (b) und (c) und finden Sie diejenigen, die in allen Paaren enthalten sind.

Alternativ kann dies wahrscheinlich auch als ein Würfel gemacht werden.

Nur als Gedankentipp.

+0

Dies könnte die Lösung Ihrer Frage. http://stackoverflow.com/questions/16434838/subtraction-matrix-in-r –

Verwandte Themen