Effiziente Stringähnlichkeitsgruppierung

8

Einstellung : Ich habe Daten über Personen und die Namen ihrer Eltern, und ich möchte Geschwister (Personen mit identischen Elternnamen) finden.

%Vor%

Die erwartete Ausgabe wäre hier eine Spalte, die angibt, dass die ersten beiden Beobachtungen zur Familie X gehören, während die dritte und vierte Spalte jeweils in einer eigenen Familie stehen. ZB:

%Vor%

Derzeitiger Ansatz : Ich bin bezüglich der Abstandsmetrik flexibel. Zur Zeit benutze ich Levenshtein edit-distance, um obs zu entsprechen, was zweistellige Unterschiede erlaubt. Aber andere Varianten wie "größte gemeinsame Sub-String" wäre in Ordnung, wenn sie schneller laufen.

Bei kleineren Unterabtastungen verwende ich stringdist::stringdist in einer Schleife oder stringdist::stringdistmatrix , aber dies wird zunehmend ineffizient, wenn die Stichprobengröße zunimmt.

Die Matrixversion explodiert, sobald eine bestimmte Stichprobengröße verwendet wird. Mein schrecklich ineffizienter Versuch des Loopings ist hier:

%Vor%

Meine Frage : Es sollte erhebliche Effizienzgewinne geben, z.B. weil ich aufhören könnte, Strings zu vergleichen, sobald ich sie gefunden habe, um sich ausreichend in etwas zu unterscheiden, das leichter zu beurteilen ist, z. Zeichenfolge Länge oder erstes Wort. Die String-Längenvariante funktioniert bereits und reduziert die Komplexität um einen Faktor ~ 3. Aber das ist bei weitem zu wenig. Vorschläge zur Reduzierung der Rechenzeit sind willkommen.

Anmerkungen :

  • Die Strings sind eigentlich in Unicode und nicht im lateinischen Alphabet (Devnagari)
  • Die Vorverarbeitung, um nicht verwendete Zeichen usw. zu löschen, ist gemacht
sheß 02.01.2018, 08:59
quelle

9 Antworten

7
___ qstnhdr ___ Effiziente Stringähnlichkeitsgruppierung ___ answer48098679 ___

Mein Vorschlag ist, einen datenwissenschaftlichen Ansatz zu verwenden, um nur ähnliche (gleiche Cluster-) Namen zu identifizieren, die mit stringdist verglichen werden.

Ich habe ein bisschen den Code geändert, der "elternsname" generiert, was mehr Variabilität in den ersten und zweiten Namen in einem realitätsnahen Szenario hinzufügt.

%Vor%

Hier starten Sie die echte Analyse, zuerst extrahieren Sie das Merkmal aus den Namen wie globale Länge, Länge des ersten, Länge des zweiten, Anzahl der Vokale und Konsonanten in beiden ersten und zweiten Namen (und alle anderen von Interesse).

Danach binden Sie alle diese Features und clustern das data.frame in einer hohen Anzahl von Clustern (zB 1000)

%Vor%

Übernehmen Sie stringdistmatrix nur innerhalb jedes Clusters (mit ähnlichen Namen)

%Vor%

In dist_matrix haben Sie den Abstand zwischen jedem Element im Cluster und können die family_id mit diesem Abstand zuweisen.

Um den Abstand in jedem Cluster (in diesem Beispiel) zu berechnen, benötigt der Code ungefähr 1 Sekunde (abhängig von der Dimension des Clusters), in 15 Minuten werden alle Entfernungen berechnet.

WARNUNG : dist_matrix wächst sehr schnell, in Ihrem Code ist besser, wenn Sie es innerhalb di for Schleife analysieren extrahieren famyli_id und dann können Sie es verwerfen.

    
___ qstntxt ___

Einstellung : Ich habe Daten über Personen und die Namen ihrer Eltern, und ich möchte Geschwister (Personen mit identischen Elternnamen) finden.

%Vor%

Die erwartete Ausgabe wäre hier eine Spalte, die angibt, dass die ersten beiden Beobachtungen zur Familie X gehören, während die dritte und vierte Spalte jeweils in einer eigenen Familie stehen. ZB:

%Vor%

