Python中的高性能模糊字符串比较,使用Levenshtein或difflib


127

我正在进行临床消息标准化(拼写检查),其中我对照900,000个单词的医学词典检查每个给定的单词。我更关心时间的复杂性/性能。

我想进行模糊字符串比较,但是不确定使用哪个库。

选项1:

import Levenshtein
Levenshtein.ratio('hello world', 'hello')

Result: 0.625

选项2:

import difflib
difflib.SequenceMatcher(None, 'hello world', 'hello').ratio()

Result: 0.625

在此示例中,两者给出相同的答案。您是否认为在这种情况下两者表现都一样?

Answers:


152

如果您想对Levenshtein和Difflib的相似性进行快速的视觉比较,我计算了约230万本书的书名:

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

然后,我用R绘制结果:

在此处输入图片说明

出于好奇,我还比较了Difflib,Levenshtein,Sørensen和Jaccard相似度值:

library(ggplot2)
require(GGally)

difflib <- read.table("similarity_measures.txt", sep = " ")
colnames(difflib) <- c("difflib", "levenshtein", "sorensen", "jaccard")

ggpairs(difflib)

结果: 在此处输入图片说明

Difflib / Levenshtein的相似性确实很有趣。

2018编辑:如果您要识别相似的字符串,还可以查看minhashing-这里有一个很棒的概述。Minhashing在线性时间内在大型文本集合中发现相似之处非常了不起。我的实验室在这里组装了一个应用程序,该应用程序使用minhashing检测和可视化文本重用:https//github.com/YaleDHLab/intertext


2
这太酷了!那你对此怎么看?Levenshtein是否适合标题长度的字符串?
Ulf Aslak,2015年

3
这确实取决于您要在相似性指标中捕获什么...
duhaime 2015年

2
我认为difflib和levenshtein之间的某些分歧可以得到解释,因为difflib使用了自动垃圾启发法。如果禁用它会怎样?
迈克尔·迈克尔(Michael

2
这是个好问题。自动垃圾邮件过滤器仅在观察次数> 200时才生效,因此我不确定这个特定的数据集(书名)是否会受到很大影响,但是值得研究……
duhaime 2016年

2
@duhaime,谢谢您的详细分析。我是这类情节的新手,也不知道如何解释它们。这些图被称为什么,以便我可以查找它们并了解它们?
Zach Young

104
  • difflib.SequenceMatcher使用Ratcliff / Obershelp算法,计算匹配字符的加倍数除以两个字符串中的字符总数。

  • Levenshtein使用Levenshtein算法,它计算将一个字符串转换为另一个字符串所需的最少编辑次数

复杂

SequenceMatcher是最坏情况下的二次时间,其预期情况下的行为以复杂的方式取决于序列共有多少个元素。(从这里

Levenshtein为O(m * n),其中n和m是两个输入字符串的长度。

性能

根据Levenshtein模块的源代码:Levenshtein与difflib(SequenceMatcher)有一些重叠。它仅支持字符串,不支持任意序列类型,但另一方面,它要快得多。


非常感谢您提供的信息。我添加了更多详细信息。这就是:I am doing clinical message normalization (spell check) in which I check each given word against 900,000 word medical dictionary. I am more concern about the time complexity/performance.在这种情况下,您认为两者的表现是否相同。
Maggie
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.