Расчет режима в мультимодальном списке в Python - PullRequest
4 голосов
/ 05 марта 2012

Я пытаюсь вычислить режим (наиболее частое значение) списка значений в 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, спасибо за помощь.

edit: должен был упомянуть, что я на Python 2.4

Ответы [ 3 ]

5 голосов
/ 05 марта 2012

Ну, первая проблема в том, что да, вы возвращаете значение в frequences, а не ключ.Это означает, что вы получаете количество режима, а не сам режим.Обычно, чтобы получить режим, вы должны использовать ключевое слово 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]

Я предпочитаю идиому decorate-sort-undecorate для ключевого слова cmp.Я думаю, что это более читабельно.Может быть, это только я.

5 голосов
/ 05 марта 2012

В 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) ту же частоту, что и наиболее частый элемент.

1 голос
/ 05 марта 2012

вы можете использовать счетчик для верхнего значения во время итерации, что-то вроде этого:

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))]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...