Python中的字符串相似性度量

时间:2009-09-24 11:43:00

标签: python algorithm string levenshtein-distance

我想找到两个字符串之间的字符串相似性。 This页面包含其中一些示例。 Python的实现是Levenshtein algorithm。在这些约束条件下是否有更好的算法(并且希望是一个python库)。

  1. 我想在字符串之间进行模糊匹配。例如匹配('Hello,All you people','hello,all you peopl')应返回True
  2. 可以接受假阴性,误报,除极少数情况外不是。
  3. 这是在非实时设置中完成的,因此速度不是(非常)关注的。
  4. [编辑]我正在比较多字符串。
  5. Levenshtein距离(或Levenshtein比率)以外的其他东西是否能成为我案例的更好算法?

6 个答案:

答案 0 :(得分:81)

我意识到这不是一回事,但这已足够接近了:

>>> import difflib
>>> a = 'Hello, All you people'
>>> b = 'hello, all You peopl'
>>> seq=difflib.SequenceMatcher(a=a.lower(), b=b.lower())
>>> seq.ratio()
0.97560975609756095

您可以将其设为功能

def similar(seq1, seq2):
    return difflib.SequenceMatcher(a=seq1.lower(), b=seq2.lower()).ratio() > 0.9

>>> similar(a, b)
True
>>> similar('Hello, world', 'Hi, world')
False

答案 1 :(得分:20)

谢菲尔德大学有很好的字符串相似性指标资源。它有各种指标列表(不仅仅是Levenshtein),并且有开源实现。看起来很多应该很容易适应Python。

http://web.archive.org/web/20081224234350/http://www.dcs.shef.ac.uk/~sam/stringmetrics.html

以下是一些清单:

  • 汉明距离
  • Levenshtein距离
  • Needleman-Wunch距离或卖家算法
  • 以及更多...

答案 2 :(得分:13)

此片段将计算两个字符串的difflib,Levenshtein,Sørensen和Jaccard相似度值。在下面的代码片段中,我正在迭代一个tsv,其中感兴趣的字符串占据了tsv的[3][4]列。 (pip install python-Levenshteinpip install distance):

import codecs, difflib, Levenshtein, distance

with codecs.open("titles.tsv","r","utf-8") as f:
    title_list = f.read().split("\n")[:-1]

    for row in title_list:

        sr      = row.lower().split("\t")

        diffl   = difflib.SequenceMatcher(None, sr[3], sr[4]).ratio()
        lev     = Levenshtein.ratio(sr[3], sr[4]) 
        sor     = 1 - distance.sorensen(sr[3], sr[4])
        jac     = 1 - distance.jaccard(sr[3], sr[4])

        print diffl, lev, sor, jac

答案 3 :(得分:7)

我会使用Levenshtein距离,或所谓的Damerau距离(考虑转换)而不是difflib的东西有两个原因(1)“足够快”(动态编程算法)和“whoooosh”(bit-抨击)C代码可用,(2)易于理解的行为,例如Levenshtein满足三角不等式,因此可用于例如三角形不等式。 Burkhard-Keller树。

阈值:你应该只将距离<1的情况视为“积极的”。 (1 - X)* max(len(string1),len(string2))并调整X(相似因子)以适合自己。选择X的一种方法是获得匹配样本,为每个匹配计算X,忽略X <1的情况。比如说0.8或0.9,然后按照X的降序对剩余部分进行排序并对它们进行眼球并插入正确的结果并计算出不同级别的X的一些成本错误度量。

N.B。您的猿/苹果示例距离为2,因此X为0.6 ......如果我拼命寻找某些东西且假阴性惩罚很高,我只会使用低至0.75的阈值

答案 4 :(得分:5)

这是你的意思吗?

>>> get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'])
['apple', 'ape']
>>> import keyword
>>> get_close_matches('wheel', keyword.kwlist)
['while']
>>> get_close_matches('apple', keyword.kwlist)
[]
>>> get_close_matches('accept', keyword.kwlist)
['except']

查看http://docs.python.org/library/difflib.html#difflib.get_close_matches

答案 5 :(得分:2)

我知道这不是一样的但你可以调整比例来过滤掉那些不够相似的字符串,并将最接近的匹配返回给你正在寻找的字符串。

也许您会对语义相似度指标更感兴趣。

https://www.google.com/search?client=ubuntu&channel=fs&q=semantic+similarity+string+match&ie=utf-8&oe=utf-8

我意识到你说速度不是问题但是如果你正在为你的算法处理很多字符串,下面的内容非常有帮助。

def spellcheck(self, sentence):
    #return ' '.join([difflib.get_close_matches(word, wordlist,1 , 0)[0] for word in sentence.split()])
    return ' '.join( [ sorted( { Levenshtein.ratio(x, word):x for x in wordlist }.items(), reverse=True)[0][1] for word in sentence.split() ] )

它比difflib快20倍。

https://pypi.python.org/pypi/python-Levenshtein/

导入Levenshtein