5

我试图想出一种基于相似度分数来查找重复地址的方法。考虑这些重复的地址:

addr_1 = '# 3 FAIRMONT LINK SOUTH'
addr_2 = '3 FAIRMONT LINK S'

addr_3 = '5703 - 48TH AVE'
adrr_4 = '5703- 48 AVENUE'

我计划应用一些字符串转换来使长单词缩写,如 NORTH -> N,删除所有空格、逗号和破折号以及井号。现在,有了这个输出,我如何将 addr_3 与其余地址进行比较并检测到相似之处?多少百分比的相似性是安全的?你能为此提供一个简单的python代码吗?

addr_1 = '3FAIRMONTLINKS'
addr_2 = '3FAIRMONTLINKS'

addr_3 = '570348THAV'
adrr_4 = '570348AV'

谢天谢地,

爱德华多

4

6 回答 6

2

删除空格、逗号和破折号将是不明确的。最好用一个空格替换它们。

以这个地址为例

56 5th avenue

还有这个

5, 65th avenue

使用您的方法,它们都将是:

565THAV

您可以做的是编写一个好的地址缩短算法,然后使用字符串比较来检测重复项。在一般情况下,这应该足以检测重复项。一般的相似性算法不起作用。因为一个数字差异可能意味着地址的巨大变化。

该算法可以是这样的:

  1. 用空格替换所有逗号破折号。为此使用他的翻译方法。
  2. 用单词及其缩写形式构建字典
  3. TH如果它跟随一个数字,请移除该部分。
于 2009-09-02T18:33:46.820 回答
2

这应该有助于构建您的缩写词词典:

https://pe.usps.com/text/pub28/28apc_002.htm

于 2009-09-02T19:27:55.730 回答
2

首先,通过将所有空格折叠到每个单词之间的单个空格来简化地址字符串,并强制所有内容为小写(如果您愿意,也可以为大写):

adr = " ".join(adr.tolower().split())

然后,我会去掉“41st Street”中的“st”或“42nd Street”中的“nd”之类的东西:

adr = re.sub("1st(\b|$)", r'1', adr)
adr = re.sub("([2-9])\s?nd(\b|$)", r'\1', adr)

请注意,第二个 sub() 将使用“2”和“nd”之间的空格,但我没有设置第一个这样做;因为我不确定您如何区分“41 St Ave”和“41 St”(第二个是“41 Street”的缩写)。

请务必阅读 re 模块的所有帮助;它功能强大但神秘。

然后,我会将您留下的内容拆分为单词列表,并应用 Soundex 算法列出看起来不像数字的项目:

http://en.wikipedia.org/wiki/Soundex

http://wwwhomes.uni-bielefeld.de/gibbon/Forms/Python/SEARCH/soundex.html

adrlist = [word if word.isdigit() else soundex(word) for word in adr.split()]

然后,您可以使用该列表或按照您认为最好的方式将其加入到字符串中。

Soundex 的整个想法是处理拼写错误的地址。这可能不是您想要的,在这种情况下,请忽略这个 Soundex 想法。

祝你好运。

于 2009-09-02T21:54:37.133 回答
1

我经常检查我工作的地址是否重复,我不得不说,我发现 Soundex 非常不合适。它既太慢又太急于匹配事物。我对 Levenshtein 距离有类似的问题。

对我来说最有效的是对地址进行清理和标记(去掉标点符号,将内容分成单词),然后看看有多少标记匹配。因为地址通常有多个令牌,所以您可以根据以下组合建立一定程度的置信度:(1) 匹配了多少令牌,(2) 匹配了多少数字令牌,以及 (3) 有多少令牌可用。例如,如果较短地址中的所有标记都在较长地址中,则匹配的置信度非常高。同样,如果您匹配 5 个令牌,其中至少有一个是数字的,即使每个地址都有 8 个,这仍然是一个高置信度匹配。

做一些调整肯定很有用,比如替换一些常见的缩写。USPS 清单有所帮助,尽管我不会全力以赴地尝试实施所有这些清单,而且一些最有价值的替代品不在这些清单上。例如,“JFK”应该匹配“JOHN F KENNEDY”,并且有许多常用的方法来缩短“MARTIN LUTHER KING JR”。

也许不言而喻,但为了完整起见,我还是会说:不要忘记在处理更复杂的事情之前对整个地址进行直接的字符串比较!这应该是一个非常便宜的测试,因此可能是不费吹灰之力的第一次通过。

显然,您愿意并且能够花费的时间越多(编程/测试和运行时间),您就能做得越好。模糊字符串匹配技术(比 Levenshtein 更快且更不通用的类型)可能很有用,作为与令牌方法的单独传递(我不会尝试将各个令牌相互模糊匹配)。我发现模糊字符串匹配并不能让我在地址上获得足够的收益(尽管我会在名称上使用它)。

于 2009-09-04T05:07:04.220 回答
1

为了做到这一点,您需要根据 USPS 标准标准化您的地址(您的地址示例似乎是基于美国的)。有许多直销服务提供商提供邮政地址的CASS(编码准确性支持系统)认证。CASS 流程将标准化您的所有地址并将 zip + 4 附加到它们。任何无法投递的地址都将被标记出来,如果这是您的意图,这将进一步降低您的邮寄成本。一旦您的所有地址都标准化,消除重复将是微不足道的。

于 2009-12-18T10:52:44.560 回答
0

我不得不这样做一次。我将所有内容都转换为小写字母,计算每个地址到每个其他地址的 Levenshtein 距离,并对结果进行排序。它工作得很好,但它非常耗时。

如果您有一个大型数据集,您将希望在 C 中而不是在 Python 中使用 Levenshtein 的实现。我想我的有几万,并且花了一天的大部分时间来运行,我想。

于 2009-09-03T11:18:35.820 回答