2012-06-15 18:29:24 +0000 2012-06-15 18:29:24 +0000
14
14
Advertisement

Сравнение аналогичных текстовых строк в Excel

Advertisement

В настоящее время я пытаюсь примирить поля “Имя” из двух отдельных источников данных. У меня есть несколько имен, которые не являются точным совпадением, но достаточно близки, чтобы их можно было считать совпаденными (примеры ниже). У вас есть идеи, как я могу улучшить количество автоматических совпадений? Я уже устраняю средние инициалы из критериев соответствия.

=IFERROR(IF(LEFT(SYSTEM A,IF(ISERROR(SEARCH(" ",SYSTEM A)),LEN(SYSTEM A),SEARCH(" ",SYSTEM A)-1))=LEFT(SYSTEM B,IF(ISERROR(SEARCH(" ",SYSTEM B)),LEN(SYSTEM B),SEARCH(" ",SYSTEM B)-1)),"",IF(LEFT(SYSTEM A,FIND(",",SYSTEM A))=LEFT(SYSTEM B,FIND(",",SYSTEM B)),"Last Name Match","RESEARCH")),"RESEARCH")

Текущая формула матча:

Advertisement
Advertisement

Ответы (7)

12
12
12
2012-06-15 18:51:25 +0000

Вы можете рассмотреть возможность использования Microsoft Fuzzy Lookup Addin .

с сайта MS:

Обзор

Нечеткий Поисковый модуль для Excel был разработан Microsoft Research и выполняет нечеткое совпадение текстовых данных в Microsoft Excel. Оно может быть использовано для идентификации нечетких дублирующих друг друга строк внутри одной таблицы или для нечеткого соединения похожих строк между двумя разными таблицами. Сопоставление устойчиво к широкому спектру ошибок, включая орфографические ошибки, аббревиатуры, синонимы и добавленные/пропущенные данные. Например, может быть обнаружено, что строки “Мистер Эндрю Хилл”, “Хилл, Эндрю R.” и “Энди Хилл” относятся к одному и тому же базовому сущности, возвращая счет схожести вместе с каждым совпадением. Хотя конфигурация по умолчанию хорошо работает с большим разнообразием текстовых данных, таких как названия продуктов или адреса клиентов, соответствие может быть также настроено для определенных доменов или языков.

6
6
6
2012-06-15 19:47:53 +0000

Я бы посмотрел, как использовать этот список (только на английском языке), чтобы помочь избавиться от общих сокращений.

Добавление, возможно, вы захотите подумать об использовании функции, которая точно скажет вам, насколько “закрыты” две строки. Следующий код пришел из здесь и благодаря smirkingman .

Option Explicit
Public Function Levenshtein(s1 As String, s2 As String)

Dim i As Integer
Dim j As Integer
Dim l1 As Integer
Dim l2 As Integer
Dim d() As Integer
Dim min1 As Integer
Dim 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

Это скажет вам, сколько вставок и удалений нужно сделать в одной строке, чтобы попасть в другую. Я постараюсь сохранить это число на низком уровне (а фамилии должны быть точными).

5
Advertisement
5
5
2015-10-09 14:26:12 +0000
Advertisement

У меня есть (длинная) формула, которую вы можете использовать. Она не так хорошо отточена, как выше - и работает только для фамилии, а не для полного имени - но вы можете найти ее полезной.

Так что если у вас есть строка заголовка и вы хотите сравнить A2 с B2, поместите ее в любую другую ячейку этой строки (например, C2) и скопируйте до конца.

