Je souhaite obtenir une liste des données contenues dans une corbeille d'histogramme. J'utilise numpy, et Matplotlib. Je sais comment parcourir les données et vérifier les bords de la corbeille. Cependant, je veux le faire pour un histogramme 2D et le code pour le faire est plutôt moche. Est-ce que numpy a des constructions pour rendre cela plus facile?Comment obtenir des données dans une corbeille d'histogramme
Pour le cas 1D, je peux utiliser searchsorted(). Mais la logique n'est pas tellement meilleure, et je ne veux pas vraiment faire une recherche binaire sur chaque point de données quand je n'ai pas à le faire.
La plus grande partie de la mauvaise logique est due aux régions limites de la corbeille. Toutes les régions ont des limites comme celle-ci: [bord gauche, bord droit]. Sauf le dernier bin, qui a une région comme celle-ci: [bord gauche, bord droit].
Voici quelques exemples de code pour le cas 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
Voici quelques exemples de code pour le cas 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
Y at-il un moyen plus propre/plus efficace de le faire? Il semble que tout cela aurait quelque chose pour ça.
Juste par curiosité; pourquoi utilisez-vous des commentaires comme #end si dans votre code? "Chaque pixel compte" En faisant cela, vous ignorez le but de l'indentation. –
2 raisons. Je suis d'abord un développeur C++, puis un développeur python. Le manque d'accolades de Python m'irrite énormément. Quand j'ai des blocs de code compliqués avec beaucoup d'indentation variable, je ne veux pas compter les espaces. Et je fais la majeure partie de mon développement chez Emacs. En mettant des commentaires de fermeture sur les blocs de code, cela me permet d'appuyer sur TAB sur chaque ligne et Emacs n'essaiera pas d'indenter quelque chose à tort. – Ben