Derzeitiger Ansatz : Ich bin bezüglich der Abstandsmetrik flexibel. Zur Zeit benutze ich Levenshtein edit-distance, um obs zu entsprechen, was zweistellige Unterschiede erlaubt. Aber andere Varianten wie "größte gemeinsame Sub-String" wäre in Ordnung, wenn sie schneller laufen.

Bei kleineren Unterabtastungen verwende ich %code% in einer Schleife oder %code% , aber dies wird zunehmend ineffizient, wenn die Stichprobengröße zunimmt.

Die Matrixversion explodiert, sobald eine bestimmte Stichprobengröße verwendet wird. Mein schrecklich ineffizienter Versuch des Loopings ist hier:

%Vor%

Meine Frage : Es sollte erhebliche Effizienzgewinne geben, z.B. weil ich aufhören könnte, Strings zu vergleichen, sobald ich sie gefunden habe, um sich ausreichend in etwas zu unterscheiden, das leichter zu beurteilen ist, z. Zeichenfolge Länge oder erstes Wort. Die String-Längenvariante funktioniert bereits und reduziert die Komplexität um einen Faktor ~ 3. Aber das ist bei weitem zu wenig. Vorschläge zur Reduzierung der Rechenzeit sind willkommen.

Anmerkungen :

  • Die Strings sind eigentlich in Unicode und nicht im lateinischen Alphabet (Devnagari)
  • Die Vorverarbeitung, um nicht verwendete Zeichen usw. zu löschen, ist gemacht
___ answer48096986 ___

Sie können sich verbessern, indem Sie nicht alle Linienpaare vergleichen. Erstellen Sie stattdessen eine neue Variable, die Ihnen hilft, zu entscheiden, ob es sich lohnt zu vergleichen.

Erstellen Sie zum Beispiel eine neue Variable "score", die die geordnete Liste der in elternsname verwendeten Buchstaben enthält (zum Beispiel wenn "Peter pan + marta steward" dann die Punktzahl "ademnprstw" ist), und berechnen Sie nur die Entfernung zwischen den Zeilen Ergebnis stimmt überein.

Natürlich können Sie eine Punktzahl finden, die besser zu Ihrem Bedarf passt, und ein wenig verbessern, um einen Vergleich zu ermöglichen, wenn nicht alle verwendeten Buchstaben üblich sind.

    
___ answer48199271 ___

Es macht keinen Sinn, Äquivalenzgruppen für nicht transitive Beziehungen zu erstellen. Wenn %code% ist wie %code% und %code% ist wie %code% , aber %code% ist nicht wie %code% , wie würdest du daraus Familien machen? Etwas wie Soundex zu verwenden (das war die Idee von Neal Fultz, nicht meiner) scheint die einzig sinnvolle Option zu sein und es löst auch dein Problem mit der Leistung.

    
___ answer48187085 ___

Ich hatte vor ein paar Jahren das gleiche Leistungsproblem. Ich musste die Duplikate der Leute basierend auf ihren eingegebenen Namen vergleichen. Mein Datensatz hatte 200.000 Namen und der Matrix-Ansatz explodierte. Nachdem ich eines Tages nach einer besseren Methode gesucht habe, hat die Methode, die ich hier vorschlage, in wenigen Minuten die Arbeit für mich erledigt:

%Vor%

Auf diese Weise vergleicht %code% bei jeder Iteration weniger Übereinstimmungen. Daraus können Sie verschiedene Leistungssteigerungen implementieren, wie das Filtern der Namen mit dem gleichen Anfangsbuchstaben vor dem Vergleich usw.

    
___ answer48211929 ___

Was ich verwendet habe, um die Permutationen zu reduzieren, die bei dieser Art von Namensabgleich eine Rolle spielen, ist die Erstellung einer Funktion, die die Silben im Namen (Nachnamen) zählt. Dann speichern Sie dies in der Datenbank als vorverarbeiteten Wert. Dies wird zu einer Funktion Syllable Hash .

Dann können Sie wählen, Wörter zusammen mit der gleichen Anzahl von Silben zu gruppieren. (Obwohl ich Algorithmen verwende, die 1 oder 2 Silben Unterschied erlauben, die als legitime Rechtschreib- / Tippfehler angezeigt werden können ... Aber meine Forschung hat herausgefunden, dass 95% der Rechtschreibfehler die gleiche Anzahl von Silben teilen)

In diesem Fall hätten %code% und %code% die gleiche Silbenzahl (2), aber %code% und %code% nicht (sie haben 1). (Zum Beispiel)

