J'ai deux listes avec les noms d'utilisateur et je veux calculer la similarité de Jaccard. C'est possible?
This thread montre comment calculer la similarité Jaccard entre deux chaînes, mais je souhaite l’appliquer à deux listes, où chaque élément est un mot (par exemple, un nom d’utilisateur).
J'ai fini par écrire ma propre solution après tout:
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 Je n'ai pas assez de réputation pour ajouter un commentaire à votre réponse, mais pour clarifier les choses, votre solution mesure le jaccard_similarity
mais la fonction porte à tort le nom jaccard_distance
, qui est en fait 1 - jaccard_similarity
.
En supposant que vos noms d'utilisateur ne se répètent pas, vous pouvez utiliser la même idée:
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
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
Si vous souhaitez inclure des éléments répétés, vous pouvez utiliser Counter
, ce qui, je suppose, est relativement rapide puisqu'il ne s'agit que d'une dict
étendue:
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 1 - n/(len(a) + len(b) - n)
list1 = ['dog', 'cat', 'rat', 'cat']
list2 = ['dog', 'cat', 'rat']
list3 = ['dog', 'cat', 'mouse']
jaccard_repeats(list1, list3)
>>> 0.25
jaccard_repeats(list1, list2)
>>> 0.8333333333333334
jaccard_repeats(list2, list3)
>>> 0.5
Vous pouvez utiliser le Distance library
#pip install Distance
import distance
distance.jaccard("decide", "resize")
# Returns
0.7142857142857143