Python: создать дистрибутив из списка на основе количества элементов, попадающих в определенные диапазоны

1

Я отметил этот вопрос с помощью poisson, так как не уверен, будет ли он полезен в этом случае.

Мне нужно создать дистрибутив (возможно, отформатированный как изображение в конце) из списка данных.

Например:

data = [1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 10, 10, 10, 22, 30, 30, 35, 46, 58, 59, 59]

чтобы данные могли использоваться для создания визуального распределения. Я мог бы, например, в этом случае сказать, что диапазоны находятся в 10, и в каждом диапазоне должно быть не менее 3 элементов.

В этом примере данные, я ожидаю, что результат будет аналогичен

ditribution = [1, 2, 4, 6]

так как у меня есть > 3 элемента в диапазонах 0-9, 10-19, 30-39 и 50-59. Используя этот результат, я мог бы создать изображение, в котором сегменты сегментированы (более темный цвет), которые существуют в моем конечном распределении. Пример типа изображения, который я пытаюсь создать, можно увидеть ниже и был бы создан с гораздо большим количеством данных. Игнорируйте синюю линию на данный момент.

Я знаю, как сделать это методом грубой силы, итерации по каждому элементу списка и выполнению моих вычислений. Но мой набор данных может иметь сотни тысяч или даже миллионы чисел. Мой диапазон (10) и мое необходимое количество предметов (3), вероятно, будут намного больше в реальном мире.

Изображение 174551

Спасибо за любую помощь.

  • 0
    Ваши входные данные всегда сортируются?
  • 0
    На мой неподготовленный глаз это выглядит как случай для numpy . Вы, вероятно, знаете лучше, хотя :)
Показать ещё 2 комментария
Теги:
poisson
distribution

3 ответа

4
Лучший ответ

Если data всегда сортируется, можно использовать компактный подход:

import itertools as it

d = [k+1 for k, L in
         ((k, len(list(g))) for k, g in it.groupby(data,key=lambda x:x//10))
     if L>=3]

Если data не сортируется или если вы не знаете, используйте sorted(data) в качестве первого аргумента для itertools.groupby, а не только data.

Если вы предпочитаете менее плотный/компактный подход, вы можете, конечно, расширить это, например. в:

def divby10(x): return x//10

distribution = []
for k, g in it.groupby(data, key=divby10):
    L = len(list(g))
    if L < 3: continue
    distribution.append(k+1)

В любом случае механизм состоит в том, что groupby сначала применяет вызываемый, передаваемый как key= к каждому элементу в итерабельном переданном в качестве первого аргумента, для получения "ключа" каждого элемента; для каждой последовательной группы элементов, имеющих один и тот же "ключ", groupby дает кортеж с двумя элементами: значением ключа и итерированием по всем элементам в указанной группе.

Здесь ключ получается путем деления элемента на 10 (с усечением); len(list(g)) - количество последовательных элементов с этим "ключом". Поскольку элементы должны быть последовательными, вам нужны данные для сортировки (и проще их сортировать, чем сортировать по значению, деленное на 10 с усечением "; -).

2

Так как data может быть очень длинным, вам может понадобиться использовать numpy. Он предоставляет множество полезных функций для численной работы, для хранения data в массиве numpy требуется меньше памяти, чем список Python [*], и поскольку многие из функций numpy вызывают функции C под капотом, вы можете получить некоторую прирост скорости:

import numpy as np

data = np.array([1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 10, 10, 10, 22, 30, 30, 35, 46, 58, 59, 59])

hist,bins=np.histogram(data,bins=np.linspace(0,60,7))
print(hist)
# [11  3  1  3  1  3]

distribution=np.where(hist>=3)[0]+1
print(distribution)
# [1 2 4 6]

[*] - Примечание: В приведенном выше коде был сформирован список Python в процессе определения data. Таким образом, максимальная потребность в памяти здесь больше, чем если бы вы использовали список Python. Однако память должна быть освобождена, если нет других ссылок на список Python. В качестве альтернативы, если данные хранятся на диске, numpy.loadtxt можно использовать для чтения непосредственно в массив numpy.

0

Это звучит как работа для некоторой формы гистограммы. Для этого не требуется предварительный сбор. Я обсуждаю использование варианта сортировки ведра для группировки близлежащих элементов здесь, хотя вам необходимо настроить этот алгоритм в соответствии с вашими потребностями. Обратите внимание, что вам не нужно хранить номера в ведрах, чтобы сформировать гистограмму

Ещё вопросы

Сообщество Overcoder
Наверх
Меню