Chcę uzyskać listę danych zawartych w pojemniku histogramu. Używam numpy i Matplotlib. Wiem, jak przejść przez dane i sprawdzić krawędzie pojemnika. Jednak chcę to zrobić dla histogramu 2D i kod do tego jest raczej brzydki. Czy numpy ma jakieś konstrukcje, aby to ułatwić?Jak uzyskać dane w bin histogramie
W przypadku przypadku 1D można użyć funkcji searchsorted(). Ale logika nie jest o wiele lepsza i nie chcę robić wyszukiwania binarnego w każdym punkcie danych, kiedy nie muszę.
Większość nieprzyjemnej logiki wynika z regionów granic bin. Wszystkie regiony mają takie granice: [lewa krawędź, prawa krawędź]. Z wyjątkiem ostatniego pojemnika, który ma taki region: [lewa krawędź, prawa krawędź].
Oto przykładowy kod dla przypadku 1D:
import numpy as np
data = [0, 0.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 3]
hist, edges = np.histogram(data, bins=3)
print 'data =', data
print 'histogram =', hist
print 'edges =', edges
getbin = 2 #0, 1, or 2
print '---'
print 'alg 1:'
#for i in range(len(data)):
for d in data:
if d >= edges[getbin]:
if (getbin == len(edges)-2) or d < edges[getbin+1]:
print 'found:', d
#end if
#end if
#end for
print '---'
print 'alg 2:'
for d in data:
val = np.searchsorted(edges, d, side='right')-1
if val == getbin or val == len(edges)-1:
print 'found:', d
#end if
#end for
Oto przykładowy kod dla przypadku 2D:
import numpy as np
xdata = [0, 1.5, 1.5, 2.5, 2.5, 2.5, \
0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, \
0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 3]
ydata = [0, 5,5, 5, 5, 5, \
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, \
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 30]
xbins = 3
ybins = 3
hist2d, xedges, yedges = np.histogram2d(xdata, ydata, bins=(xbins, ybins))
print 'data2d =', zip(xdata, ydata)
print 'hist2d ='
print hist2d
print 'xedges =', xedges
print 'yedges =', yedges
getbin2d = 5 #0 through 8
print 'find data in bin #', getbin2d
xedge_i = getbin2d % xbins
yedge_i = int(getbin2d/xbins) #IMPORTANT: this is xbins
for x, y in zip(xdata, ydata):
# x and y left edges
if x >= xedges[xedge_i] and y >= yedges[yedge_i]:
#x right edge
if xedge_i == xbins-1 or x < xedges[xedge_i + 1]:
#y right edge
if yedge_i == ybins-1 or y < yedges[yedge_i + 1]:
print 'found:', x, y
#end if
#end if
#end if
#end for
Czy jest czystszy/bardziej efektywny sposób to zrobić? Wygląda na to, że numpy ma coś do tego.
Tak z ciekawości; dlaczego używasz komentarzy takich jak #end, jeśli masz kod? "Każdy piksel się liczy" Robiąc to, ignorujesz cel wcięcia. –
2 powody. Najpierw jestem programistą C++, a drugi program python. Brak aparatów Pythona irytuje mnie bez końca. Kiedy mam skomplikowane bloki kodu z wieloma różnymi wcięciami, nie chcę odliczać białych znaków. I robię większość mojego rozwoju w Emacs. Poprzez umieszczanie komentarzy zamykających na blokach kodu, pozwala mi on naciskać klawisz TAB na każdej linii, a Emacs nie będzie próbował niczego błędnie wciskać. – Ben