Python - подсчет вхождений определенных диапазонов в списке - PullRequest
4 голосов
/ 03 марта 2012

Таким образом, в основном я хочу посчитать количество вхождений, которое с плавающей точкой появляется в данном списке.Например: список оценок (все оценки из 100) вводятся пользователем и сортируются по группам по десять.Сколько раз появляются оценки от 0-10, 10-20, 20-30 и т. Д.)?Как распределение результатов теста.Я знаю, что могу использовать функцию подсчета, но так как я не ищу конкретные числа, у меня возникли проблемы.Есть ли возможность объединить счет и диапазон?Спасибо за любую помощь.

Ответы [ 4 ]

7 голосов
/ 03 марта 2012

Чтобы сгруппировать данные, разделите их на ширину интервала. Чтобы подсчитать число в каждой группе, рассмотрите возможность использования collection.Counter . Вот отработанный пример с документацией и тестом:

from collections import Counter

def histogram(iterable, low, high, bins):
    '''Count elements from the iterable into evenly spaced bins

        >>> scores = [82, 85, 90, 91, 70, 87, 45]
        >>> histogram(scores, 0, 100, 10)
        [0, 0, 0, 0, 1, 0, 0, 1, 3, 2]

    '''
    step = (high - low + 0.0) / bins
    dist = Counter((float(x) - low) // step for x in iterable)
    return [dist[b] for b in range(bins)]

if __name__ == '__main__':
    import doctest
    print doctest.testmod()
6 голосов
/ 03 марта 2012

Если вы хорошо используете внешнюю библиотеку NumPy, вам просто нужно позвонить numpy.histogram():

>>> data = [82, 85, 90, 91, 70, 87, 45]
>>> counts, bins = numpy.histogram(data, bins=10, range=(0, 100))
>>> counts
array([0, 0, 0, 0, 1, 0, 0, 1, 3, 2])
>>> bins
array([   0.,   10.,   20.,   30.,   40.,   50.,   60.,   70.,   80.,
         90.,  100.])
4 голосов
/ 03 марта 2012
decs = [int(x/10) for x in scores]

карты оценки от 0-9 -> 0, 10-19 -> 1 и так далее.Затем просто посчитайте вхождения 0, 1, 2, 3 и т. Д. (Через что-то вроде collections.Counter) и отобразите обратно диапазоны.

2 голосов
/ 03 марта 2012

Этот метод использует bisect, который может быть более эффективным, но он требует, чтобы вы сначала отсортировали результаты.

from bisect import bisect
import random

scores = [random.randint(0,100) for _ in xrange(100)]
bins = [20, 40, 60, 80, 100]

scores.sort()
counts = []
last = 0
for range_max in bins:
    i = bisect(scores, range_max, last)
    counts.append(i - last)
    last = i

Я бы не ожидал, что вы установите numpy только для этого, но если вы ужеNumpy вы можете использовать numpy.histogram.

ОБНОВЛЕНИЕ

Во-первых, использование bisect является более гибким.Использование [i//n for i in scores] требует, чтобы все лотки были одинакового размера.Использование bisect позволяет бинам иметь произвольные пределы.Также i//n означает, что диапазоны [вот, привет).При использовании пополам диапазоны (lo, hi), но вы можете использовать bisect_left, если хотите [lo, hi).

Второй пополам быстрее, см. Время ниже.Я заменил Scores.sort () на более медленную сортировку (баллы), потому что сортировка - самый медленный шаг, и я не хотел смещать время с предварительно отсортированным массивом, но ОП говорит, что его / ее массив ужеотсортировано, так что пополам может иметь еще больше смысла в этом случае.

setup="""
from bisect import bisect_left
import random
from collections import Counter

def histogram(iterable, low, high, bins):
    step = (high - low) / bins
    dist = Counter(((x - low + 0.) // step for x in iterable))
    return [dist[b] for b in xrange(bins)]

def histogram_bisect(scores, groups):
    scores = sorted(scores)
    counts = []
    last = 0
    for range_max in groups:
        i = bisect_left(scores, range_max, last)
        counts.append(i - last)
        last = i
    return counts

def histogram_simple(scores, bin_size):
    scores = [i//bin_size for i in scores]
    return [scores.count(i) for i in range(max(scores)+1)]

scores = [random.randint(0,100) for _ in xrange(100)]
bins = range(10, 101, 10)
"""
from timeit import repeat
t = repeat('C = histogram(scores, 0, 100, 10)', setup=setup, number=10000)
print min(t)
#.95
t = repeat('C = histogram_bisect(scores, bins)', setup=setup, number=10000)
print min(t)
#.22
t = repeat('histogram_simple(scores, 10)', setup=setup, number=10000)
print min(t)
#.36
...