Возвращает индексы данных для всех бинов со счетчиками больше порогового - PullRequest
1 голос
/ 17 июня 2020

Я пытаюсь найти все индексы в определенном бункере бункера данных, который мне понравился:

import numpy as np

x=np.random.random(1000)
y=np.random.random(1000)
#The bins are not evenly spaced and not the same number in x and y. 
xedges=np.array(0.1,0.2, 0.4, 0.5, 0.55, 0.6, 0.8, 0.9)
yedges=np.arange(0.1,0.2, 0.4, 0.5, 0.55, 0.6, 0.8, 0.9)

h=np.histogram2d(x,y, bins=[xedges,yedges])

Я хочу найти индексы (затем построить их и c), содержащиеся в каждом бункере что больше некоторого порогового числа отсчетов. Таким образом, каждая ячейка со счетчиком, превышающим пороговое значение, является «кластером», и я хочу знать все точки данных (x, y) в этом кластере.

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

thres=5 
mask=(h>5)

for i in mask:
    # for each bin with count > thres 
    # get bin edges for x and y directions 

    # find  (rightEdge < x < leftEdge) and (rightEdge < y < leftEdge)

    # return indices for each True in mask 

plt.plot(x[indices], y[indicies])

Я пробовал читать документацию для таких функций, как scipy.stats.binned_statistic2d и pandas .DataFrame.groupby , но я не мог понять как применить это к моим данным. Для binned_statistic2d они запрашивают аргумент values:

Данные, по которым будет вычисляться статистика c. Это должна быть та же форма, что и x, или набор последовательностей - каждая такая же форма, как x.

И я не был уверен, как вводить данные, на которых я хотел, чтобы они были вычислены.

Спасибо за любую помощь, которую вы можете оказать по этому вопросу.

1 Ответ

1 голос
/ 17 июня 2020

Если я правильно понимаю, вы хотите построить маску на исходных точках, указывающую, что точка принадлежит ячейке с более чем 5 точками.

Чтобы построить такую ​​маску, np.histogram2d возвращает количество для каждой ячейки, но не указывает, какая точка в какую ячейку попадает.

Вы можете построить такую ​​маску, перебирая каждую ячейку, которая удовлетворяет условию, и добавляя все соответствующие индексы точек к маске.

Для визуализации результата np.histogram2d можно использовать plt.pcolormesh. Рисование me sh с h > 5 покажет все значения True с наивысшим цветом (красный) и значения False с самым низким цветом (синий).

from matplotlib import pyplot as plt
import numpy as np

x = np.random.uniform(0, 2, 500)
y = np.random.uniform(0, 1, x.shape)

xedges = np.array([0.1, 0.2, 0.5, 0.55, 0.6, 0.8, 1.0, 1.3, 1.5, 1.9])
yedges = np.array([0.1, 0.2, 0.4, 0.5, 0.55, 0.6, 0.8, 0.9])

hist, _xedges, _yedges = np.histogram2d(x, y, bins=[xedges, yedges])

h = hist.T  # np.histogram2d transposes x and y, therefore, transpose the resulting array
thres = 5
desired = h > thres
plt.pcolormesh(xedges, yedges, desired, cmap='coolwarm', ec='white', lw=2)

mask = np.zeros_like(x, dtype=np.bool)  # start with mask all False
for i in range(len(xedges) - 1):
    for j in range(len(yedges) - 1):
        if desired[j, i]:
            # print(f'x from {xedges[i]} to {xedges[i + 1]} y from {yedges[j]} to {yedges[j + 1]}')
            mask = np.logical_or(mask, (x >= xedges[i]) & (x < xedges[i + 1]) & (y >= yedges[j]) & (y < yedges[j + 1]))
            # plt.scatter(np.random.uniform(xedges[i], xedges[i+1], 100), np.random.uniform(yedges[j], yedges[j+1], 100),
            #             marker='o', color='g', alpha=0.3)
plt.scatter(x, y, marker='o', color='gold', label='initial points')
plt.scatter(x[mask], y[mask], marker='.', color='green', label='filtered points')
plt.legend(bbox_to_anchor=(1.02, 1), loc='upper left')
plt.tight_layout()
plt.show()

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

example plot

...