【问题标题】:Percentage Overlap of Two Lists两个列表的百分比重叠
【发布时间】:2015-04-28 20:15:47
【问题描述】:

这更像是一道数学题。假设我在 Python 中有两个不同大小的列表

listA = ["Alice", "Bob", "Joe"]
listB = ["Joe", "Bob", "Alice", "Ken"]

我想知道这两个列表的重叠百分比。顺序在列表中并不重要。找到重叠很容易,我已经看过其他关于如何做到这一点的帖子,但我无法在脑海中完全扩展它以找出它们重叠的百分比。如果我以不同的顺序比较列表,结果会有所不同吗?这样做的最佳方法是什么?

【问题讨论】:

  • 顺序在这里并不重要,但是,您首先需要定义百分比的公式,它可以是:2*number of matches/(len(lista)+len(listb)) 或其他东西
  • 如果列表是 [1,1,1][1]。重叠是 100% 还是 33%?
  • 这两个列表的预期输出是什么?
  • 您是否关心两个列表共有的不同元素的百分比(在这种情况下set() 将非常有帮助),或者关心所有元素(包括重复)的百分比,即两个列表共享?

标签: python list overlap similarity


【解决方案1】:

从主要的角度来看,我想说您可能会问两个明智的问题:

  1. 如果与第一个列表相比,重叠的百分比是多少? IE。与第一个列表相比,共同部分有多大?
  2. 第二个列表也是如此。
  3. 如果与“宇宙”(即两个列表的并集)相比,重叠的百分比是多少?

当然也可以找到其他含义,而且会有很多。总而言之,您可能应该知道您要解决什么问题。

从编程的角度来看,解决方案很简单:

listA = ["Alice", "Bob", "Joe"]
listB = ["Joe", "Bob", "Alice", "Ken"]

setA = set(listA)
setB = set(listB)

overlap = setA & setB
universe = setA | setB

result1 = float(len(overlap)) / len(setA) * 100
result2 = float(len(overlap)) / len(setB) * 100
result3 = float(len(overlap)) / len(universe) * 100

【讨论】:

    【解决方案2】:
    >>> len(set(listA)&set(listB)) / float(len(set(listA) | set(listB))) * 100
    75.0
    

    我会从不同的项目总数中计算出常见的项目。

    len(set(listA)&set(listB)) 返回常见项目(在您的示例中为 3)。

    len(set(listA) | set(listB)) 返回不同项目的总数 (4)。

    乘以 100 得到百分比。

    【讨论】:

    • 请注意,这个答案和@JuniorCompressor 的答案是不同的,都是正确的,但取决于具体要求。
    【解决方案3】:

    最大的区别是两个列表有完全不同的元素。所以我们最多有n + m 离散元素,其中n 是第一个列表的大小,m 是第二个列表的大小。一种措施可以是:

    2 * c / (n + m)
    

    其中c 是公共元素的数量。这可以像这样计算为百分比:

    200.0 * len(set(listA) & set(listB)) / (len(listA) + len(listB))
    

    【讨论】:

    • 以下示例失败:listA = ["Alice", "Alice"] listB = ["Alice", "Alice"]
    【解决方案4】:
    def computeOverlap(L1, L2):
        d1, d2 = {}, {}
        for e in L1:
            if e not in d1:
                d1[e] = 1
            d1[e] += 1
    
        for e in L2:
            if e not in d2:
                d2[e] = 0
            d2[e] += 1
    
        o1, o2 = 0, 0
        for k in d1:
            o1 += min(d1[k], d2.get(k,0))
        for k in d2:
            o2 += min(d1.get(k,0), d2[k])
    
        print((100*o1) if o1 else 0 "% of the first list overlaps with the second list")
        print((100*o2) if o2 else 0 "% of the second list overlaps with the first list")
    

    当然,您可以使用 defaultdict 和 counter 来完成此操作,以使事情变得更容易:

    from collections import defaultdict, Counter
    
    def computeOverlap(L1, L2):
        d1 = defaultdict(int, Counter(L1))
        d2 = defaultdict(int, Counter(L2))
    
        o1, o2 = 0, 0
        for k in d1:
            o1 += min(d1[k], d2[k])
        for k in d2:
            o2 += min(d1[k,0], d2[k])
    
        print((100*o1) if o1 else 0 "% of the first list overlaps with the second list")
        print((100*o2) if o2 else 0 "% of the second list overlaps with the first list")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 2021-12-17
      相关资源
      最近更新 更多