Wenn Ihre Funktion keine 1 Silbe für %code% erhält, müssen Sie möglicherweise Ihre Toleranz erhöhen, um einen Unterschied von mindestens 1 Silbe in der von Ihnen verwendeten Syllable Hash-Funktionsgruppierung zu berücksichtigen. (Um falsche Silbenfunktionsergebnisse zu berücksichtigen und den übereinstimmenden Nachnamen in der Gruppierung korrekt abzufangen)

Meine Silbenzählfunktion ist möglicherweise nicht vollständig anwendbar - da Sie möglicherweise nicht-englische Buchstabensätze verarbeiten müssen ... (Also habe ich den Code nicht eingefügt ... Seiner ist sowieso C) Wohlgemerkt - die Silbenzählfunktion muss nicht in Bezug auf die TRUE Silbenanzahl genau sein; es muss einfach als zuverlässige Hashing-Funktion fungieren - was es tut. SoundEx ist weit überlegen, da der erste Buchstabe genau ist.

Probieren Sie es aus, Sie werden überrascht sein, wie viel Verbesserung Sie durch die Implementierung einer Syllable Hash-Funktion erzielen. Möglicherweise müssen Sie SO um Hilfe bitten, damit die Funktion in Ihre Sprache übernommen wird.

    
___ answer48097430 ___

Wenn ich es richtig verstanden habe, möchten Sie jedes Elternpaar (jede Zeile im Datenrahmen parent_name) mit allen anderen Paaren (Zeilen) vergleichen und Zeilen mit Levenstein-Abstand kleiner oder gleich 2 behalten.

Ich habe folgenden Code für den Anfang geschrieben:

%Vor%

Gibt es zurück, was Sie wollten?

    
___ answer48206509 ___

es reproduziert Ihre Ausgabe, ich denke, Sie müssen teilweise übereinstimmende Kriterien entscheiden, ich habe die Standard-Agrep diejenigen beibehalten

%Vor%     
___ tag123r ___ R ist eine freie, quelloffene Programmiersprache und Softwareumgebung für statistische Berechnungen, Bioinformatik, Visualisierung und allgemeine Datenverarbeitung. Stellen Sie minimale, reproduzierbare, repräsentative Beispiele für Ihre Fragen bereit. Verwenden Sie dput () für Daten und geben Sie alle Nicht-Basis-Pakete mit Bibliotheksaufrufen an. Bilder für Daten oder Code nicht einbetten, eingerückte Codeblöcke verwenden. Verwenden Sie für statistische Fragen http://stats.stackexchange.com. ___ tag123string ___ Eine Zeichenfolge ist eine endliche Abfolge von Symbolen, die üblicherweise für Text verwendet wird, manchmal jedoch auch für beliebige Daten. ___ tag123performance ___ Für Fragen zur Messung oder Verbesserung der Code- und Anwendungseffizienz. ___ tag123levenshteindistance ___ Eine Metrik zur Messung der Differenz zwischen zwei Sequenzen. ___ antwort48104521 ___

Es gibt zwei Herausforderungen:

A. Die parallele Ausführung der Levenstein-Distanz - anstelle einer sequentiellen Schleife

B. Die Anzahl der Vergleiche: Wenn unsere Quellenliste 4 Millionen Einträge hat, sollten wir theoretisch 16 Billionen Levenstein Distanzmaße laufen lassen, was unrealistisch ist, selbst wenn wir die erste Herausforderung lösen.

