2016-02-12 3 views
5

Рассмотрим вычисление гистограммы Numpy массива, который возвращает проценты:Фильтрация гистограммы краев и подсчитывает

# 500 random numbers between 0 and 10,000 
values = np.random.uniform(0,10000,500) 

# Histogram using e.g. 200 buckets 
perc, edges = np.histogram(values, bins=200, 
          weights=np.zeros_like(values) + 100/values.size) 

Вышеуказанные возвращает два массива:

  • perc, содержащий % (т.е. проценты) значений в пределах каждая пара последовательных edges[ix] и edges[ix+1] из общей суммы.
  • edges длины len(hist)+1

Теперь, говорят, что я хочу, чтобы фильтровать perc и edges так, что я только в конечном итоге с процентами и ребер для значений, содержащихся в новом диапазоне [m, M]. '

То есть, я хочу работать с подмассивами из perc и edges соответствующих интервала значений, в пределах [m, M]. Излишне говорить, что новый массив процентов будет по-прежнему относиться к суммарному счету фракций входного массива. Мы просто хотим отфильтровать perc и edges, чтобы получить правильные подмассивы.

Как я могу обработать perc и edges?

Значения m и M могут быть любым количеством конечно. В приведенном выше примере мы можем предположить, например, m = 0 и M = 200. работа

ответ

2
m = 0; M = 200 
mask = [(m < edges) & (edges < M)] 
>>> edges[mask] 
array([ 37.4789683 , 87.07491593, 136.67086357, 186.2668112 ]) 

Давайте на меньшем наборе данных, так что легче понять:

np.random.seed(0) 
values = np.random.uniform(0, 100, 10) 
values.sort() 
>>> values 
array([ 38.34415188, 42.36547993, 43.75872113, 54.4883183 , 
     54.88135039, 60.27633761, 64.58941131, 71.51893664, 
     89.17730008, 96.36627605]) 

# Histogram using e.g. 10 buckets 
perc, edges = np.histogram(values, bins=10, 
          weights=np.zeros_like(values) + 100./values.size) 

>>> perc 
array([ 30., 0., 20., 10., 10., 10., 0., 0., 10., 10.]) 

>>> edges 
array([ 38.34415188, 44.1463643 , 49.94857672, 55.75078913, 
     61.55300155, 67.35521397, 73.15742638, 78.9596388 , 
     84.76185122, 90.56406363, 96.36627605]) 

m = 0; M = 50 
mask = (m <= edges) & (edges < M) 
>>> mask 
array([ True, True, True, False, False, False, False, False, False, 
     False, False], dtype=bool) 

>>> edges[mask] 
array([ 38.34415188, 44.1463643 , 49.94857672]) 

>>> perc[mask[:-1]][:-1] 
array([ 30., 0.]) 

m = 40; M = 60 
mask = (m < edges) & (edges < M) 
>>> edges[mask] 
array([ 44.1463643 , 49.94857672, 55.75078913]) 
>>> perc[mask[:-1]][:-1] 
array([ 0., 20.]) 
+0

Спасибо, но как теперь мы используем 'mask' также фильтровать' perc'? –

1

Ну вы, возможно, потребуется немного математики для этого. Бункеры равномерно разнесены, так что вы можете определить, какой бункер является первым, чтобы включить и который является последним, используя ширину каждого бина:

bin_width = edges[1] - edges[0] 

Вычислим теперь первый и последний действительный бункер:

first = math.floor((m - edges[0])/bin_width) + 1 # How many bins from the left 
last = math.floor((edges[-1] - M)/bin_width) + 1 # How many bins from the right 

(не обращайте внимания на +1 для обоих, если вы хотите включить в бункер, содержащий m или M - но тогда будьте осторожны, что вы не до конца с отрицательными значениями для первого и последнего)

Теперь вы знаете, сколько бункеров для включения:

valid_edges = edges[first:-last] 
valid_perc = perc[first:-last] 

Это исключит первые first точки и последние last баллов.

Возможно, я не уделял достаточного внимания округлению, и есть включенная ошибка, но я думаю, что идея звучит. :-)

Вам, вероятно, нужно поймать особые случаи, такие как M > edges[-1], но для удобства чтения я их не включил.


Или, если контейнеры не равноудаленные использовать логические маски вместо расчета:

first = edged[edges < m].size + 1 
last = edged[edges > M].size + 1 
Смежные вопросы