python - 带有拼写检查的查询分段
问题描述
假设我有一个固定的多词名称列表,例如:
Water
Tocopherol (Vitamin E)
Vitamin D
PEG-60 Hydrogenated Castor Oil
我想要以下输入/输出结果:
Water, PEG-60 Hydrogenated Castor Oil
->Water
,PEG-60 Hydrogenated Castor Oil
PEG-60 Hydrnated Castor Oil
->PEG-60 Hydrogenated Castor Oil
wter PEG-60 Hydrnated Castor Oil
->Water
,PEG-60 Hydrogenated Castor Oil
Vitamin E
->Tocopherol (Vitamin E)
我需要它是高性能的,并且能够识别出有太多接近的比赛而没有接近的比赛。使用 1 相对容易,因为我可以用逗号分隔。大多数情况下,输入列表用逗号分隔,所以这在 80% 的时间里都有效,但即使这样也有小问题。以 4 为例。一旦分离,大多数拼写检查库(我尝试过一个数字)不会返回 4 的理想匹配,因为编辑距离Vitamin D
要小得多。有一些网站做得很好,但我不知道该怎么做。
这个问题的第二部分是,我如何在上面进行分词。假设一个给定的列表没有逗号,我需要能够识别它。最简单的例子Water Vtamin D
应该是Water
, Vitamin D
。我可以举很多例子,但我认为这很好地说明了这个问题。
这是可以使用的名称列表。
解决方案
语境
这是一种近似字符串匹配或模糊匹配的情况。有很好的材料和图书馆。
有不同的库和方法来涵盖这一点。我将限制在相对简单的库中
一些很酷的库:
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 结合使用时。
参考
推荐阅读
- c# - 实体框架核心:未处理的异常
- python - Python Tornado - TCPServer 和应用程序
- amazon-web-services - 无法在 Web 浏览器上使用 AWS 公共 DNS 打开 cloudera manager 7180 端口
- linux - MT4/Wine/Ubuntu 将不允许 FileOpen
- apache-kafka - Kafka 1.1.0 中的分区重新分配失败
- typescript - TypeScript 无法返回与泛型参数具有相同基数的对象
- python - 允许 zip 函数将 1D 映射到 2D 数组
- c# - 如何在 Azure 存储帐户表中插入记录。当我运行我的代码 FIXED 时应用程序关闭
- jquery - 如何在没有 React 的情况下订阅多个组件到 Redux 中的操作?
- c# - 仅适用于属性的自定义 XML 序列化