Um meinen Gebrauch der Sprache klar zu machen, hier sind unsere Definitionen

  • Wir wollen die Levenstein-Distanz zwischen den Ausdrücken messen.
  • Jeder Ausdruck hat zwei Abschnitte, den übergeordneten Namen A und den vollständigen Namen B, die durch ein Pluszeichen
  • getrennt sind
  • Die Reihenfolge der Abschnitte ist wichtig (dh zwei Ausdrücke (1, 2) sind identisch, wenn Parent A von Ausdruck 1 = Parent A von Ausdruck 2 und Parent B oder Ausdruck 1 = Parent B von Ausdruck 2 ist. Ausdrücke werden nicht berücksichtigt identisch, wenn Parent A von Ausdruck 1 = Parent B von Ausdruck 2 und Parent B von Ausdruck 1 = Parent A von Ausdruck 2)
  • Ein Abschnitt (oder ein vollständiger Name) ist eine Reihe von Wörtern, die durch Leerzeichen oder Bindestriche getrennt sind und dem Vor- und Nachnamen einer Person entsprechen
  • wir nehmen an, dass die maximale Anzahl von Wörtern in einem Abschnitt 6 ist (Ihr Beispiel hat Abschnitte von 2 oder 3 Wörtern, ich nehme an, dass wir bis zu 6 Wörter haben können) die Reihenfolge der Wörter in einem Abschnitt ist wichtig (der Abschnitt ist immer ein Vorname, gefolgt von einem Nachnamen und nie der Nachname zuerst, zum Beispiel Jack John und John Jack sind zwei verschiedene Personen).
  • gibt es 4 Millionen Ausdrücke
  • Es wird angenommen, dass
  • Ausdrücke nur englische Zeichen enthalten. Zahlen, Leerzeichen, Satzzeichen, Bindestriche und andere nicht englische Zeichen können ignoriert werden.
  • wir gehen davon aus, dass die einfachen Übereinstimmungen bereits erledigt sind (wie der exakte Ausdruck übereinstimmt) und wir nicht nach exakten Übereinstimmungen suchen müssen

Technisch besteht das Ziel darin, eine Reihe übereinstimmender Ausdrücke in der Liste der 4 Millionen Ausdrücke zu finden. Zwei Ausdrücke gelten als übereinstimmender Ausdruck, wenn ihr Levenstein-Abstand kleiner als 2 ist.

Praktisch erstellen wir zwei Listen, die genaue Kopien der ursprünglichen 4-Millionen-Liste von Ausdrücken sind. Wir rufen dann die linke Liste und die rechte Liste auf. Jedem Ausdruck wird vor dem Duplizieren der Liste eine Ausdrucks-ID zugewiesen. Unser Ziel ist es, Einträge in der rechten Liste zu finden, die einen Levenstein-Abstand von weniger als 2 zu Einträgen der linken Liste haben, mit Ausnahme des gleichen Eintrags (gleiche Ausdrucks-ID).

Ich schlage einen zweistufigen Ansatz vor, um die beiden Herausforderungen getrennt zu lösen. Der erste Schritt wird die Liste der möglichen übereinstimmenden Ausdrücke reduzieren, der zweite wird die Levenstein-Distanzmessung vereinfachen, da wir nur sehr enge Ausdrücke betrachten. Bei der verwendeten Technologie handelt es sich um einen herkömmlichen Datenbankserver, da die Datensätze für die Leistung indexiert werden müssen.

HERAUSFORDERUNG A

Die Herausforderung A besteht darin, die Anzahl der Entfernungsmessungen zu reduzieren. Wir starten von maximal ca. 16 Billionen (4 Millionen zur Macht von zwei) und wir sollten ein paar Zehn oder Hunderte von Millionen nicht überschreiten. Die hier zu verwendende Technik besteht darin, nach mindestens einem ähnlichen Wort im vollständigen Ausdruck zu suchen. Abhängig davon, wie die Daten verteilt werden, reduziert dies die Anzahl der möglichen passenden Paare dramatisch. Alternativ können wir, abhängig von der geforderten Genauigkeit des Ergebnisses, auch nach Paaren mit mindestens zwei ähnlichen Wörtern oder mit mindestens der Hälfte ähnlicher Wörter suchen.

Technisch schlage ich vor, die Ausdruckliste in eine Tabelle zu legen. Fügen Sie eine Identitätsspalte hinzu, um eine eindeutige ID pro Ausdruck zu erstellen, und erstellen Sie 12-Zeichen-Spalten. Parsen Sie dann die Ausdrücke und setzen Sie jedes Wort jedes Abschnitts in eine separate Spalte. Dies wird aussehen (ich habe nicht alle 12 Spalten dargestellt, aber die Idee ist unten):

%Vor%

Es gibt leere Spalten (da es nur sehr wenige Ausdrücke mit 12 Wörtern gibt), aber das spielt keine Rolle.

Dann replizieren wir die Tabelle und erstellen einen Index für jede ... Spalte. Wir führen 12 Joins durch, die ähnliche Wörter suchen, etwa

%Vor%

