【问题标题】:How can I calculate the Jaccard Similarity of two lists containing strings in Python?如何在 Python 中计算两个包含字符串的列表的 Jaccard 相似度?
【发布时间】:2017-10-27 13:14:02
【问题描述】:

我有两个用户名列表,我想计算 Jaccard 相似度。是否可以?

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

【问题讨论】:

    标签: python python-3.x similarity


    【解决方案1】:

    毕竟我最终编写了自己的解决方案:

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

    【讨论】:

    • 函数总是返回0.0
    • @xyd 非常适合我。你能解释一下吗?
    • 值得注意的是,此计算与@w2bo 的答案不同,因为此计算不除以设置长度联合。
    • 这个答案是错误的。例如,jaccard_similarity([1], [0, 1]) -> 0.5jaccard_similarity([1, 1], [0, 1, 1]) -> 0.25 但是根据您定义 jaccard 的方式,第二个应该与第一个相似或更相似。
    • 解决方案简单优雅,但并非 100% 正确。您应该将相应的行更改为:union = (len(set(list1)) + len(set(list2))) - intersection
    【解决方案2】:

    对于 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
    

    对于 Python2 使用 return len(s1.intersection(s2)) / float(len(s1.union(s2)))

    【讨论】:

    • 这也会给出 0.0 作为结果。修改返回语句:return float(len(s1.intersection(s2))) / float(len(s1.union(s2)))
    • 对于 Python2 使用:return float(len(s1.intersection(s2))) / len(s1.union(s2))
    【解决方案3】:

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

    【讨论】:

    • 感谢您的提示!我不知道。我相应地编辑了答案。
    【解决方案4】:

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

    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
    

    【讨论】:

      【解决方案5】:

      您可以使用Distance

      #pip install Distance
      
      import distance
      
      distance.jaccard("decide", "resize")
      
      # Returns
      0.7142857142857143
      

      【讨论】:

        【解决方案6】:

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

        【讨论】:

        • 我认为这个解决方案对于重复项是不正确的。但是,它适用于包含非重复项的列表。
        • 我认为这是距离,所以如果想要相似,'1 - '应该从返回行中删除。
        【解决方案7】:

        @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
        

        请注意,在交集处,无需先转换为列表。此外,在 Python 3 中不需要强制转换为浮点数。

        【讨论】:

          【解决方案8】:

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

          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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-03-27
            • 1970-01-01
            • 1970-01-01
            • 2021-10-25
            • 2011-07-16
            • 2022-01-04
            • 2012-03-28
            • 2011-10-06
            相关资源
            最近更新 更多