=IF(A2=B2, “EXACT”,IF(SUBSTITUTE(A2, “-”,“ ”)=SUBSTITUTE(B2, “-”,“ ”), “Hyphen”,IF(LEN(A2)>LEN(B2),IF(LEN(A2)>LEN(SUBSTITUTE(A2,B2,“)), "Целая строка”,IF(MID(A2,1, 1)=MID(B2,1,1),1,0)+IF(MID(A2,2,1)=MID(B2,2,1),1,0)+IF(MID(A2,3,1)=MID(B2,3,1),1,0)+IF(MID(A2,LEN(A2),1)=MID(B2,LEN(B2),1),1,0)+IF(MID(A2,LEN(A2)-1,1)=MID(B2,LEN(B2)-1,1),1, 0)+IF(MID(A2,LEN(A2)-2,1)=MID(B2,LEN(B2)-2,1),1,0)&“°”),IF(LEN(B2)>LEN(SUBSTITUTE(B2,A2,“)), "Целая строка”,IF(MID(A2,1,1)=MID(B2,1,1),1,0)+IF(MID(A2,2,1)=MID(B2,2,1),1, 0)+IF(MID(A2,3,1)=MID(B2,3,1),1,0)+IF(MID(A2,LEN(A2),1)=MID(B2,LEN(B2),1),1,0)+IF(MID(A2,LEN(A2)-1,1)=MID(B2,LEN(B2)-1,1),1,0)+IF(MID(A2,LEN(A2)-2,1)=MID(B2,LEN(B2)-2,1),1,0)&“°”)))).

Это вернется:

  • EXACT - если это точное совпадение
  • Дефис - если это пара двойных имен, но на них есть дефис, а на другом пробел
  • Капитальная строка - если все одна фамилия является частью другой (например, если кузнец стал французским кузнецом)

После этого вы получите градус от 0° до 6° в зависимости от количества точек сравнения между ними. (т.е. 6° сравнивается лучше).

Как я уже сказал, немного грубовато и готово, но надеюсь, что вы попадёте примерно в нужный шаровой парк.

2
2
2
2016-06-23 06:12:19 +0000

искал что-то похожее. Я нашел код ниже. Надеюсь, это поможет следующему пользователю, который подойдет к этому вопросу

Возвращает 91% для Абракадабра / Абракадабра, 75% для Голливуд Стрит / Холлид Стрит, 62% для Флоренции / Франс и 0 для Диснейленда

Я бы сказал, что это достаточно близко к тому, что вы хотели :).

Public Function Similarity(ByVal String1 As String, _
    ByVal String2 As String, _
    Optional ByRef RetMatch As String, _
    Optional min_match = 1) As Single
Dim b1() As Byte, b2() As Byte
Dim lngLen1 As Long, lngLen2 As Long
Dim lngResult As Long

If UCase(String1) = UCase(String2) Then
    Similarity = 1
Else:
    lngLen1 = Len(String1)
    lngLen2 = Len(String2)
    If (lngLen1 = 0) Or (lngLen2 = 0) Then
        Similarity = 0
    Else:
        b1() = StrConv(UCase(String1), vbFromUnicode)
        b2() = StrConv(UCase(String2), vbFromUnicode)
        lngResult = Similarity_sub(0, lngLen1 - 1, _
        0, lngLen2 - 1, _
        b1, b2, _
        String1, _
        RetMatch, _
        min_match)
        Erase b1
        Erase b2
        If lngLen1 >= lngLen2 Then
            Similarity = lngResult / lngLen1
        Else
            Similarity = lngResult / lngLen2
        End If
    End If
End If

End Function

Private Function Similarity_sub(ByVal start1 As Long, ByVal end1 As Long, _
                                ByVal start2 As Long, ByVal end2 As Long, _
                                ByRef b1() As Byte, ByRef b2() As Byte, _
                                ByVal FirstString As String, _
                                ByRef RetMatch As String, _
                                ByVal min_match As Long, _
                                Optional recur_level As Integer = 0) As Long
'* CALLED BY: Similarity *(RECURSIVE)

Dim lngCurr1 As Long, lngCurr2 As Long
Dim lngMatchAt1 As Long, lngMatchAt2 As Long
Dim I As Long
Dim lngLongestMatch As Long, lngLocalLongestMatch As Long
Dim strRetMatch1 As String, strRetMatch2 As String

If (start1 > end1) Or (start1 < 0) Or (end1 - start1 + 1 < min_match) _
Or (start2 > end2) Or (start2 < 0) Or (end2 - start2 + 1 < min_match) Then
    Exit Function '(exit if start/end is out of string, or length is too short)
End If

For lngCurr1 = start1 To end1
    For lngCurr2 = start2 To end2
        I = 0
        Do Until b1(lngCurr1 + I) <> b2(lngCurr2 + I)
            I = I + 1
            If I > lngLongestMatch Then
                lngMatchAt1 = lngCurr1
                lngMatchAt2 = lngCurr2
                lngLongestMatch = I
            End If
            If (lngCurr1 + I) > end1 Or (lngCurr2 + I) > end2 Then Exit Do
        Loop
    Next lngCurr2