Wir sammeln die Ausgabe in 12 temporären Tabellen und führen eine Vereinigungsabfrage der 12 Tabellen durch, um eine kurze Liste aller Ausdrücke zu erhalten, die potentielle übereinstimmende Ausdrücke mit mindestens einem identischen Wort haben. Dies ist die Lösung für unsere Herausforderung A. Wir haben jetzt eine kurze Liste der wahrscheinlich passenden Paare. Diese Liste enthält Millionen von Datensätzen (Paare von linken und rechten Einträgen), aber keine Milliarden.

HERAUSFORDERUNG B

Das Ziel von Herausforderung B besteht darin, eine vereinfachte Levenstein-Distanz im Stapel zu verarbeiten (anstatt sie in einer Schleife auszuführen). Zuerst sollten wir uns einigen, was eine vereinfachte Levenstein-Distanz ist. Zuerst stimmen wir zu, dass die levenstein-Distanz zweier Ausdrücke die Summe der levenstein-Distanz aller Wörter der beiden Ausdrücke ist, die denselben Index haben.Ich meine die Levenstein-Distanz von zwei Ausdrücken ist die Entfernung ihrer zwei ersten Wörter plus der Abstand ihrer zwei zweiten Wörter usw. Zweitens müssen wir eine vereinfachte Levenstein-Distanz erfinden. Ich schlage vor, den N-Gramm-Ansatz mit nur zwei Gramm Zeichen zu verwenden, die einen absoluten Indexunterschied von weniger als 2 haben.

z.B. Der Abstand zwischen Peter und Pieter wird wie folgt berechnet:

%Vor%

Peter und Pieter haben 4 gemeinsame 2-Gramm mit einer absoluten Indexdifferenz von weniger als 2 'et', 'te', 'er', 'r_'. Es gibt 6 mögliche 2-Gramm in der größten der beiden Wörter, die Entfernung ist dann 6-4 = 2 - Die Levenstein-Entfernung wäre auch 2, weil es eine Bewegung von 'eter' und eine Buchstabeneinfügung 'i' gibt.

Dies ist eine Annäherung, die nicht in allen Fällen funktionieren wird, aber ich denke, in unserer Situation wird es sehr gut funktionieren. Wenn wir mit der Qualität der Ergebnisse nicht zufrieden sind, können wir es mit 3 Gramm oder 4 Gramm versuchen oder einen Sequenzunterschied von mehr als 2 Gramm ermöglichen. Aber die Idee ist, viel weniger Berechnungen pro Paar durchzuführen als im traditionellen Levenstein-Algorithmus.

Dann müssen wir das in eine technische Lösung umwandeln. Was ich vorher gemacht habe, ist folgendes: Isoliere zuerst die Wörter: da wir nur die Entfernung zwischen den Wörtern messen müssen, und dann diese Abstände pro Ausdruck summieren, können wir die Anzahl der Berechnungen weiter reduzieren, indem wir eine bestimmte Auswahl auf der Wörterliste ausführen (wir haben bereits die Liste vorbereitet Wörter im vorherigen Abschnitt).

Dieser Ansatz erfordert eine Zuordnungstabelle, die die Ausdrucks-ID, die Abschnitts-ID, die Wort-ID und die Wortfolgenummer für das Wort verfolgt, so dass die ursprüngliche Ausdrucksdistanz am Ende des Prozesses berechnet werden kann.

Wir haben dann eine neue Liste, die viel kürzer ist und eine Kreuzverbindung aller Wörter enthält, für die das 2-Gramm-Abstandsmaß relevant ist. Dann wollen wir diese 2-Gramm-Distanzmessung im Batch-Verfahren verarbeiten, und ich schlage vor, dies in einem SQL-Join zu tun. Dies erfordert einen Vorverarbeitungsschritt, der darin besteht, eine neue temporäre Tabelle zu erstellen, die alle 2 Gramm in einer separaten Zeile speichert - und das Wort Id, die Wortfolge und den Abschnittstyp verfolgt

Dies geschieht technisch, indem man die Liste der Wörter mit einer Reihe (oder einer Schleife) der Teilzeichenfolge schneidet, wie folgt (unter der Annahme der Wortlistentabellen gibt es zwei Kopien, eine links und eine rechts - enthalten zwei Spalten word_id und Wort):

%Vor%

Und dann

%Vor%

usw.

Etwas, das "Steward" so aussehen lässt (angenommen, das Wort id ist 152)

%Vor%

