2014-05-25 59 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可能会是一个不错的选择。