我有以下代码检查数据框中的句子是否在列表中。如果是这种情况,则应将部件替换为''。
import pandas as pd
input_set = pd.DataFrame([['Thanks for the mail Harry', 1], ['Thanks for mailing Harry', 1]], columns=('Sentence', 'ticketID'))
def reduceString(string, listSentences):
for i in listSentences:
new_string = string.replace(i, '')
return(new_string)
listSentences = ['Thanks for the ']
for index, sentence in input_set.iterrows():
string = reduceString(sentence['Sentence'], listSentences)
print(string)
一切正常。
但是,我想通过包含diff模块使其更加强大。目标是不仅删除了确切的句子,而且删除了与x%相似的句子。
因此我尝试用这个来调整代码:
import difflib
def reduceString2(string, listSentences):
for i in listSentences:
ratio = difflib.SequenceMatcher(None, i, string).ratio()
print(ratio)
if(ratio > 0.6):
new_string = string.replace(i, '')
return(new_string)
但是,如果我现在尝试运行:
for index, sentence in input_set.iterrows():
string = reduceString2(df['Sentence'], listSentences)
它确实没有改变第二句,而确实触及了if语句的障碍。有人可以说明为什么没有替换相关文本吗?
答案 0 :(得分:1)
首先,第一和第二算法完全不同;第一个将替换字符串中的任何位置的句子,而第二个将比较两个字符串总数是否相似(不是有相似的子序列)。
其次,即使string
和i
相似,您也试图替换string
中不一定存在的子字符串。您可以使用SequenceMatcher
中的某些方法找到要删除的正确位置:
import difflib
def reduceString2(string, listSentences):
for i in listSentences:
matcher = difflib.SequenceMatcher(None, i, string)
ratio = matcher.ratio()
print(ratio)
if(ratio > 0.6):
blocks = matcher.get_matching_blocks()
b_first, b_last = blocks[0], blocks[-2]
new_string = string[:b_first[1]] + string[b_last[1] + b_last[2]:]
return(new_string)
然而,这种方法特别会给你:
mail Harry
Harry
因为'Thanks for the '
中的最后一个空格与第二个句子中Harry
之前的空格匹配。另一个选择是只删除被替换的块,但这会给你:
mail Harry
mailingHarry
这可能不是你所期望的。所以你必须决定如何处理这些匹配的块。
此外,您可以考虑使用quick_ratio()
或real_quick_ratio()
作为更快的过滤器(请参阅SequenceMatcher
documentation),以及其他一些小问题,例如剥离和小写字符串。