Vergessen Sie nicht, einen Index für die Spalten word_id, gram und gram_seq zu erstellen, und die Entfernung kann mit einem Join der linken und rechten Grammliste berechnet werden, wobei ON wie

aussieht %Vor%

Die Entfernung ist die Länge des längsten der beiden Wörter minus der Anzahl der übereinstimmenden Gramm. SQL ist extrem schnell, eine solche Abfrage zu machen, und ich denke, ein einfacher Computer mit 8 Gigabyte RAM würde leicht mehrere hundert Millionen Zeilen in einem vernünftigen Zeitrahmen tun.

Und dann ist es nur eine Frage der Zuordnungstabelle, um die Summe der Wort-zu-Wort-Distanz in jedem Ausdruck zu berechnen, um den Gesamtausdruck zum Ausdruck zu bringen.

    
___ answer48178729 ___

Sie verwenden das %code% -Paket trotzdem, passt %code% Ihren Anforderungen? Er berechnet den Soundex-Code für jeden String, zB:

%Vor%

Soundex ist eine altbewährte Methode (fast 100 Jahre alt) für Hash-Namen, und das bedeutet, dass Sie nicht jedes einzelne Beobachtungspaar vergleichen müssen.

Vielleicht möchten Sie weiter gehen und den Vornamen und den Nachnamen separat für Vater und Mutter angeben.

    
___
JeromeE 04.01.2018 22:31
quelle
6

Sie verwenden das stringdist -Paket trotzdem, passt stringdist::phonetic() Ihren Anforderungen? Er berechnet den Soundex-Code für jeden String, zB:

%Vor%

Soundex ist eine altbewährte Methode (fast 100 Jahre alt) für Hash-Namen, und das bedeutet, dass Sie nicht jedes einzelne Beobachtungspaar vergleichen müssen.

Vielleicht möchten Sie weiter gehen und den Vornamen und den Nachnamen separat für Vater und Mutter angeben.

    
Neal Fultz 10.01.2018 00:39
quelle
5

Mein Vorschlag ist, einen datenwissenschaftlichen Ansatz zu verwenden, um nur ähnliche (gleiche Cluster-) Namen zu identifizieren, die mit stringdist verglichen werden.

Ich habe ein bisschen den Code geändert, der "elternsname" generiert, was mehr Variabilität in den ersten und zweiten Namen in einem realitätsnahen Szenario hinzufügt.

%Vor%

Hier starten Sie die echte Analyse, zuerst extrahieren Sie das Merkmal aus den Namen wie globale Länge, Länge des ersten, Länge des zweiten, Anzahl der Vokale und Konsonanten in beiden ersten und zweiten Namen (und alle anderen von Interesse).

Danach binden Sie alle diese Features und clustern das data.frame in einer hohen Anzahl von Clustern (zB 1000)

%Vor%

Übernehmen Sie stringdistmatrix nur innerhalb jedes Clusters (mit ähnlichen Namen)

%Vor%

In dist_matrix haben Sie den Abstand zwischen jedem Element im Cluster und können die family_id mit diesem Abstand zuweisen.

Um den Abstand in jedem Cluster (in diesem Beispiel) zu berechnen, benötigt der Code ungefähr 1 Sekunde (abhängig von der Dimension des Clusters), in 15 Minuten werden alle Entfernungen berechnet.

WARNUNG : dist_matrix wächst sehr schnell, in Ihrem Code ist besser, wenn Sie es innerhalb di for Schleife analysieren extrahieren famyli_id und dann können Sie es verwerfen.

    
Terru_theTerror 04.01.2018 15:41
quelle
2

Sie können sich verbessern, indem Sie nicht alle Linienpaare vergleichen. Erstellen Sie stattdessen eine neue Variable, die Ihnen hilft, zu entscheiden, ob es sich lohnt zu vergleichen.

Erstellen Sie zum Beispiel eine neue Variable "score", die die geordnete Liste der in elternsname verwendeten Buchstaben enthält (zum Beispiel wenn "Peter pan + marta steward" dann die Punktzahl "ademnprstw" ist), und berechnen Sie nur die Entfernung zwischen den Zeilen Ergebnis stimmt überein.

Natürlich können Sie eine Punktzahl finden, die besser zu Ihrem Bedarf passt, und ein wenig verbessern, um einen Vergleich zu ermöglichen, wenn nicht alle verwendeten Buchstaben üblich sind.

    
MrSmithGoesToWashington 04.01.2018 14:07
quelle
1