Next lngCurr1

If lngLongestMatch < min_match Then Exit Function

lngLocalLongestMatch = lngLongestMatch
RetMatch = ""

lngLongestMatch = lngLongestMatch _
+ Similarity_sub(start1, lngMatchAt1 - 1, _
start2, lngMatchAt2 - 1, _
b1, b2, _
FirstString, _
strRetMatch1, _
min_match, _
recur_level + 1)
If strRetMatch1 <> "" Then
    RetMatch = RetMatch & strRetMatch1 & "*"
Else
    RetMatch = RetMatch & IIf(recur_level = 0 _
    And lngLocalLongestMatch > 0 _
    And (lngMatchAt1 > 1 Or lngMatchAt2 > 1) _
    , "*", "")
End If

RetMatch = RetMatch & Mid$(FirstString, lngMatchAt1 + 1, lngLocalLongestMatch)

lngLongestMatch = lngLongestMatch _
+ Similarity_sub(lngMatchAt1 + lngLocalLongestMatch, end1, _
lngMatchAt2 + lngLocalLongestMatch, end2, _
b1, b2, _
FirstString, _
strRetMatch2, _
min_match, _
recur_level + 1)

If strRetMatch2 <> "" Then
    RetMatch = RetMatch & "*" & strRetMatch2
Else
    RetMatch = RetMatch & IIf(recur_level = 0 _
    And lngLocalLongestMatch > 0 _
    And ((lngMatchAt1 + lngLocalLongestMatch < end1) _
    Or (lngMatchAt2 + lngLocalLongestMatch < end2)) _
    , "*", "")
End If

Similarity_sub = lngLongestMatch

End Function
1
Advertisement
1
1
2015-10-30 10:56:53 +0000
Advertisement

Данный код сканирует столбец a и столбец b, если находит сходство в обоих столбцах, он отображается желтым цветом. Вы можете использовать цветовой фильтр для получения конечного значения. Я не добавлял эту часть в код.

Sub item_difference()

Range("A1").Select

last_row_all = Range("A65536").End(xlUp).Row
last_row_new = Range("B65536").End(xlUp).Row

Range("A1:B" & last_row_new).Select
With Selection.Interior
    .Pattern = xlSolid
    .PatternColorIndex = xlAutomatic
    .Color = 65535
    .TintAndShade = 0
    .PatternTintAndShade = 0
End With

For i = 1 To last_row_new
For j = 1 To last_row_all

If Range("A" & i).Value = Range("A" & j).Value Then

Range("A" & i & ":B" & i).Select
With Selection.Interior
    .Pattern = xlSolid
    .PatternColorIndex = xlAutomatic
    .ThemeColor = xlThemeColorDark1
    .TintAndShade = 0
  .PatternTintAndShade = 0
End With

End If
Next j
Next i
End Sub
1
1
1
2016-09-14 12:14:05 +0000

Хотя мое решение не позволяет идентифицировать очень разные строки, оно полезно для частичного совпадения (сравнения подстрок), например, “это строка” и “строка” получится как “совпадение”:

** просто добавьте “*” до и после строки для поиска в таблице.**

Обычная формула:

  • vlookup(A1,B1:B10,1,0)
  • cerca.vert(A1;B1:B10;1;0)

становится

  • vlookup(“*” & A1 & “*”,B1:B10;1,0)
  • cerca. vert(“*” & A1 & “*”;B1:B10;1;0) 0x2 & 0x2 & “&” - это “короткая версия” для concatenate().
1
Advertisement
1
1
2015-02-05 02:42:16 +0000
Advertisement

Вы можете использовать функцию сходства (pwrSIMILARITY), чтобы сравнить строки и получить процентное совпадение. Вы можете сделать ее чувствительной к регистру или нет. Вам нужно будет решить, какой процент совпадения “достаточно близок” для ваших нужд.

Там есть справочная страница по адресу http://officepowerups.com/help-support/excel-function-reference/excel-text-analyzer/pwrsimilarity/ .

Но она довольно хорошо работает для сравнения текста в колонке A со столбцом B.

Advertisement

Похожие вопросы

6
13
9
10
17
Advertisement
Advertisement