在 FuzzyWuzzy 中传递多个参数

Fat*_*ima 2 python

我已在包含超过 9000 条记录的数据集上应用了 fuzzy-wuzzy 函数,如下所示:

def fuzzy(name, column):
    all = []     
    #fuzzy set 
    set = process.extract(name, column, scorer=fuzz.token_set_ratio)
    for set_result in set:
        set_data = {}
        set_data['name'] = set_result[0] 
        set_data['Matching Score'] = set_result[1]
        set_data['Function'] = "set" 
        all.append(set_data)
    return all  

     
#apply similrty  
def Get_all(name): 
    fuzzy_all= []
    fuzzy= fuzzy(name,table.Name)
    fuzzy2= fuzzy(soundex.encode_word(name),table["name_encoded"])
    fuzzy_all=fuzzy+fuzzy2
    return fuzzy_all
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以改进函数并同时传递多个参数(columnname),通过仅调用 fuzzy 一次,以便 fuzzy 不必多次访问整个数据集?

max*_*ann 6

过程.提取物

我将首先解释它的用途process.extract以及可以传递给它的所有参数的含义,因为它经常被滥用,这会对性能产生很大影响。在解释中我将始终引用库rapidfuzz(我是作者)。Rapidfuzz 实现了相同的字符串匹配算法,并且具有非常相似的界面(当它们有助于提高性能时存在一些差异)。

process.extract在rapidfuzz中有以下接口:

extract(
  query,
  choices,
  scorer=<built-in function WRatio>,
  processor=<built-in function default_process>,
  limit=5,
  score_cutoff=0)
Run Code Online (Sandbox Code Playgroud)

该函数用于在选项列表中查找查询的最佳匹配项

询问

query 是你要查找的字符串

选择

choice 支持两种影响函数返回内容的输入

  1. 具有 method 的类型items。示例是dictsorpandas.Series 在这种情况下,函数将比较映射到查询的所有值,并以 [(<value>, <score>, <key>),...] 的形式返回结果的排序列表。 。因此,例如使用 apandas.Series您将收到 [(<value>, <score>, <index>),...]。

  2. 任何可迭代的类型,例如列表或生成器在这种情况下,函数会将 Iterable 的所有值与查询进行比较,并以 [(<value>, <score>),... 的形式返回结果的排序列表。 ]。

处理器

处理器是一个函数,用于在比较查询和每个选择之前对其进行预处理。这可以是任何接受字符串作为参数并返回字符串的函数。默认情况下rapidfuzz.utils.default_process,它会小写字符串,删除非字母数字字符并删除字符串开头/结尾的空格。

得分手

Scorer 是用于将查询与每个选择进行比较的函数,需要以下接口:

def scorer(s1, s2, processor, score_cutoff)
Run Code Online (Sandbox Code Playgroud)

s1 和 s2 是两个字符串。Processor 通常作为 None 传递以process.extract停用预处理,因为这已经在process.extract. Score_cutoff 是两个字符串之间所需的最小相似度。如果未达到此相似度,则应返回 0。

默认情况下,该评分器fuzz.WRatio结合多个不同的比率并对它们进行加权。其他可用的记分器可以在这里找到:记分器文档 或者您可以使用类似的界面创建自己的函数来执行比较。

分数截止

如上所述,score_cutoff 用于设置字符串匹配的最小相似度。低于此相似度的元素不会添加到结果中。提供此参数有助于提高性能,因为它允许rapidfuzz使用更快的算法来比较字符串:当没有提供score_cutoff时,rapidfuzz将始终使用具有O(N*M)运行时间的levenshtein距离。然而,当它通过时,它将:

  1. 比较两个字符串的长度,看看是否可以在常数时间内达到score_cutoff,如果不能达到则返回0(分数至少与levenshtein距离一样高)
  2. 它将在 O(N+M) 时间内计算一个字符串中出现了多少个字符,但另一个字符串中没有出现,以找出是否可以达到 Score_cutoff,如果不能达到则提前退出(得分至少与 Levenshtein 距离一样高) )
  3. 仅当无法提前退出时,才会计算编辑距离

限制

使用此参数,您可以将结果数量限制为limit中的最佳匹配项choices。默认情况下,该值为 5,因此您只能获得 5 个最佳结果。通过设置,limit=None您将获得所有结果,只要它们没有被过滤掉score_cutoff

函数中最耗时的部分是对 的调用process.extract

def scorer(s1, s2, processor, score_cutoff)
Run Code Online (Sandbox Code Playgroud)

提高性能的可能性

有几件事可能会帮助您获得更好的性能:

  1. 您可能应该使用rapidfuzz,因为它要快得多。这是因为我确实用 C++ 实现了所有内容,并且 Fuzzywuzzy 的很多算法都可以改进很多。

  2. processor=None您可以通过传递给 来停用字符串预处理process.extract。当您需要对数据进行预处理时,您可以提前执行一次,这样您就不必每次调用时都执行它Get_all

  3. 如上所述提供一个score_cutoff可以帮助提高性能

  4. 最后一个选择是编写process.extract. 现在它会计算所有通过的选择的分数。然而,在找到limit分数以上的选项后score_cutoff,有可能增加到score_cutoff结果中的最小分数。然而,这需要维护当前最佳结果的排序列表,因此可能值得也可能不值得。当您只对最佳结果感兴趣时,process.extractOne已经使用此技术来改进运行时间。