我正在处理来自多个来源的一些汇总会员数据。我在一列中有名字,在另一列中有一个长成员备忘录字符串。我希望有最好的方法将名称与会员单备忘录相匹配。
例如,
我想找到最好的方法:
'Barack Obama'
在以下字符串中,因为此数据已聚合且格式可能不同。这里有几个例子:
"Member Data REWNEW:EX PAID ID:234242 Barack Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
"Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
"Member Data REWNEW:EX PAID ID:234242 Obama Barack WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
"Member Data REWNEW:EX PAID ID:234242 Barack H Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
过去,我使用fuzzywuzzy进行模糊逻辑匹配。如果我比较两个字符串,但是不想在另一个更长的字符串中找到一个字符串,这往往会很好。例如:
from fuzzywuzzy import fuzz
from fuzzywuzzy import fuzz
print(fuzz.ratio("Barack Obama", "Barack Obama"))
print(fuzz.ratio("Michelle Obama", "Barack Obama"))
print(fuzz.ratio("Barack Obama", "Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"))
print(fuzz.ratio("Michelle Obama", "Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"))
100
54
22
16
很明显前两个是非常不同的(100对54)但是后两个看起来并没有那么不同,因此这不是最好的方法。
有没有人对如何最好地实现这种类型的字符串搜索有任何想法?
非常感谢你!
UPDATE1:
我试过了:
memo_string="Member Data REWNEW:EX PAID ID:234242 Barack Hussein Obama WASHINGTON DC LAST CO 2834298:EEXE:00WIE"
search_terms = "Barack Obama"
memo_words = memo_string.split(" ")
search_term_count = len(search_terms.split(" "))
memo_slices = []
for i in range(len(memo_words) - search_term_count):
memo_slices.append(" ".join(memo_words[i:i+search_term_count]))
max_for_memo = 0
best_match_in_memo = None
for memo_slice in memo_slices:
fuzz_score = fuzz.ratio(search_terms, memo_slice)
if fuzz_score > max_for_memo:
max_for_memo = fuzz_score
best_match_in_memo = memo_slice
print(max_for_memo)
I also tried with search_terms = 'Michelle Obama'
这两个分数分别为52和50,这仍然是我在开始时提出的挑战,也就是说我想要某种逻辑将两者更明确地分开。
思考?
非常感谢你!
答案 0 :(得分:2)
最简单的方法就是检查姓名和姓氏。在您的示例中,您可以执行以下操作:
search_terms = "Barack Obama"
matches = []
for memo_string in memos_list:
for word in search_terms.split(" "):
if word not in memo_string:
break
else:
matches.append(memo_string) # triggers when the for loop doesn't break
这将匹配包含您的确切搜索字词的所有备忘录。但这并不会检查这些术语是否彼此相邻,并且要求它们完全匹配。
对于模糊匹配,您可以将搜索条件与备注字符串的片段进行比较(为简洁起见,省略了一些序言)。
memo_words = memo_string.split(" ")
search_term_count = len(search_terms.split(" "))
memo_slices = []
for i in range(memo_words - search_term_count):
memo_slices.append(" ".join(memo_words[i:i+search_term_count]))
max_for_memo = 0
best_match_in_memo = None
for memo_slice in memo_slices:
fuzz_score = fuzz.ratio(search_terms, memo_slice)
if fuzz_score > max_for_memo:
max_for_memo = fuzz_score
best_match_in_memo = memo_slice
这应该允许您将较长文本中匹配的模糊分数与较短文本进行比较。一旦你想开始将搜索项与目标字符串中不同大小的切片进行匹配,它会变得有点复杂,但你应该在那时查看正则表达式(我只是想提供一些更可能的解决方案)。
答案 1 :(得分:0)
使用findall或从re模块中搜索。 Findall返回匹配字符串列表。如果找到匹配,则搜索返回true。 例如: 进口重新 pattern ='Barack Obama' matches = re.findall(pattern,string)