首页 > 解决方案 > 带有拼写检查的查询分段

问题描述

假设我有一个固定的多词名称列表,例如: Water Tocopherol (Vitamin E) Vitamin D PEG-60 Hydrogenated Castor Oil

我想要以下输入/输出结果:

  1. Water, PEG-60 Hydrogenated Castor Oil-> Water,PEG-60 Hydrogenated Castor Oil
  2. PEG-60 Hydrnated Castor Oil->PEG-60 Hydrogenated Castor Oil
  3. wter PEG-60 Hydrnated Castor Oil-> Water,PEG-60 Hydrogenated Castor Oil
  4. Vitamin E->Tocopherol (Vitamin E)

我需要它是高性能的,并且能够识别出有太多接近的比赛而没有接近的比赛。使用 1 相对容易,因为我可以用逗号分隔。大多数情况下,输入列表用逗号分隔,所以这在 80% 的时间里都有效,但即使这样也有小问题。以 4 为例。一旦分离,大多数拼写检查库(我尝试过一个数字)不会返回 4 的理想匹配,因为编辑距离Vitamin D要小得多。有一些网站做得很好,但我不知道该怎么做。

这个问题的第二部分是,我如何在上面进行分词。假设一个给定的列表没有逗号,我需要能够识别它。最简单的例子Water Vtamin D应该是Water, Vitamin D。我可以举很多例子,但我认为这很好地说明了这个问题。

是可以使用的名称列表。

标签: pythonstringsearchspell-checking

解决方案


语境

这是一种近似字符串匹配模糊匹配的情况。有很好的材料和图书馆。

有不同的库和方法来涵盖这一点。我将限制在相对简单的库中

一些很酷的库:

from fuzzywuzzy import process
import pandas as pd
import string

第一部分

让我们放置数据来玩。我尝试重现上面的示例,希望它很好。

# Set up dataframe
d = {'originals': [["Water","PEG-60 Hydrogenated Castor Oil"],
                   ["PEG-60 Hydrnated Castor Oil"],
                   ["wter"," PEG-60 Hydrnated Castor Oil"],
                   ['Vitamin E']],
     'correct': [["Water","PEG-60 Hydrogenated Castor Oil"],
                 ["PEG-60 Hydrogenated Castor Oil"],
                 ['Water', 'PEG-60 Hydrogenated Castor Oil'],
                 ['Tocopherol (Vitamin E)']]}
df = pd.DataFrame(data=d)
print(df)
                                 originals                                  correct
0  [Water, PEG-60 Hydrogenated Castor Oil]  [Water, PEG-60 Hydrogenated Castor Oil]
1            [PEG-60 Hydrnated Castor Oil]         [PEG-60 Hydrogenated Castor Oil]
2     [wter,  PEG-60 Hydrnated Castor Oil]  [Water, PEG-60 Hydrogenated Castor Oil]
3                              [Vitamin E]                 [Tocopherol (Vitamin E)]

从上面我们得到了问题的陈述:我们有一些原始的措辞并且想要改变它。

哪些是我们的正确选择:

strOptions = ['Water', "Tocopherol (Vitamin E)",
             "Vitamin D", "PEG-60 Hydrogenated Castor Oil"]

这些功能将对我们有所帮助。我试着把它们记录下来。

def function_proximity(str2Match,strOptions):
    """
    This function help to get the first guess by similiarity.

    paramters
    ---------
    str2Match: string. The string to match.
    strOptions: list of strings. Those are the possibilities to match.
    """
    highest = process.extractOne(str2Match,strOptions)
    return highest[0]
def check_strings(x, strOptions):
    """
    Takes a list of string and give you a list of string best matched.
    :param x: list of string to link / matched
    :param strOptions:
    :return: list of string matched
    """
    list_results = []
    for i in x:
        i=str(i)
        list_results.append(function_proximity(i,strOptions))
    return list_results

让我们应用于数据框:

df['solutions_1'] = df['originals'].apply(lambda x: check_strings(x, strOptions))

让我们通过比较列来检查结果。

print(df['solutions_1'] == df['correct'])
0    True
1    True
2    True
3    True
dtype: bool

如您所见,解决方案在四种情况下都有效。

第二部分

问题示例解决方案:您Water Vtamin D应该成为Water, Vitamin D.

让我们创建一个有效单词列表。

list_words = []
for i in strOptions:
    print(i.split(' '))
    list_words = list_words + i.split(' ')
# Lower case and remove punctionation
list_valid_words = []
for i in list_words:
    i = i.lower()
    list_valid_words.append(i.translate(str.maketrans('', '', string.punctuation)))
print(list_valid_words)
['water', 'tocopherol', 'vitamin', 'e', 'vitamin', 'd', 'peg60', 'hydrogenated', 'castor', 'oil']

如果列表中的单词是有效的。

def remove_puntuation_split(x):
    """
    This function remove puntuation and split the string into tokens.
    :param x: string
    :return: list of proper tokens
    """
    x = x.lower()
    # Remove all puntuation
    x = x.translate(str.maketrans('', '', string.punctuation))
    return x.split(' ')

tokens = remove_puntuation_split(x)
# Clean tokens
clean_tokens = [function_proximity(x,list_valid_words) for x in tokens]
# Matched tokens with proper selection
tokens_clasified = [function_proximity(x,strOptions) for x in tokens]
# Removed repeated
tokens_clasified =  list(set(tokens_clasified))
print(tokens_clasified)
['Vitamin D', 'Water']

这是最初的要求。然而,这些可能会失败一点,尤其是当维生素 E 和 D 结合使用时。

参考


推荐阅读