Formel zum Finden nahezu perfekter Übereinstimmungen [Duplikat]


7

Ich habe eine Liste mit + -8000 Elementen, die das Ergebnis ist, nachdem zahlreiche Techniken zum Entfernen von Duplikaten angewendet wurden (die Liste begann bei über 10000 Elementen).

Ich habe jetzt das folgende Problem -

Beispiel 1. Jack Daniel 2. Jack Daniels 3. Jack Daniels

Alle oben genannten Punkte beziehen sich eindeutig auf einen Artikel, sind jedoch technisch immer noch einzigartig. Ich habe versucht, die ersten 4 Buchstaben zu ziehen und nach Übereinstimmungen zu suchen, aber es gab + -4000 und die meisten von ihnen waren falsch positiv, dh

  1. Jack Dxxx
  2. Jack Bxxx

Beide würden Jack ziehen, wären aber kein gültiges Duplikat.

Irgendwelche Gedanken?


4
Möglicherweise müssen Sie den Levenshtein-Abstand zwischen den einzelnen Elementen überprüfen und die Datensätze mit einem geringen Abstand melden.
Zoredache

@Zoredache wie würdest du das in Excel machen?
James Jenkins

Keine Ahnung. Das überlasse ich Ihnen. Oder vielleicht jemand anderes, der die Zeit damit verbringen möchte, eine vollständige Antwort zu schreiben.
Zoredache

Excel verfügt dazu über keine integrierte Funktionalität. Sie müssen ein Add-In installieren (es gibt einige, die jedoch nicht kostenlos sind). Schauen Sie sich open refine an, das kostenlos ist: youtube.com/watch?feature=player_embedded&v=B70J_H_zAWM , ich hatte das gleiche Problem und es hat es für mich gelöst (und es ist sehr einfach, Daten von / nach Excel zu übertragen).
Ioannis

Antworten:


3

Basierend auf Zoredaches Kommentar ist hier meine Beispielarbeitsmappe mit VBA und Levenshtein Distance , um ähnliche Zeichenfolgen in einer großen Liste zu finden. Es basiert auf den Antworten von @smirkingman und @ Apostolos55 zum Stackoverflow .

Der Levenshtein-Abstand zwischen zwei Wörtern ist die Mindestanzahl von Einzelzeichenänderungen (Einfügen, Löschen, Ersetzen), die erforderlich sind, um ein Wort in das andere zu ändern

Ich habe zwei verschiedene Versionen implementiert. Bitte überprüfen Sie, welche Funktion für Ihren Fall mit 8000 Werten schneller ist. Wenn Sie neugierig sind, sehen Sie sich den vollständigen VBA- Code auf Github an . Erhöhen Sie den Schwellenwert in der Zeile, const treshold = 1wenn Sie Ergebnisse mit mehr als einer erforderlichen Bearbeitung wünschen, um irgendwo eine Übereinstimmung zu erzielen.

Geben Sie hier die Bildbeschreibung ein

  • Formelsyntax: =LevenshteinCompare( <cell_to_check> , <range_to_search_in> )
    Beispiel: =LevenshteinCompare(A2;A$2:A$12)(Beachten Sie den festen Bereich)
  • Ausgabesyntax: <number_of_required_edits> - [<match_address>] <match_value>

Private Function Levenshtein(S1 As String, S2 As String)

Dim i As Integer, j As Integer
Dim l1 As Integer, l2 As Integer
Dim d() As Integer
Dim min1 As Integer, min2 As Integer

l1 = Len(S1)
l2 = Len(S2)
ReDim d(l1, l2)
For i = 0 To l1
    d(i, 0) = i
Next
For j = 0 To l2
    d(0, j) = j
