2014-05-25 58 views
1

我有一個List<String[]> Java(從數據庫)的客戶記錄。我從人工眼球知道25%+是重複的數據。在Java中的模糊匹配重複

儘管重複的內容還很不準確。有時他們有不同的拉鍊,但名稱和地址相同。其他時間的地址是完全丟失,等...

經過一天的研究;對於如何開始解決這個問題,我仍然很難過?

什麼是我應該用Google來描述這個領域的「術語」(從Java解析這個角度)?我不認爲那裏有fuzzymatch.jar,這只是爲了簡單?

+0

編輯距離的算法,如Levenshtein距離或漢明距離可能他們的推導。 – Brandon

+1

盧塞恩和Solr是用Java編寫的功能工具的模糊匹配,等等。 –

+0

Levenshtein只能在字符串上工作嗎?不是一組字符串? – Kong

回答

2

我之前做過類似的系統來匹配地點信息和人員信息。這些是具有許多特徵的複雜對象,並計算出兩個不同的對象是描述同一個地方還是人是棘手的。做到這一點的方法是將其分解爲基本要素。

這裏有幾件事情,你可以做:

0)如果這是一個oneoff,將數據加載到openrefine和交互解決的事情。最大限度地解決了您的問題,最低限度會顯示您可能匹配的位置。

1)有幾種方法可以比較字符串。基本上它們在產生負面和錯誤匹配方面的可靠程度不同。否定匹配是匹配時不匹配。積極的匹配是它應該匹配的時候。字符串等於不會產生負面的比賽,但會由於輕微的變化而錯過很多潛在的比賽。帶有小因素的萊文斯坦稍微好一些。 Ngrams產生很多匹配,但其中許多將是錯誤的。還有幾個算法,看看例如openrefine代碼來查找比較和聚類字符串的各種方法。 Lucene在它的分析器框架中實現了很多這些東西,但如果你對它的設計不是很熟悉的話,它有點像野獸一樣。

2)將決定你是否匹配的過程分開。我過去所做的就是使用一個簡單的數字分數來限定我的比較。該字段完全匹配(100),但該字段是部分匹配(75),該字段完全不匹配。合格的比較結果向量,例如(100,75,0,25)可以與定義完美或部分匹配標準的參考矢量進行比較。例如,如果名字,姓氏和街道匹配,那麼無論其餘字段如何,這兩個記錄都是相同的。或者如果電話號碼和姓氏匹配,那也是有效的匹配。您可以將這種完美匹配作爲矢量進行編碼,然後將其與比較矢量進行比較,以確定它是匹配,不匹配還是部分匹配。這是一種機器學習的手動版本,它將提取特徵向量,然後建立一個概率模型,其中向量表示參考數據的向量。手動操作,可以解決簡單的問題。

3)根據您知道匹配或不匹配的測試用例組建一個參考數據集,並根據該參考集評估您的算法。這樣,當你調整時,你會知道什麼時候你正在改善事情或者變得更糟。進入萊文斯坦或其他因素。

1

吉勒斯的答案很棒,來自經驗。我還必須努力清理大型雜亂的桌子,並且當時對我的選擇知之甚少(我最終使用了Excel和許多自動過濾器)。希望我瞭解OpenRefine。

但是,如果你能,你必須編寫自定義代碼來做到這一點,我想提出一個建議至於怎樣點:本欄目始終是相同的,對不對?例如,第一個字符串總是關鍵字,第二個是名字,第六個是郵政編碼,第十個是傳真號碼等等?

假設有沒有場的不合理號碼,我會與具有各個DB字段作爲成員,而不是在陣列中的位置的自定義記錄類型開始。類似於

class CustomerRow { 
    public final String id; 
    public final String firstName; 
    // ... 

    public CustomerRow(String[] data) { 
     id = data[0]; 
     // ... 
} 

如果您知道存在您總是想要過濾掉的垃圾值,那麼您還可以在構造函數中包含一些驗證代碼。

(請注意,你基本上是做一個ORM會自動做什麼,但有一個起步很可能比剛寫入記錄類型更多的工作。)

然後你會實現一些Comparator<CustomerRow> S的只看特定的領域,或者定義模糊術語的平等(編輯距離算法會派上用場的地方),或者做特殊的分類。

Java使用的對象一個穩定的排序,所以通過例如進行排序名稱,然後是地址,然後是鍵,您只需進行每種排序,但按相反順序選擇比較器。

此外,如果你有機會到實際的數據庫,它是一個真正的關係型數據庫,我建議你做一些你的搜索查詢,如在可能的情況。如果您需要在Java對象和數據庫之間來回切換,那麼使用ORM可能會是一個不錯的選擇。