Einführung
In diesem Lab lernen wir, wie man gefüllte Histogramme mit Schraffierungen mit Matplotlib erstellt. Ein Histogramm ist eine grafische Darstellung von Daten, bei der Balken verwendet werden, um die Häufigkeit numerischer Daten anzuzeigen. Ein gefülltes Histogramm mit Schraffierungen ist ein Histogramm, bei dem die Balken mit einem Muster aus Linien, Punkten oder anderen Symbolen gefüllt sind.
Tipps für die VM
Nachdem der Start der VM abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu öffnen.
Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund der Einschränkungen von Jupyter Notebook nicht automatisiert werden.
Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.
Importiere erforderliche Bibliotheken
Wir werden die erforderlichen Bibliotheken für dieses Lab importieren. Wir benötigen die folgenden Bibliotheken:
numpyzum Generieren von Zufallsdatenmatplotlib.pyplotzum Erstellen von Diagrammenmatplotlib.tickerzum Festlegen der Achsenmarkierungsstellencyclerzum Erstellen von Stilzyklenfunctools.partialzum Erstellen einer partielle Funktion
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from cycler import cycler
from functools import partial
Definiere die Histogrammfunktion
Wir werden eine Funktion definieren, um ein Histogramm als gestuftes Patch zu zeichnen. Die Funktion nimmt die folgenden Parameter:
ax: Die Achsen, auf denen geplottet werden solledges: Ein Array der Länge n+1, das die linken Kanten jedes Bins und die rechte Kante des letzten Bins angibtvalues: Ein Array der Länge n mit den Häufigkeiten oder Werten der Binsbottoms: Ein Float oder Array, optional, ein Array der Länge n mit der unteren Grenze der Balken. Wenn None, wird Null verwendet.orientation: Ein String, optional, die Ausrichtung des Histogramms. 'v' (Standard) hat die Balken in die positive y-Richtung zunehmend.
def filled_hist(ax, edges, values, bottoms=None, orientation='v', **kwargs):
"""
Zeichnet ein Histogramm als gestuftes Patch.
Parameter
----------
ax : Achsen
Die Achsen, auf denen geplottet werden soll
Kanten : Array
Ein Array der Länge n+1, das die linken Kanten jedes Bins und die
rechte Kante des letzten Bins angibt.
Werte : Array
Ein Array der Länge n mit den Häufigkeiten oder Werten der Bins
Unterkanten : float oder Array, optional
Ein Array der Länge n mit der unteren Grenze der Balken. Wenn None, wird Null verwendet.
Orientierung : {'v', 'h'}
Ausrichtung des Histogramms. 'v' (Standard) hat
die Balken in die positive y-Richtung zunehmend.
**kwargs
Zusätzliche Schlüsselwortargumente werden an `.fill_between` weitergeleitet.
Rückgabe
-------
ret : PolyCollection
Künstler, der zur Achse hinzugefügt wird
"""
if orientation not in 'hv':
raise ValueError(f"Orientierung muss in {{'h', 'v'}} sein, nicht {orientation}")
kwargs.setdefault('step', 'post')
kwargs.setdefault('alpha', 0.7)
Kanten = np.asarray(Kanten)
Werte = np.asarray(Werte)
if len(Kanten) - 1!= len(Werte):
raise ValueError(f'Muss eine Bin-Kante mehr als Wert angeben, nicht: {len(Kanten)=} {len(Werte)=}')
if Unterkanten ist None:
Unterkanten = 0
Unterkanten = np.broadcast_to(Unterkanten, Werte.shape)
Werte = np.append(Werte, Werte[-1])
Unterkanten = np.append(Unterkanten, Unterkanten[-1])
if Orientierung == 'h':
return ax.fill_betweenx(Kanten, Werte, Unterkanten, **kwargs)
elif Orientierung == 'v':
return ax.fill_between(Kanten, Werte, Unterkanten, **kwargs)
else:
raise AssertionError("Du solltest nie hier sein")
Definiere die gestapelte Histogrammfunktion
Wir werden eine Funktion definieren, um ein gestapeltes Histogramm zu erstellen. Die Funktion nimmt die folgenden Parameter:
ax: Die Achsen, denen Künstler hinzugefügt werden sollenstacked_data: Ein Array der Form (M, N). Die erste Dimension wird iteriert, um die Histogramme zeilenweise zu berechnensty_cycle: Ein Cycler oder ein dict-fähiges Objekt, der Stil, der auf jede Menge angewendet werden sollbottoms: Ein Array, Standardwert: 0, die Anfangspositionen der Unterkantenhist_func: Ein aufrufbares Objekt, optional. Muss die Signaturbin_vals, bin_edges = f(data)haben.bin_edgessollte um eins länger alsbin_valsseinlabels: Eine Liste von Strings, optional, das Label für jede Menge. Wenn nicht angegeben undstacked_dataein Array ist, standardmäßig 'default set {n}'. Wennstacked_dataein Mapping ist undlabelsNone ist, standardmäßig die Schlüssel. Wennstacked_dataein Mapping ist undlabelsangegeben ist, werden nur die aufgelisteten Spalten geplottetplot_func: Ein aufrufbares Objekt, optional, Funktion, die aufgerufen wird, um das Histogramm zu zeichnen. Muss die Signaturret = plot_func(ax, edges, top, bottoms=bottoms, label=label, **kwargs)habenplot_kwargs: Ein Dictionary, optional, alle zusätzlichen Schlüsselwortargumente, die an die Plotfunktion weitergeleitet werden sollen. Dies wird für alle Aufrufe der Plotfunktion gleich sein und wird die Werte insty_cycleüberschreiben
def stack_hist(ax, stacked_data, sty_cycle, bottoms=None, hist_func=None, labels=None, plot_func=None, plot_kwargs=None):
"""
Parameter
----------
ax : axes.Axes
Die Achsen, denen Künstler hinzugefügt werden sollen
stacked_data : array oder Mapping
Ein Array der Form (M, N). Die erste Dimension wird iteriert, um
die Histogramme zeilenweise zu berechnen
sty_cycle : Cycler oder operable of dict
Stil, der auf jede Menge angewendet werden soll
bottoms : array, default: 0
Die Anfangspositionen der Unterkanten.
hist_func : callable, optional
Muss die Signatur `bin_vals, bin_edges = f(data)` haben.
`bin_edges` sollte um eins länger als `bin_vals` sein
labels : liste von str, optional
Das Label für jede Menge.
Wenn nicht angegeben und `stacked_data` ein Array ist, standardmäßig 'default set {n}'
Wenn *stacked_data* ein Mapping ist, und *labels* ist None, standardmäßig die
Schlüssel.
Wenn *stacked_data* ein Mapping ist und *labels* angegeben ist, werden nur die
aufgelisteten Spalten geplottet.
plot_func : callable, optional
Funktion, die aufgerufen wird, um das Histogramm zu zeichnen, muss die Signatur haben:
ret = plot_func(ax, edges, top, bottoms=bottoms,
label=label, **kwargs)
plot_kwargs : dict, optional
Alle zusätzlichen Schlüsselwortargumente, die an die Plotfunktion weitergeleitet werden sollen.
Dies wird für alle Aufrufe der Plotfunktion gleich sein und wird
die Werte in *sty_cycle* überschreiben.
Rückgabe
-------
arts : dict
Dictionary von Künstlern, die nach ihren Labels indiziert sind
"""
## Gehe mit der Standard-Binning-Funktion um
if hist_func is None:
hist_func = np.histogram
## Gehe mit der Standard-Plotfunktion um
if plot_func is None:
plot_func = filled_hist
## Gehe mit dem Standard um
if plot_kwargs is None:
plot_kwargs = {}
versuche:
l_keys = stacked_data.keys()
label_data = True
if labels is None:
labels = l_keys
außer AttributeError:
label_data = False
if labels is None:
labels = itertools.repeat(None)
if label_data:
loop_iter = enumerate((stacked_data[lab], lab, s) für lab, s in zip(labels, sty_cycle))
sonst:
loop_iter = enumerate(zip(stacked_data, labels, sty_cycle))
arts = {}
für j, (data, label, sty) in loop_iter:
wenn label ist None:
label = f'dflt set {j}'
label = sty.pop('label', label)
vals, edges = hist_func(data)
wenn bottoms ist None:
bottoms = np.zeros_like(vals)
top = bottoms + vals
sty.update(plot_kwargs)
ret = plot_func(ax, edges, top, bottoms=bottoms, label=label, **sty)
bottoms = top
arts[label] = ret
ax.legend(fontsize=10)
return arts
Einrichten der Histogrammfunktion mit fester Binung
Wir werden eine Histogrammfunktion mit fester Binung mithilfe von numpy.histogram einrichten. Wir werden 20 Bins erstellen, die von -3 bis 3 reichen.
edges = np.linspace(-3, 3, 20, endpoint=True)
hist_func = partial(np.histogram, bins=edges)
Einrichten von Stilzyklen
Wir werden Stilzyklen für die Histogramme mithilfe von cycler einrichten. Wir werden drei Stilzyklen erstellen: einen für die Flächeneigenschaft, einen für das Label und einen für das Schraffierungsmuster.
color_cycle = cycler(facecolor=plt.rcParams['axes.prop_cycle'][:4])
label_cycle = cycler(label=[f'set {n}' for n in range(4)])
hatch_cycle = cycler(hatch=['/', '*', '+', '|'])
Generiere zufällige Daten
Wir werden zufällige Daten mithilfe von numpy.random.randn generieren. Wir werden 4 Datensätze mit jeweils 12250 Punkten generieren.
np.random.seed(19680801)
stack_data = np.random.randn(4, 12250)
Erstelle das mit Schraffierungen gefüllte Histogramm
Wir werden ein mit Schraffierungen gefülltes Histogramm erstellen, indem wir die zuvor definierte Funktion stack_hist verwenden. Wir werden die zuvor definierten Variablen stack_data, color_cycle und hist_func nutzen. Wir werden auch plot_kwargs so einstellen, dass die Kantenfarbe und die Orientierung eingeschlossen sind.
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5), tight_layout=True)
arts = stack_hist(ax1, stack_data, color_cycle + label_cycle + hatch_cycle, hist_func=hist_func)
arts = stack_hist(ax2, stack_data, color_cycle, hist_func=hist_func, plot_kwargs=dict(edgecolor='w', orientation='h'))
ax1.set_ylabel('counts')
ax1.set_xlabel('x')
ax2.set_xlabel('counts')
ax2.set_ylabel('x')
Erstelle das mit Bezeichnung und Schraffierungen gefüllte Histogramm
Wir werden ein mit Bezeichnung und Schraffierungen gefülltes Histogramm erstellen, indem wir die zuvor definierte Funktion stack_hist verwenden. Wir werden die zuvor definierten Variablen dict_data, color_cycle und hist_func nutzen. Wir werden auch labels auf ['set 0','set 3'] setzen, um nur den ersten und den letzten Datensatz zu plotten.
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(9, 4.5), tight_layout=True, sharey=True)
dict_data = dict(zip((c['label'] for c in label_cycle), stack_data))
arts = stack_hist(ax1, dict_data, color_cycle + hatch_cycle, hist_func=hist_func)
arts = stack_hist(ax2, dict_data, color_cycle + hatch_cycle, hist_func=hist_func, labels=['set 0','set 3'])
ax1.xaxis.set_major_locator(mticker.MaxNLocator(5))
ax1.set_xlabel('counts')
ax1.set_ylabel('x')
ax2.set_ylabel('x')
Zusammenfassung
In diesem Lab haben wir gelernt, wie man mit Matplotlib mit Schraffierungen gefüllte Histogramme erstellt. Wir haben zwei Funktionen definiert: filled_hist, um ein Histogramm als gestuftes Patch zu zeichnen, und stack_hist, um ein gestapeltes Histogramm zu erstellen. Wir haben auch eine Histogrammfunktion mit fester Anzahl von Bins mithilfe von numpy.histogram eingerichtet und drei Stilzyklen für die Histogramme mit cycler definiert. Schließlich haben wir zufällige Daten generiert und zwei mit Schraffierungen gefüllte Histogramme mit der stack_hist-Funktion erstellt.