Next
For i = 1 To l1
    For j = 1 To l2
        If Mid(S1, i, 1) = Mid(S2, j, 1) Then
            d(i, j) = d(i - 1, j - 1)
        Else
            min1 = d(i - 1, j) + 1
            min2 = d(i, j - 1) + 1
            If min2 < min1 Then
                min1 = min2
            End If
            min2 = d(i - 1, j - 1) + 1
            If min2 < min1 Then
                min1 = min2
            End If
            d(i, j) = min1
        End If
    Next
Next
Levenshtein = d(l1, l2)
End Function


Public Function LevenshteinCompare(S1 As Range, wordrange As Range)

Const treshold = 1
For Each S2 In Application.Intersect(wordrange, wordrange.Parent.UsedRange)
    oldRes = newRes
    newRes = Levenshtein(S1.Value, S2.Value)
    If oldRes < newRes And oldRes <> "" Or S1.Address = S2.Address Then
        newRes = oldRes
        newS2row = oldS2row
    Else
        oldS2 = S2
        oldS2row = S2.Address(0, 0)
    End If
    newS2 = oldS2
Next

If newRes <= treshold Then
    LevenshteinCompare = newRes & " - [" & newS2row & "]  " & newS2
Else
    LevenshteinCompare = ""
End If
End Function

Das hat Spaß gemacht ☜ (゚ ヮ ゚ ☜)


Gute Antwort! Ich kann mir vorstellen, diesen zu benutzen. In diesem Fall ist es möglicherweise besser, eine Funktion zu haben, die nur die Anzahl der Zellen zurückgibt, die N Bearbeitungen oder weniger entfernt sind (analog zu COUNTIF). Dies würde das Entfernen von Duplikaten erleichtern (da Sie nach der zweiten Spalte sortieren / filtern könnten).
Benshepherd

@benshepherd number of cells which are N edits or less away. Können Sie erklären, was Sie unter Anzahl der Zellen , Adresse und Gesamtbetrag verstehen ? Wenn Sie die Zeile LevenshteinCompare = newRes & " - [" & newS2row & "] " & newS2in ändern , sehen LevenshteinCompare = newResSie nur die Mindestanzahl an Änderungen, die erforderlich sind, um mit einer anderen Zelle
übereinzustimmen

Ich meinte, anstatt die minimale Anzahl von Änderungen über den gesamten Bereich zurückzugeben, wäre es nützlich, eine Funktion zu haben, die die Anzahl von Zellen in dem Bereich zählt, die 1 Bearbeitung oder weniger entfernt waren. (Da Sie normalerweise nach der minimalen Anzahl suchen, können Sie Ihre Vergleichsfunktion frühzeitig abbrechen, um sie schneller zu machen?)
Benshepherd

0

Verwenden Sie = len und wenn der Unterschied geringer ist, markieren Sie ihn als 2

und so etwas wie = mid (Value, (len_Value - 7), 4) markiert es als möglich betrogen.

In Kombination mit dem, was Sie bereits haben, sollten Sie ein viel besser machbares Set erhalten, mit dem Sie arbeiten können.

Bearbeiten

Formeln wie diese: Beachten Sie, dass "Jack Daniel" <> "Jack Berries" in G2. sieht aber wie ein mögliches Spiel überall anders aus. Sie müssten ein wenig modifizieren, um Ihren spezifischen Anforderungen zu entsprechen, aber es sollte eine überschaubare Anzahl erreichen.

C1 = IF (LINKS (A1,4) = LINKS (B1,4), "T", "F")

D1 = IF (LEN (A1) - LEN (B1) <= 2, "T", "F")

E1 = LEN (A1)

F1 = LEN (B1)

G1 = IF (MID (A1, (E1 - 7), 4) = MID (B1, (E1 - 7), 4), "T", "F")

Geben Sie hier die Bildbeschreibung ein


Vielen Dank für die Antwort James - Ich bin nicht sicher, wie ich die Formel "= mid (Value, (len_Value - 7), 4)" verwenden soll. Ich nehme an, der Wert ist die Zelle mit der Liste und len_value ist das Ergebnis von = len?
Brandon
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.