【问题标题】:Calculating the mode in a multimodal list in Python在 Python 中计算多模式列表中的模式
【发布时间】:2012-03-05 13:46:32
【问题描述】:

我正在尝试计算 Python 中值列表的众数(最常见的值)。我想出了一个解决方案,无论如何给出了错误的答案,但我随后意识到我的数据可能是多模态的;

ie 1,1,2,3,4,4 mode = 1 & 4

这是我到目前为止的想法:

def mode(valueList):
  frequencies = {}
  for value in valueList:
    if value in frequencies:
      frequencies[value] += 1
    else:
      frequencies[value] = 1
  mode = max(frequencies.itervalues())
  return mode

我认为这里的问题是我输出的是值而不是最大值的指针。无论如何,任何人都可以提出一种更好的方法来做到这一点,这种方法可以在不止一种模式下工作吗?或者如果失败了,我该如何修复我目前所拥有的并确定单一模式?

您可能会说我对 python 很陌生,感谢您的帮助。

编辑:应该提到我在 Python 2.4 中

【问题讨论】:

  • 你真的应该升级到最新支持的 Python 版本。

标签: python statistics


【解决方案1】:

在 Python >=2.7 中,将collections.Counter 用于频率表。

from collections import Counter
from itertools import takewhile

data = [1,1,2,3,4,4]
freq = Counter(data)
mostfreq = freq.most_common()
modes = list(takewhile(lambda x_f: x_f[1] == mostfreq[0][1], mostfreq))

请注意使用匿名函数 (lambda) 检查一对 (_, f) 是否与最频繁的元素具有相同的频率。

【讨论】:

  • @Captastic:那你真的应该升级了。 Python 2.4 是从 2004 年开始的;甚至 Python 2.5 也不再收到安全补丁。
  • 如果我能在我的版本 3.2.3 上让最后一个“takewhile”行在没有 SyntaxError 的情况下工作,我会很高兴,但我是新手。想法?
  • @MatthewCornell:函数定义(包括 lambdas)中的元组解包在 3.2 甚至更早版本中被删除。我会更新答案。
【解决方案2】:

请注意,从Python 3.8 开始,标准库包含statistics.multimode 函数,以按最常出现的值的顺序返回最常出现的值的列表:

from statistics import multimode

multimode([1, 1, 2, 3, 4, 4])
# [1, 4]

【讨论】:

    【解决方案3】:

    嗯,第一个问题是,是的,您返回的是 frequences 中的值而不是键。这意味着您获得了模式的 count,而不是模式本身。通常,要获取模式,您可以使用 key 关键字参数来设置 max,如下所示:

    >>> max(frequencies, key=counts.get())
    

    但在 2.4 中不存在!这是我相信在 2.4 中可以使用的方法:

    >>> import random
    >>> l = [random.randrange(0, 5) for _ in range(50)]
    >>> frequencies = {}
    >>> for i in l:
    ...     frequencies[i] = frequencies.get(i, 0) + 1
    ... 
    >>> frequencies
    {0: 11, 1: 13, 2: 8, 3: 8, 4: 10}
    >>> mode = max((v, k) for k, v in frequencies.iteritems())[1]
    >>> mode
    1
    >>> max_freq = max(frequencies.itervalues())
    >>> modes = [k for k, v in frequencies.iteritems() if v == max_freq]
    >>> modes
    [1]
    

    比起cmp 关键字,我更喜欢decorate-sort-undecorate 成语。我认为它更具可读性。可能这只是我。

    【讨论】:

    • 非常感谢,我也应该提到我在 2.4 中。我已经更新了帖子。
    • @Captastic,啊。没有defaultdict,没有Counter,也没有key 参数max。呸。必须以艰难的方式做到这一点......只需一秒钟。
    • 在 Py2.4 中,您将使用 cmp 参数到 max 而不是 key(尚不存在);所以,mode = max(frequencies, cmp=lambda i,j: cmp(counts[i], counts[j])).
    • @senderle 就是这个!它工作得很好。非常感谢。现在来了解它是如何工作的:)
    【解决方案4】:

    您可以在迭代时使用计数器作为最大值,如下所示:

    def mode(valueList):
      frequencies = {}
      mx = None
      for value in valueList:
        if value in frequencies:
          frequencies[value] += 1
        else:
          frequencies[value] = 1
        if not mx or frequencies[value] > mx[1]:
          mx = (value, frequencies[value])
    
      mode = mx[0]
      return mode
    

    另一种用于多种模式的方法,使用 nlargest,它可以为您提供字典的 N 个最大值:

    from heapq import nlargest
    import operator
    
    def mode(valueList, nmodes):
      frequencies = {}
    
      for value in valueList:
        frequencies[value] = frequencies.get(value, 0) + 1
    
      return [x[0] for x in nlargest(nmodes,frequencies.iteritems(),operator.itemgetter(1))]
    

    【讨论】:

    • 就可以了,谢谢。虽然不确定如何将其转换为使用多种模式。
    • 感谢您的意见,我已经采用了 senderles 方法,但如果只是为了学习经验,我将不得不与您一起玩。
    猜你喜欢
    • 2018-09-19
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多