Excelでの類似のテキスト文字列の比較


14

現在、2つの別個のデータソースから「名前」フィールドを調整しようとしています。完全には一致していませんが、一致すると見なされるほど近い名前がいくつかあります(下の例を参照)。自動一致の数をどのように改善できるかについてのアイデアはありますか?私はすでに一致基準からミドルネームのイニシャルを削除しています。

ここに画像の説明を入力してください

現在の一致式:

=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")

回答:


12

あなたは使用を検討するかもしれません Microsoft Fuzzy Lookup Addinの

MSサイトから:

概要

Excelのファジールックアップアドインは、Microsoft Researchによって開発され、Microsoft Excelのテキストデータのファジーマッチングを実行します。単一のテーブル内のファジー重複行を識別したり、2つの異なるテーブル間で類似する行をファジー結合するために使用できます。この照合は、スペルミス、略語、同義語、追加/欠落データなど、さまざまなエラーに対して堅牢です。たとえば、「Mr。アンドリュー・ヒル」、「ヒル、アンドリュー・R」および「Andy Hill」はすべて同じ基礎エンティティを参照し、各一致とともに類似度スコアを返します。デフォルトの構成は、製品名や顧客の住所など、さまざまなテキストデータに対して適切に機能しますが、特定のドメインまたは言語に対して一致をカスタマイズすることもできます。


.net frameworkが必要なため、管理者権限が必要なため、アドオンをオフィスにインストールできません。:-(
ジャンプジャック

これは素晴らしいことですが、10行以上を生成することはできません。私は成功せずに設定をクリックしました。任意のヒント?
ビョルンテ16

6

私はこれを使用することを検討しますリスト(英語のセクションのみ)をして、一般的な短縮を取り除くのに役立てます。

さらに、2つの文字列がどの程度「近い」かを正確に示す関数の使用を検討することもできます。次のコードはここから来ました。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

使用できる(長い)数式があります。それは上記のものほど磨かれていません-そして、フルネームではなく姓でのみ動作します-しかし、あなたはそれが役に立つかもしれません。

そのため、ヘッダー行があり、と比較する場合A2B2、これをその行の他のセル(例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 -それは完全一致だ場合
  • ハイフン -二重バレルの名前のペアであるが、ハイフンがあり、もう1つがスペースである場合
  • 文字列全体 –ある姓がすべて他の姓の一部である場合(たとえば、スミスがフランス語スミスになった場合)

その後、2つの比較ポイントの数に応じて、0°から6°の程度が与えられます。(つまり、6°の方が優れています)。

私は少し荒く準備ができていると言いますが、うまくいけばおおよそ正しい球場にあなたを連れて行きます。


これはすべてのレベルで過小評価されています。とてもうまくできました!たぶん、これに何かアップデートがありますか?
DeerSpotter

2

同様のものを探していました。以下のコードを見つけました。これがこの質問に来た次のユーザーに役立つことを願っています

アブラカダブラ/アブラカダブラで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

クレジットを与えずにこの回答からコードをコピーしています
-phuclv

1

類似度関数(pwrSIMILARITY)を使用して、文字列を比較し、2つの一致率を取得できます。大文字と小文字を区別するかどうかを選択できます。マッチの何パーセントがあなたのニーズに「十分近い」かを決める必要があります。

http://officepowerups.com/help-support/excel-function-reference/excel-text-analyzer/pwrsimilarity/にリファレンスページがあります。

しかし、列Aのテキストと列Bを比較する場合は非常にうまく機能します。


1

私のソリューションではまったく異なる文字列を識別できませんが、部分一致(部分文字列一致)には役立ちます。たとえば、「this is a string」と「a string」は「matching」になります。

テーブルを検索する文字列の前後に「*」を追加するだけです。

通常の式:

  • 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)

「&」は、concatenate()の「ショートバージョン」です。


1

このコードは、列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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.