我已经完成了模糊匹配20,000多个电影标题列表中的每个元素与每个其他元素,每个元素返回一个值:
from fuzzywuzzy import fuzz
titles = ['Scary Movie', 'Happy Movie', 'Sappy Movie', 'Crappy Movie']
print fuzz.ratio(titles[2],titles[3])
>>> 91 #/100 higher value denotes closer match
for x in titles:
for y in titles:
fuzzed = fuzz.ratio(x,y)
print "value for %r and %r is %r" % (x, y, fuzzed)
如何有效地整理这些数据?更具体地说 - 如何根据匹配值将匹配组合在一起?
从嵌套循环中捕获返回值,然后用x和y将它们打包到元组或列表中显然是多余和杂乱的。我尝试使用类实现,但我遗漏了一些东西。
答案 0 :(得分:1)
使用列表推导和itertools.product
:
from itertools import product
[(x, y, fuzz.ratio(x, y)) for (x, y) in product(titles, repeat=2)]
使用toolz
from toolz.curried import pipe, filter, map
pipe(
product(titles, repeat=2),
# No reason to check duplicates
filter(lambda (x, y): x > y),
map(lambda (x, y): (x, y, fuzz.ratio(x, y))))
答案 1 :(得分:1)
您只需要迭代combinations
个标题,因为该比率并不取决于订单。这比迭代product
快得多。
对于20,000个标题的列表,如果您使用product
,则会迭代 400,000 000 对。使用combinations
,您只会迭代 199 990 000 。
from fuzzywuzzy import fuzz
import collections
import itertools
titles = ['Scary Movie', 'Happy Movie', 'Sappy Movie', 'Crappy Movie']
然后,您可以将比率存储在字典中,您可以在字典中查找比率,以获得具有该比率的set
对。
fuzzes_by_ratio = collections.defaultdict(set)
或者在字典中,您可以查找frozenset
个对并获得它们的比率。
fuzzes_per_pair = {}
-
for m1, m2 in itertools.combinations(titles, 2):
pair = frozenset({m1, m2})
ratio = fuzz.ratio(m1, m2)
fuzzes_by_ratio[ratio].add(pair)
fuzzes_per_pair[pair] = ratio
然后您可以稍后检索数据:
# I don't have fuzzywuzzy installed so this is just made up:
>>> fuzzes_by_ratio[91]
{frozenset({"Scary Movie", "Happy Movie"}), frozenset({"Sappy Movie", "Happy Movie"})}
>>> fuzz_per_pair[frozenset({"Scary Movie", "Sappy Movie"})]
82
请记住,此存储需要大量内存。根据您的需要/方便,您可以仅使用上述两种方法中的一种来将其减半。
答案 2 :(得分:0)
也许您可以将fuzzed
比例存储在以(x,y)
元组为关键字的字典中,以便以后更轻松地搜索ratio
每对。为此,您可以在for循环外创建一个空字典,然后在for循环中将fuzz.ratio(x , y)
分配给该字典的密钥(x, y)
。
示例代码 -
fuzzDict = {}
for x in titles:
for y in titles:
fuzzDict[(x,y)] = fuzz.ratio(x,y)
稍后,当您想要检索比率时,您可以简单地调用fuzzDict[(x , y)]
来获取它。
您还可以在Python 2.7+中使用字典理解 -
{(x, y) : fuzz.ratio(x,y) for x in titles for y in titles}