2013-02-19 4 views
6

У меня есть список значений и список ребер. Теперь мне нужно проверить все значения в том, в каком бине они принадлежат. Есть ли более вещий способ, чем итерация значений, а затем над бункерами и проверками, если значение принадлежит текущему бункеру, как:Python: проверка, к какому бину принадлежит значение

my_list = [3,2,56,4,32,4,7,88,4,3,4] 
bins = [0,20,40,60,80,100] 

for i in my_list: 
    for j in range(len(bins)): 
     if bins(j) < i < bins(j+1): 
      DO SOMETHING 

Это не выглядит очень красиво для меня. Спасибо!

+0

Начните с сортировки списка. –

ответ

14

Вероятно, слишком поздно, но в будущем, NumPy имеет функцию, которая делает только что:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.digitize.html

>>> my_list = [3,2,56,4,32,4,7,88,4,3,4] 
>>> bins = [0,20,40,60,80,100] 
>>> np.digitize(my_list,bins) 
array([1, 1, 3, 1, 2, 1, 1, 5, 1, 1, 1]) 

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

>>> my_list = [-5,200] 
>>> np.digitize(my_list,bins) 
array([0, 6]) 

И панды есть нечто подобное тоже:

http://pandas.pydata.org/pandas-docs/dev/basics.html#discretization-and-quantiling

>>> pd.cut(my_list, bins) 
Categorical: 
array(['(0, 20]', '(0, 20]', '(40, 60]', '(0, 20]', '(20, 40]', '(0, 20]', 
     '(0, 20]', '(80, 100]', '(0, 20]', '(0, 20]', '(0, 20]'], dtype=object) 
Levels (5): Index(['(0, 20]', '(20, 40]', '(40, 60]', '(60, 80]', 
        '(80, 100]'], dtype=object) 
2

Может быть, это поможет вам на правильном пути:

>>> import itertools 
>>> my_list = [3,2,56,4,32,4,7,88,4,3,4] 
>>> for k, g in itertools.groupby(sorted(my_list), lambda x: x // 20 * 20): 
...  print k, list(g) 
... 
0 [2, 3, 3, 4, 4, 4, 4, 7] 
20 [32] 
40 [56] 
80 [88] 
+0

Удивление, почему голосующий голос. – sberry

3

Прежде всего, ваш код будет сбой в тех случаях, когда значение равно бункерная граница -

изменения

if bins(j) < i < bins(j+1): 

<= знак где-то.

После этого, используйте модуль bisect

import bisect 
bisect.bisect(x, bins) 

или bisect.bisect_right

в зависимости от хотите ли вы предпочитаете брать более высокую или более низкую мусорное ведро, когда значение находится на границе бен.

+1

Я думаю, что аргументы 'bisect' меняются на противоположные. – sberry