Python Matplotlib rechteckiger Binning
-
19-09-2019 - |
Frage
Ich habe eine Reihe von (x, y) bekommt Werte, dass ich ein 2D-Histogramm darstellen möge Python matplotlib zu verwenden. Mit hexbin, ich so etwas wie dieses:
Aber ich bin auf der Suche nach so etwas wie folgt aus:
Beispielcode:
from matplotlib import pyplot as plt
import random
foo = lambda : random.gauss(0.0,1.0)
x = [foo() for i in xrange(5000)]
y = [foo() for i in xrange(5000)]
pairs = zip(x,y)
#using hexbin I supply the x,y series and it does the binning for me
hexfig = plt.figure()
hexplt = hexfig.add_subplot(1,1,1)
hexplt.hexbin(x, y, gridsize = 20)
#to use imshow I have to bin the data myself
def histBin(pairsData,xbins,ybins=None):
if (ybins == None): ybins = xbins
xdata, ydata = zip(*pairsData)
xmin,xmax = min(xdata),max(xdata)
xwidth = xmax-xmin
ymin,ymax = min(ydata),max(ydata)
ywidth = ymax-ymin
def xbin(xval):
xbin = int(xbins*(xval-xmin)/xwidth)
return max(min(xbin,xbins-1),0)
def ybin(yval):
ybin = int(ybins*(yval-ymin)/ywidth)
return max(min(ybin,ybins-1),0)
hist = [[0 for x in xrange(xbins)] for y in xrange(ybins)]
for x,y in pairsData:
hist[ybin(y)][xbin(x)] += 1
extent = (xmin,xmax,ymin,ymax)
return hist,extent
#plot using imshow
imdata,extent = histBin(pairs,20)
imfig = plt.figure()
implt = imfig.add_subplot(1,1,1)
implt.imshow(imdata,extent = extent, interpolation = 'nearest')
plt.draw()
plt.show()
Es scheint, wie es sollte schon eine Möglichkeit, dies zu tun, ohne mein eigenes Schreiben „Binning“ Methode und mit imshow.
Lösung
hat Numpy eine Funktion namens histogram2d , deren Docstring zeigt Ihnen auch, wie es Matplotlib mit sichtbar zu machen. In interpolation=nearest
zum imshow Aufruf, um die Interpolation zu deaktivieren.
Andere Tipps
Ich weiß, dass es ein Patch zu matplotlib eingereicht, aber ich nahm den Code aus dem anderen Beispiel ein paar Bedürfnisse acommodate, dass ich hatte.
nun das Histogramm aus der linken unteren Ecke aufgetragen wird, wie dies bei herkömmlicher Mathematik (nicht computing)
auch Werte außerhalb des Binning Bereichs werden ignoriert und verwende ich eine 2d numpy Array für das zweidimensionale Array
änderte ich die Dateneingabe von Paaren zu zwei 1D-Arrays, da dies, wie Daten an Streuung zugeführt wird (x, y) und gleichermaßen Funktionen
def histBin(x,y,x_range=(0.0,1.0),y_range=(0.0,1.0),xbins=10,ybins=None):
""" Helper function to do 2D histogram binning
x, y are lists / 2D arrays
x_range and yrange define the range of the plot similar to the hist(range=...)
xbins,ybins are the number of bins within this range.
"""
pairsData = zip(x,y)
if (ybins == None):
ybins = xbins
xdata, ydata = zip(*pairsData)
xmin,xmax = x_range
xmin = float(xmin)
xmax = float(xmax)
xwidth = xmax-xmin
ymin,ymax = y_range
ymin = float(ymin)
ymax = float(ymax)
ywidth = ymax-ymin
def xbin(xval):
return floor(xbins*(xval-xmin)/xwidth) if xmin <= xval < xmax else xbins-1 if xval ==xmax else None
def ybin(yval):
return floor(ybins*(yval-ymin)/ywidth) if ymin <= yval < ymax else ybins-1 if yval ==ymax else None
hist = numpy.zeros((xbins,ybins))
for x,y in pairsData:
i_x,i_y = xbin(x),ybin(ymax-y)
if i_x is not None and i_y is not None:
hist[i_y,i_x] += 1
extent = (xmin,xmax,ymin,ymax)
return hist,extent
Ich legte nur eine Pull-Anforderung für diese https://github.com/matplotlib/matplotlib/ Zug- / 805 . Hoffentlich wird es akzeptiert.
Ist matplotlib.pyplot.hist
, was Sie suchen?
>>> help(matplotlib.pyplot.hist)
Help on function hist in module matplotlib.pyplot:
hist(x, bins=10, range=None, normed=False, weights=None, cumulative=False, botto
m=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=Fa
lse, hold=None, **kwargs)
call signature::
hist(x, bins=10, range=None, normed=False, cumulative=False,
bottom=None, histtype='bar', align='mid',
orientation='vertical', rwidth=None, log=False, **kwargs)
Compute and draw the histogram of *x*. The return value is a
tuple (*n*, *bins*, *patches*) or ([*n0*, *n1*, ...], *bins*,
[*patches0*, *patches1*,...]) if the input contains multiple
data.
Mit xlim
und ylim
die Grenzen des Grundstücks zu setzen. xlim(-3, 3)
und ylim(-3, 3)
sollte es tun.