如何在Python中计算两个包含字符串的列表的Jaccard相似度?

1tu0hz3e  于 2023-11-20  发布在  Python
关注(0)|答案(9)|浏览(122)

我有两个用户名列表,我想计算Jaccard相似度。可以吗?
This线程显示了如何计算两个字符串之间的Jaccard相似度,但是我想将其应用于两个列表,其中每个元素都是一个单词(例如,用户名)。

cwtwac6a

cwtwac6a1#

最后,我还是写了自己的解决方案:

def jaccard_similarity(list1, list2):
    intersection = len(list(set(list1).intersection(list2)))
    union = (len(set(list1)) + len(set(list2))) - intersection
    return float(intersection) / union

字符串

t5fffqht

t5fffqht2#

对于Python 3:

def jaccard_similarity(list1, list2):
    s1 = set(list1)
    s2 = set(list2)
    return float(len(s1.intersection(s2)) / len(s1.union(s2)))
list1 = ['dog', 'cat', 'cat', 'rat']
list2 = ['dog', 'cat', 'mouse']
jaccard_similarity(list1, list2)
>>> 0.5

字符串
对于Python 2,使用return len(s1.intersection(s2)) / float(len(s1.union(s2)))

kg7wmglp

kg7wmglp3#

@aventinus我没有足够的声誉对你的答案添加评论,但为了让事情更清楚,你的解决方案测量了jaccard_similarity,但函数被错误地命名为jaccard_distance,实际上是1 - jaccard_similarity

axr492tv

axr492tv4#

假设你的用户名不重复,你可以使用同样的想法:

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

字符串

sf6xfgos

sf6xfgos5#

您可以使用Distance

#pip install Distance

import distance

distance.jaccard("decide", "resize")

# Returns
0.7142857142857143

字符串

huus2vyu

huus2vyu6#

@Aventinus(我也不能评论):注意Jaccard similarity 是对集合的操作,所以在分母部分也应该使用集合(而不是列表)。所以例如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

字符串
注意,在交集中,不需要先转换为list。同样,在Python 3中也不需要转换为float。

yzuktlbb

yzuktlbb7#

Simphile包含几种文本相似性方法,Jaccard是其中之一。
在终端安装软件包:

pip install simphile

字符串
那么你的代码可能是这样的:

from simphile import jaccard_list_similarity

list_a = ['cat', 'cat', 'dog']
list_b = ['dog', 'dog', 'cat']

print(f"Jaccard Similarity: {jaccard_list_similarity(list_a, list_b)}")


输出为:

Jaccard Similarity: 0.5


请注意,此解决方案考虑了重复的元素--这对文本相似性至关重要;如果没有它,上面的示例将显示100%的相似性,因为两个列表作为集合将减少为“dog”,“cat”}。

gjmwrych

gjmwrych8#

如果你想包含重复的元素,你可以使用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

字符串

vjrehmav

vjrehmav9#

为了避免联合(分母)中的元素重复,我建议更快一点:

def Jaccar_score(lista1, lista2):    
    inter = len(list(set(lista_1) & set(lista_2)))
    union = len(list(set(lista_1) | set(lista_2)))
    return inter/union

字符串

相关问题