Python 在20个随机数的列表中找到最常见的一对、三人组等,播放100次

Python 在20个随机数的列表中找到最常见的一对、三人组等,播放100次,python,math,random,combinations,Python,Math,Random,Combinations,所以我有一个CSV,有100行,每行20个数字,用逗号分隔: 23, 52, 63, 76, 23, 45, ... 39, 52, 83, 33, 35, 23, ... etc. 我想写一个算法,找到一对的所有不同组合,列出它发生的次数,对三人组,四人组,等等做同样的事情 显然,每一行都有很多组合(因为顺序无关紧要) 这将是每一行的答案 所以每行15个组合。。现在我只能想象如果是20而不是6,会有多少人,但现在我们不必担心 因为有15个,我不希望程序显示每一个组合,只显示那些“计数”大于

所以我有一个CSV,有100行,每行20个数字,用逗号分隔:

23, 52, 63, 76, 23, 45, ...
39, 52, 83, 33, 35, 23, ...
etc.
我想写一个算法,找到一对的所有不同组合,列出它发生的次数,对三人组,四人组,等等做同样的事情

显然,每一行都有很多组合(因为顺序无关紧要)

这将是每一行的答案

所以每行15个组合。。现在我只能想象如果是20而不是6,会有多少人,但现在我们不必担心

因为有15个,我不希望程序显示每一个组合,只显示那些“计数”大于1的组合,“计数”是它们发生的次数

因此,如果我只为上面的两行运行程序,为6个数字而不是20个,程序将返回

23, 52: 2
看看如何只显示发生多次的一对,这就是我想做的,但这很简单,只是不显示计数是否等于1

不管怎样,我如何开始创建这个算法?我不知道从哪里开始,我想我应该从每一行开始,然后得到每一双,但我该怎么做呢


提前谢谢你,毫无疑问我会继续破解这个问题,如果我找到解决方案,我会发布它(以及代码)。再次感谢。

代码是内联注释的

import itertools

lines = [[23, 52, 63, 76, 23, 45],
         [39, 52, 83, 33, 35, 23]]

# This set will store the unique elements
# across all lines
uniq = set()

# This list will hold a dict for each line
# These dicts will contain the frequency
# of each unique number in that line

freq = [{} for _ in range(len(lines))]
for index, line in enumerate(lines):
    for j in line:

        freq[index][j] = freq[index].get(j, 0) + 1
        uniq.add(j)

# This will store the frequency of each possible pair
counter = {}

# There will be k * (k - 1) / 2 combinations,
# where k is the number of unique pairs

for i in itertools.combinations(uniq, 2):
    for j in range(len(lines)):

        freq1 = freq[j].get(i[0], 0)
        freq2 = freq[j].get(i[1], 0)

        # Multiplying frequencies gives us the number
        # of pairs with these numbers in this line

        counter[i] = counter.get(i, 0) + (freq1 * freq2)

# Performs a descending sort on all pairs
sol = sorted(counter.items(), key=lambda value: value[1], reverse=True)
print(sol)
输出:

   [((52, 23), 3), ((45, 23), 2), ((23, 63), 2), ((76, 23), 2), ((33, 35), 1),
    ((76, 45), 1), ((52, 63), 1), ((39, 83), 1), ((76, 52), 1), ((45, 52), 1),
    ((35, 39), 1), ((39, 23), 1), ((33, 52), 1), ((39, 52), 1), ((33, 23), 1),
    ((35, 23), 1), ((35, 52), 1), ((76, 63), 1), ((33, 83), 1), ((35, 83), 1),
    ((33, 39), 1), ((83, 23), 1), ((45, 63), 1), ((83, 52), 1), ((83, 63), 0),
    ((35, 76), 0), ((33, 76), 0), ((35, 45), 0), ((33, 45), 0), ((45, 83), 0),
    ((39, 63), 0), ((33, 63), 0), ((39, 76), 0), ((39, 45), 0), ((76, 83), 0),
    ((35, 63), 0)]
[((52, 23), 3), ((45, 23), 2), ((63, 23), 2), ((76, 23), 2), ((76, 52), 1),
 ((76, 45), 1), ((52, 63), 1), ((39, 83), 1), ((35, 39), 1), ((45, 52), 1),
 ((33, 52), 1), ((39, 52), 1), ((33, 23), 1), ((35, 23), 1), ((35, 52), 1),
 ((39, 23), 1), ((76, 63), 1), ((33, 83), 1), ((33, 39), 1), ((83, 23), 1),
 ((45, 63), 1), ((83, 52), 1), ((33, 35), 1), ((35, 83), 1)]
当心!如果列表主要由唯一值组成,则此算法将在~O(n^4)中运行

编辑:这是另一个性能更好的版本(它为每一行维护
uniq
集,因此避免了零大小组合)

输出:

   [((52, 23), 3), ((45, 23), 2), ((23, 63), 2), ((76, 23), 2), ((33, 35), 1),
    ((76, 45), 1), ((52, 63), 1), ((39, 83), 1), ((76, 52), 1), ((45, 52), 1),
    ((35, 39), 1), ((39, 23), 1), ((33, 52), 1), ((39, 52), 1), ((33, 23), 1),
    ((35, 23), 1), ((35, 52), 1), ((76, 63), 1), ((33, 83), 1), ((35, 83), 1),
    ((33, 39), 1), ((83, 23), 1), ((45, 63), 1), ((83, 52), 1), ((83, 63), 0),
    ((35, 76), 0), ((33, 76), 0), ((35, 45), 0), ((33, 45), 0), ((45, 83), 0),
    ((39, 63), 0), ((33, 63), 0), ((39, 76), 0), ((39, 45), 0), ((76, 83), 0),
    ((35, 63), 0)]
[((52, 23), 3), ((45, 23), 2), ((63, 23), 2), ((76, 23), 2), ((76, 52), 1),
 ((76, 45), 1), ((52, 63), 1), ((39, 83), 1), ((35, 39), 1), ((45, 52), 1),
 ((33, 52), 1), ((39, 52), 1), ((33, 23), 1), ((35, 23), 1), ((35, 52), 1),
 ((39, 23), 1), ((76, 63), 1), ((33, 83), 1), ((33, 39), 1), ((83, 23), 1),
 ((45, 63), 1), ((83, 52), 1), ((33, 35), 1), ((35, 83), 1)]

这些对是逐行考虑的,还是跨所有行考虑的?另外,我在上面的几行中总共看到了3对(23,52)…通常这听起来像是频繁集挖掘。@Rishav如果你是对的,我错过了:P,是的,逐行,每次该对出现并且+1被添加到计数开始时,您可以获得一行的所有对,范围为i(n-1):范围为j(i+1,n):打印(第[i]行,第[j]行)。这非常完美,我非常感谢,谢谢。问题是,我的macbook pro 16GB ram在有30多行20个数字的列表时绘制出来,我不介意程序花费很长时间,但我如何才能使它不给我带来死亡之轮?如果我只打印出现次数超过1次的对,会不会更容易?呃,您能用粘贴的方式从
打印(行)
中给我您的输入吗?我会仔细考虑的。好吧,好吧,太多了。。我还在每行使用子字符串[1:21],我也会发布我的代码。@SamirChahine不,这只是因为组合的数量增加了。长度为6的组合为9690000,长度为1的组合为9690000。