【问题标题】:Python frequency of records while combining combinations组合组合时的Python记录频率
【发布时间】:2018-08-26 15:46:49
【问题描述】:

我已经开始将 python 用于一个宠物项目,因为在 excel 这样的程序中组织这些数据是不可能的。我希望你能给我一些指导,告诉我如何达到我想要的结果。请原谅我缺乏 Python 素养。

我有以下代码,我通过减少列表的数量和这些列表中的元素数量进行了简化,以便于说明。

import itertools
from collections import Counter

a = list(itertools.permutations([32,36,41],3))
b = list(itertools.permutations([36,32,41],3))
c = list(itertools.permutations([19,31,7],3))

fulllist = a+b+c

print(Counter(map(tuple, fulllist)))

给出以下结果:

Counter({(32, 36, 41): 2, (32, 41, 36): 2, (36, 32, 41): 2, (36, 41, 32): 2, (41, 32, 36): 2, (41, 36, 32): 2, (19, 31, 7): 1, (19, 7, 31): 1, (31, 19, 7): 1, (31, 7, 19): 1, (7, 19, 31): 1, (7, 31, 19): 1})

这已经很好了,但不是我需要的。现在我已经对 intertools 生成的每个列表组合进行了第一次计数,我不再关心所述列表中每个元素的顺序。所以,我想得到的最终结果是:

(32, 36, 41): 12 
(19, 31, 7): 6 

并排序,就像我在上面写的一样。 我觉得我可能会绕圈子,也许有一种更简单的方法可以得到我正在寻找的结果。实际上,我的列表中有 15 个元素,其中大约有 50 个要处理。

我希望你能帮我解决这个问题。非常感谢您。

【问题讨论】:

  • 所以真正的最终结果是计数?为什么不只计算这些计数,而不是生成所有这些组合?
  • counts = {},然后是 key = tuple(sorted(inputlist)) 和 count = math.factorial(len(inputlist)) 和 counts[key] = counts.get(key, 0) + count,其中 `inputlist 是这三个输入之一。根本不需要生成任何排列。
  • 旁注:不需要map(tuple, ...)),因为所有排列都已经是元组。你真的应该使用itertools.chain() 来组合排列迭代器。
  • 对于完整的 50 个列表结果,您生成长度为 3 还是长度为 15 的排列?

标签: python python-3.x tuples permutation frequency


【解决方案1】:

如果您不计算排列(在这种情况下使用@Martin 的答案),而这只是用于创建示例列表,只需排序以明确顺序无关紧要:

>>>print(Counter(tuple(sorted(x)) for x in fulllist))
Counter({(32, 36, 41): 12, (7, 19, 31): 6})

【讨论】:

    【解决方案2】:

    如果您只需要计数个可能的排列,那么只需计算这些数字。该数字只是输入长度的阶乘:

    import math
    
    permutationcount = math.factorial(len(inputlist))
    

    如果您要创建的排列比len(inputlist) 短(例如,20 个中有 3 个),那么公式是 n! / (n - k)!:

    n = len(inputlist)
    k = 3
    permutationcount = math.factorial(n) // math.factorial(n - k)
    

    当然,当k 等于n,那么你除以0!,也就是1。

    您可以对输入列表进行排序,并将其转换为元组,从而将键创建为映射:

    from collections import Counter
    
    def count_permutations(lists, k=None):
        counts = Counter()
        if k is None:
            k = len(lists[0])
        for l in lists:
            key = tuple(sorted(l))
            permutationcount = math.factorial(len(l)) // math.factorial(len(l) - k)
            counts[key] += permutationcount
        return counts
    

    演示:

    >>> count_permutations(([32,36,41], [36,32,41], [19,31,7]), k=3)
    Counter({(32, 36, 41): 12, (7, 19, 31): 6})
    

    你当然不需要在这里使用Counter,但是如果你需要.most_common() 方法并且不想查找如何对字典进行排序,那么使用它可能会很方便价值。

    【讨论】:

      【解决方案3】:
      c = Counter(map(tuple, fulllist))
      l = [ {tuple(sorted(i[0])):i[1]} for i in c.items()]  
      
      for e in l:
          print(e)  
      
      {(32, 36, 41): 2}
      {(32, 36, 41): 2}
      {(32, 36, 41): 2}
      {(32, 36, 41): 2}
      {(32, 36, 41): 2}
      {(32, 36, 41): 2}
      {(7, 19, 31): 1}
      {(7, 19, 31): 1}
      {(7, 19, 31): 1}
      {(7, 19, 31): 1}
      {(7, 19, 31): 1}
      {(7, 19, 31): 1}
      

      【讨论】:

      • 这是如何解决 OPs 问题的?您在哪里将数字整理成排序集?
      • @MartijnPieters。你是对的。我没有对元组进行排序。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多