Ich hatte vor ein paar Jahren das gleiche Leistungsproblem. Ich musste die Duplikate der Leute basierend auf ihren eingegebenen Namen vergleichen. Mein Datensatz hatte 200.000 Namen und der Matrix-Ansatz explodierte. Nachdem ich eines Tages nach einer besseren Methode gesucht habe, hat die Methode, die ich hier vorschlage, in wenigen Minuten die Arbeit für mich erledigt:

%Vor%

Auf diese Weise vergleicht while bei jeder Iteration weniger Übereinstimmungen. Daraus können Sie verschiedene Leistungssteigerungen implementieren, wie das Filtern der Namen mit dem gleichen Anfangsbuchstaben vor dem Vergleich usw.

    
Anderson Neisse 10.01.2018 12:03
quelle
1

Es macht keinen Sinn, Äquivalenzgruppen für nicht transitive Beziehungen zu erstellen. Wenn A ist wie B und B ist wie C , aber A ist nicht wie C , wie würdest du daraus Familien machen? Etwas wie Soundex zu verwenden (das war die Idee von Neal Fultz, nicht meiner) scheint die einzig sinnvolle Option zu sein und es löst auch dein Problem mit der Leistung.

    
Antonín Lejsek 11.01.2018 03:18
quelle
1

Was ich verwendet habe, um die Permutationen zu reduzieren, die bei dieser Art von Namensabgleich eine Rolle spielen, ist die Erstellung einer Funktion, die die Silben im Namen (Nachnamen) zählt. Dann speichern Sie dies in der Datenbank als vorverarbeiteten Wert. Dies wird zu einer Funktion Syllable Hash .

Dann können Sie wählen, Wörter zusammen mit der gleichen Anzahl von Silben zu gruppieren. (Obwohl ich Algorithmen verwende, die 1 oder 2 Silben Unterschied erlauben, die als legitime Rechtschreib- / Tippfehler angezeigt werden können ... Aber meine Forschung hat herausgefunden, dass 95% der Rechtschreibfehler die gleiche Anzahl von Silben teilen)

In diesem Fall hätten Peter und Pieter die gleiche Silbenzahl (2), aber Jones und Smith nicht (sie haben 1). (Zum Beispiel)

Wenn Ihre Funktion keine 1 Silbe für Jones erhält, müssen Sie möglicherweise Ihre Toleranz erhöhen, um einen Unterschied von mindestens 1 Silbe in der von Ihnen verwendeten Syllable Hash-Funktionsgruppierung zu berücksichtigen. (Um falsche Silbenfunktionsergebnisse zu berücksichtigen und den übereinstimmenden Nachnamen in der Gruppierung korrekt abzufangen)

Meine Silbenzählfunktion ist möglicherweise nicht vollständig anwendbar - da Sie möglicherweise nicht-englische Buchstabensätze verarbeiten müssen ... (Also habe ich den Code nicht eingefügt ... Seiner ist sowieso C) Wohlgemerkt - die Silbenzählfunktion muss nicht in Bezug auf die TRUE Silbenanzahl genau sein; es muss einfach als zuverlässige Hashing-Funktion fungieren - was es tut. SoundEx ist weit überlegen, da der erste Buchstabe genau ist.

Probieren Sie es aus, Sie werden überrascht sein, wie viel Verbesserung Sie durch die Implementierung einer Syllable Hash-Funktion erzielen. Möglicherweise müssen Sie SO um Hilfe bitten, damit die Funktion in Ihre Sprache übernommen wird.

    
Grantly 11.01.2018 16:37
quelle
0

Wenn ich es richtig verstanden habe, möchten Sie jedes Elternpaar (jede Zeile im Datenrahmen parent_name) mit allen anderen Paaren (Zeilen) vergleichen und Zeilen mit Levenstein-Abstand kleiner oder gleich 2 behalten.

Ich habe folgenden Code für den Anfang geschrieben:

%Vor%

Gibt es zurück, was Sie wollten?

    
Mislav 04.01.2018 14:31
quelle
0

es reproduziert Ihre Ausgabe, ich denke, Sie müssen teilweise übereinstimmende Kriterien entscheiden, ich habe die Standard-Agrep diejenigen beibehalten

%Vor%     
Antonis 11.01.2018 11:56
quelle