在列表列表中查找最常见的元素

Finding the most common element in a list of lists

我得到了这样一个列表列表:

pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
         [(2, 2), (2, 1)], 
         [(1, 1), (1, 2), (2, 2), (2, 1)]]

并且期望的输出是:{(2,2)}.

我需要找到出现频率最高的元素。如果有元素重复同样多次,它必须 return 多个值。

我尝试用三个列表的交集来解决它,但它打印出 {(2,1), (2,2)},而不是 {(2,2)},因为元素 (2,2) 在第一个列表中重复了两次.

我看到了一些 import collections 的示例,但我不理解它们,所以我不知道如何更改代码以适合我的问题。

我还尝试了以下方法:

seen = set()
repeated = set()
for l in pairs:
    for i in set(l):
        if i in seen:
            repeated.add(i)
        if i in repeated:
            repeated.add(i)
        else:
            seen.add(i)

但仍然没有return正确答案。

collections.Counter() 会起作用...您只需要弄清楚如何传递嵌套列表中的所有对,您可以通过列表理解来做到这一点。例如:

from collections import Counter

pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
         [(2, 2), (2, 1)], 
         [(1, 1), (1, 2), (2, 2), (2, 1)]]

counts = Counter(pair for l in pairs for pair in l)
counts.most_common(1)
# [((2, 2), 4)]

如果出现平局,您将需要查看排名靠前的选项并挑出数量相同的选项。您可以通过查看 counts.most_common().

获得排序列表

itertools.groupby 是处理这种情况的常用方法。例如,如果您有平局,您可以获得所有排名靠前的条目,例如:

from collections import Counter
from itertools import groupby

pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
         [(2, 2), (2, 1)], 
         [(1, 1), (1, 2), (2, 2), (2, 1), (3, 2)]]

counts = Counter(pair for l in pairs for pair in l)

count, groups = next(groupby(counts.most_common(), key=lambda t: t[1]))
[g[0] for g in groups]
# [(2, 2), (3, 2)]

不使用 collections 中的 Counter 方法的替代解决方案:

def get_freq_tuple(data):
    counts = {}
    for pairs in data:
        for pair in pairs:
            counts[pair] = counts.get(pair, 0) + 1

    return [pair for pair in counts if counts[pair] == max(counts.values())]

if __name__ == "__main__":
    pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1),
              (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)],
             [(2, 2), (2, 1)],
             [(1, 1), (1, 2), (2, 2), (2, 1)]]
    print(get_freq_tuple(pairs))

输出:

[(2, 2)]

解释:

  • 计算每个元组的出现次数并将它们存储在字典中。字典的键是元组,值是出现。
  • 根据元组的最大出现次数过滤字典中的元组。

免责声明:

  • 使用 collections 中的 Counter 方法效率更高。

参考文献:

正如评论中所暗示的那样,defaultdict 非常有帮助。

from collections import defaultdict

我们有“成对”,但由于您想要 所有 列表中出现频率最高的,我们会将其展平。

pairs = [[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (2, 1), (3, 1), (3, 2), (3, 3), (3, 2), (2, 2)], 
         [(2, 2), (2, 1)], 
         [(1, 1), (1, 2), (2, 2), (2, 1)]]

flat_pairs = [tpl for lst in pairs for tpl in lst]

现在我们将创建一个默认为零的 defaultdict 来保存我们的计数,并迭代 flat_pairs 以将计数添加到字典中。

counts = defaultdict(lambda: 0)

for tpl in flat_pairs: 
    counts[tpl] += 1

或者我们可以跳过展平阶段:

counts = defaultdict(lambda: 0)

for lst in pairs:
    for tpl in lst: 
        counts[tpl] += 1

我们可以通过对字典的值使用 max 来找到最大计数值,然后使用列表理解来获得具有最大计数的一个或多个元组。

max_count = max(counts.values())

max_count_tuples = [tpl for tpl, count in counts.items() if count == max_count]