【问题标题】:How to get unique values with respective occurrence count from a list in Python?如何从 Python 中的列表中获取具有相应出现次数的唯一值?
【发布时间】:2011-01-24 11:25:46
【问题描述】:

我有一个包含重复项目的列表,我想要一个独特项目的列表及其频率。

例如,我有['a', 'a', 'b', 'b', 'b'],我想要[('a', 2), ('b', 3)]

正在寻找一种无需循环两次的简单方法。

【问题讨论】:

  • 只是让您知道...您接受的答案违反了您的“不循环两次”约束。 (我在这里发表评论,以便您收到通知:-)。
  • 你也能稍微澄清一下你的问题吗?您的项目是否总是组合在一起?或者它们可以按任何顺序出现在列表中吗?
  • 是的,汤姆。虽然我的问题没有具体说明这一点 - 但在我的特殊情况下,这些值正在排序。谢谢。

标签: python list counter


【解决方案1】:

使用 Python 2.7+,您可以使用 collections.Counter

否则,请参阅this counter receipe

在 Python 2.7+ 下:

from collections import Counter
input =  ['a', 'a', 'b', 'b', 'b']
c = Counter( input )

print( c.items() )

输出是:

[('a', 2), ('b', 3)]

【讨论】:

    【解决方案2】:

    如果您的项目被分组(即相似的项目聚集在一起),最有效的使用方法是itertools.groupby

    >>> [(g[0], len(list(g[1]))) for g in itertools.groupby(['a', 'a', 'b', 'b', 'b'])]
    [('a', 2), ('b', 3)]
    

    【讨论】:

    • @Tom:我知道这个限制。但是,当对项目进行分组时,groupby 是有效且首选的方法
    • 你应该说清楚......注意问题中的约束说“我有一个包含重复项目的列表”...... OP给出的列表只是一个例子。我认为这个解决方案不够通用。如果 OP 指定输入列表始终将元素分组,我会同意。
    • @Tom:你是对的 - 我已经更新了答案(顺便说一句,我从他的“重复项目”中假设它们是分组的)
    • 好的 Eli...感谢您的更新 :-)。我撤销了我的 -1,因为你的答案现在更清楚了。
    • 有没有办法按计数对结果元组列表进行排序?
    【解决方案3】:
    >>> mylist=['a', 'a', 'b', 'b', 'b']
    >>> [ (i,mylist.count(i)) for i in set(mylist) ]
    [('a', 2), ('b', 3)]
    

    【讨论】:

      【解决方案4】:

      如果您愿意使用 3rd 方库,NumPy 提供了一个方便的解决方案。如果您的列表仅包含数字数据,这将特别有效。

      import numpy as np
      
      L = ['a', 'a', 'b', 'b', 'b']
      
      res = list(zip(*np.unique(L, return_counts=True)))
      
      # [('a', 2), ('b', 3)]
      

      要理解语法,请注意np.unique 这里返回一个唯一值和计数的元组:

      uniq, counts = np.unique(L, return_counts=True)
      
      print(uniq)    # ['a' 'b']
      print(counts)  # [2 3]
      

      另见:What are the advantages of NumPy over regular Python lists?

      【讨论】:

        【解决方案5】:

        我知道这不是单行的...但对我来说我喜欢它,因为我很清楚我们传递了一次初始值列表(而不是对其调用 count):

        >>> from collections import defaultdict
        >>> l = ['a', 'a', 'b', 'b', 'b']
        >>> d = defaultdict(int)
        >>> for i in l:
        ...  d[i] += 1
        ... 
        >>> d
        defaultdict(<type 'int'>, {'a': 2, 'b': 3})
        >>> list(d.iteritems())
        [('a', 2), ('b', 3)]
        >>>
        

        【讨论】:

          【解决方案6】:

          “老派的方式”。

          >>> alist=['a', 'a', 'b', 'b', 'b']
          >>> d={}
          >>> for i in alist:
          ...    if not d.has_key(i): d[i]=1  #also: if not i in d
          ...    else: d[i]+=1
          ...
          >>> d
          {'a': 2, 'b': 3}
          

          【讨论】:

            【解决方案7】:

            另一种方法是

            mylist = [1, 1, 2, 3, 3, 3, 4, 4, 4, 4]
            mydict = {}
            for i in mylist:
                if i in mydict: mydict[i] += 1
                else: mydict[i] = 1
            

            然后获取元组列表,

            mytups = [(i, mydict[i]) for i in mydict]
            

            这只会遍历列表一次,但它也必须遍历字典一次。但是,鉴于列表中有很多重复项,那么字典应该小很多,因此遍历速度更快。

            不过,我承认,这不是一段非常漂亮或简洁的代码。

            【讨论】:

            • 这在精神上与我的解决方案相同...除了 defaultdict 合并第一部分(因为您不必检查是否存在)并且 list(mydict.iteritems()) 比列表理解。
            • mytups = mydict.items() 是获取元组列表的更简单方法。
            • 感谢@Paul 和@Tom。似乎总有更好的方法在 Python 中做某​​事。 :)
            【解决方案8】:

            没有散列的解决方案:

            def lcount(lst):
               return reduce(lambda a, b: a[0:-1] + [(a[-1][0], a[-1][1]+1)] if a and b == a[-1][0] else a + [(b, 1)], lst, [])
            
            >>> lcount([])
            []
            >>> lcount(['a'])
            [('a', 1)]
            >>> lcount(['a', 'a', 'a', 'b', 'b'])
            [('a', 3), ('b', 2)]
            

            【讨论】:

              【解决方案9】:

              将任意数据结构转化为pandas系列s:

              代码:

              for i in sort(s.value_counts().unique()):
                print i, (s.value_counts()==i).sum()
              

              【讨论】:

                【解决方案10】:

                在 pandas 的帮助下,您可以这样做:

                import pandas as pd
                dict(pd.value_counts(my_list))
                

                【讨论】:

                  猜你喜欢
                  • 2021-07-26
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-11-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-02-06
                  相关资源
                  最近更新 更多