我有两个用户名列表,我想计算Jaccard相似度。可能吗?
This线程显示了如何计算两个字符串之间的Jaccard相似性,但是我想将它应用于两个列表,其中每个元素是一个单词(例如,用户名)。
毕竟我最终写了自己的解决方案:
def jaccard_similarity(list1, list2):
intersection = len(list(set(list1).intersection(list2)))
print(list(set(list1).intersection(list2)))
union = (len(list1) + len(list2)) - intersection
return float(intersection / union)
@aventinus我没有足够的声誉为你的答案添加评论,但只是为了让事情更清楚,你的解决方案测量jaccard_similarity
但功能被误称为jaccard_distance
,实际上是1 - jaccard_similarity
def jaccard_similarity(list1, list2):
s1 = set(list1)
s2 = set(list2)
return len(s1.intersection(s2)) / len(s1.union(s2))
list1 = ['dog', 'cat', 'cat', 'rat']
list2 = ['dog', 'cat', 'mouse']
jaccard(list1, list2)
>>> 0.5
假设您的用户名不重复,您可以使用相同的想法:
def jaccard(a, b):
c = a.intersection(b)
return float(len(c)) / (len(a) + len(b) - len(c))
list1 = ['dog', 'cat', 'rat']
list2 = ['dog', 'cat', 'mouse']
# The intersection is ['dog', 'cat']
# union is ['dog', 'cat', 'rat', 'mouse]
words1 = set(list1)
words2 = set(list2)
jaccard(words1, words2)
>>> 0.5
您可以使用Distance库
#pip install Distance
import distance
distance.jaccard("decide", "resize")
# Returns
0.7142857142857143
如果你想包含重复的元素,你可以使用Counter
,我认为它相对较快,因为它只是一个扩展的dict
引擎盖:
from collections import Counter
def jaccard_repeats(a, b):
"""Jaccard similarity measure between input iterables,
allowing repeated elements"""
_a = Counter(a)
_b = Counter(b)
c = (_a - _b) + (_b - _a)
n = sum(c.values())
return n/(len(a) + len(b) - n)
list1 = ['dog', 'cat', 'rat', 'cat']
list2 = ['dog', 'cat', 'rat']
list3 = ['dog', 'cat', 'mouse']
jaccard_repeats(list1, list3)
>>> 0.75
jaccard_repeats(list1, list2)
>>> 0.16666666666666666
jaccard_repeats(list2, list3)
>>> 0.5
@Aventinus(我也无法评论):注意Jaccard相似性是对集合的操作,所以在分母部分它也应该使用集合(而不是列表)。所以例如jaccard_similarity('aa', 'ab')
应该导致0.5
。
def jaccard_similarity(list1, list2):
intersection = len(set(list1).intersection(list2))
union = len(set(list1)) + len(set(list2)) - intersection
return intersection / union
请注意,在交集中,不需要先转换为列表。此外,Python 3中不需要强制转换为float。