Introduction
Dans ce laboratoire, nous allons apprendre à créer des histogrammes remplis de motifs à l'aide de Matplotlib. Un histogramme est une représentation graphique des données qui utilise des barres pour montrer la fréquence des données numériques. Un histogramme rempli de motifs est un histogramme dans lequel les barres sont remplies d'un motif de lignes, de points ou d'autres symboles.
Conseils sur la machine virtuelle
Une fois le démarrage de la machine virtuelle terminé, cliquez sur le coin supérieur gauche pour basculer vers l'onglet Carnet d'étude pour accéder au carnet Jupyter pour la pratique.
Parfois, vous devrez peut-être attendre quelques secondes pour que le carnet Jupyter ait fini de charger. La validation des opérations ne peut pas être automatisée en raison des limitations du carnet Jupyter.
Si vous rencontrez des problèmes pendant l'apprentissage, n'hésitez pas à demander à Labby. Donnez des commentaires après la session, et nous résoudrons rapidement le problème pour vous.
Importez les bibliothèques nécessaires
Nous allons importer les bibliothèques nécessaires pour ce laboratoire. Nous avons besoin des bibliothèques suivantes :
numpypour générer des données aléatoiresmatplotlib.pyplotpour créer des graphiquesmatplotlib.tickerpour définir les emplacements des graduations d'axecyclerpour créer des cycles de stylefunctools.partialpour créer une fonction partielle
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from cycler import cycler
from functools import partial
Définissez la fonction d'histogramme
Nous allons définir une fonction pour tracer un histogramme sous forme d'un patch en escalier. La fonction prendra les paramètres suivants :
ax: les Axes sur lesquels traceredges: un tableau de longueur n+1 donnant les bords gauche de chaque boîte et le bord droit de la dernière boîtevalues: un tableau de longueur n des comptes ou des valeurs des boîtesbottoms: un nombre ou un tableau, optionnel, un tableau de longueur n du bas des barres. Si None, on utilise zéro.orientation: une chaîne de caractères, optionnelle, l'orientation de l'histogramme. 'v' (par défaut) a les barres croissant dans la direction y positive.
def filled_hist(ax, edges, values, bottoms=None, orientation='v', **kwargs):
"""
Trace un histogramme sous forme d'un patch en escalier.
Paramètres
----------
ax : Axes
Les axes sur lesquels tracer
edges : tableau
Un tableau de longueur n+1 donnant les bords gauche de chaque boîte et le
bord droit de la dernière boîte.
values : tableau
Un tableau de longueur n des comptes ou des valeurs des boîtes
bottoms : nombre ou tableau, optionnel
Un tableau de longueur n du bas des barres. Si None, on utilise zéro.
orientation : {'v', 'h'}
Orientation de l'histogramme. 'v' (par défaut) a
les barres croissant dans la direction y positive.
**kwargs
Les autres arguments clés sont transmis à `.fill_between`.
Retours
-------
ret : PolyCollection
Artiste ajouté aux Axes
"""
if orientation not in 'hv':
raise ValueError(f"orientation doit être dans {{'h', 'v'}} et non {orientation}")
kwargs.setdefault('step', 'post')
kwargs.setdefault('alpha', 0.7)
edges = np.asarray(edges)
values = np.asarray(values)
if len(edges) - 1!= len(values):
raise ValueError(f'Doit fournir un bord de boîte de plus que de valeur et non : {len(edges)=} {len(values)=}')
if bottoms is None:
bottoms = 0
bottoms = np.broadcast_to(bottoms, values.shape)
values = np.append(values, values[-1])
bottoms = np.append(bottoms, bottoms[-1])
if orientation == 'h':
return ax.fill_betweenx(edges, values, bottoms, **kwargs)
elif orientation == 'v':
return ax.fill_between(edges, values, bottoms, **kwargs)
else:
raise AssertionError("vous ne devriez jamais être ici")
Définissez la fonction d'histogramme empilé
Nous allons définir une fonction pour créer un histogramme empilé. La fonction prendra les paramètres suivants :
ax: les axes sur lesquels ajouter des artistesstacked_data: un tableau de forme (M, N). La première dimension sera itérée pour calculer les histogrammes ligne par lignesty_cycle: un Cycler ou un opérable de dict, le style à appliquer à chaque ensemblebottoms: un tableau, valeur par défaut : 0, les positions initiales des fondshist_func: une fonction appelable, optionnelle. Doit avoir la signaturebin_vals, bin_edges = f(data).bin_edgesest supposé être d'une longueur supérieure de 1 àbin_valslabels: une liste de chaînes de caractères, optionnelle, l'étiquette pour chaque ensemble. Si non fourni et que les données empilées sont un tableau, la valeur par défaut est 'ensemble par défaut {n}'. Si stacked_data est un mapping et labels est None, la valeur par défaut est les clés. Si stacked_data est un mapping et labels est donné, alors seulement les colonnes listées seront tracées.plot_func: une fonction appelable, optionnelle, fonction à appeler pour tracer l'histogramme. Doit avoir la signatureret = plot_func(ax, edges, top, bottoms=bottoms, label=label, **kwargs)plot_kwargs: un dictionnaire, optionnel, tous les autres arguments clés à passer à la fonction de tracé. Ceci sera le même pour tous les appels à la fonction de tracé et remplacera les valeurs danssty_cycle.
def stack_hist(ax, stacked_data, sty_cycle, bottoms=None, hist_func=None, labels=None, plot_func=None, plot_kwargs=None):
"""
Paramètres
----------
ax : axes.Axes
Les axes sur lesquels ajouter des artistes
stacked_data : array ou Mapping
Un tableau de forme (M, N). La première dimension sera itérée pour
calculer les histogrammes ligne par ligne
sty_cycle : Cycler ou opérable de dict
Style à appliquer à chaque ensemble
bottoms : array, valeur par défaut: 0
Les positions initiales des fonds.
hist_func : callable, optionnel
Doit avoir la signature `bin_vals, bin_edges = f(data)`.
`bin_edges` est supposé être d'une longueur supérieure de 1 à `bin_vals`
labels : list of str, optionnel
L'étiquette pour chaque ensemble.
Si non fourni et que les données empilées sont un tableau, la valeur par défaut est 'ensemble par défaut {n}'
Si *stacked_data* est un mapping, et *labels* est None, la valeur par défaut est les clés.
Si *stacked_data* est un mapping et *labels* est donné, alors seulement les
colonnes listées seront tracées.
plot_func : callable, optionnel
Fonction à appeler pour tracer l'histogramme doit avoir la signature :
ret = plot_func(ax, edges, top, bottoms=bottoms,
label=label, **kwargs)
plot_kwargs : dict, optionnel
Tous les autres arguments clés à passer à la fonction de tracé.
Ceci sera le même pour tous les appels à la fonction de tracé et remplacera les valeurs dans *sty_cycle*.
Retours
-------
arts : dict
Dictionnaire d'artistes indexé sur leurs étiquettes
"""
## gérer la fonction de découpage par défaut
if hist_func is None:
hist_func = np.histogram
## gérer la fonction de tracé par défaut
if plot_func is None:
plot_func = filled_hist
## gérer la valeur par défaut
if plot_kwargs is None:
plot_kwargs = {}
try:
l_keys = stacked_data.keys()
label_data = True
if labels is None:
labels = l_keys
except AttributeError:
label_data = False
if labels is None:
labels = itertools.repeat(None)
if label_data:
loop_iter = enumerate((stacked_data[lab], lab, s) for lab, s in zip(labels, sty_cycle))
else:
loop_iter = enumerate(zip(stacked_data, labels, sty_cycle))
arts = {}
for j, (data, label, sty) in loop_iter:
if label is None:
label = f'dflt set {j}'
label = sty.pop('label', label)
vals, edges = hist_func(data)
if bottoms is 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
Configurez la fonction d'histogramme avec des bins fixes
Nous allons configurer une fonction d'histogramme avec des bins fixes en utilisant numpy.histogram. Nous allons créer 20 bins allant de -3 à 3.
edges = np.linspace(-3, 3, 20, endpoint=True)
hist_func = partial(np.histogram, bins=edges)
Configurez les cycles de style
Nous allons configurer des cycles de style pour les histogrammes en utilisant cycler. Nous allons créer trois cycles de style : l'un pour la couleur de fond, l'un pour l'étiquette et l'un pour le motif de hachure.
color_cycle = cycler(facecolor=plt.rcParams['axes.prop_cycle'][:4])
label_cycle = cycler(label=[f'ensemble {n}' for n in range(4)])
hatch_cycle = cycler(hatch=['/', '*', '+', '|'])
Générez des données aléatoires
Nous allons générer des données aléatoires en utilisant numpy.random.randn. Nous allons générer 4 ensembles de données avec 12250 points chacun.
np.random.seed(19680801)
stack_data = np.random.randn(4, 12250)
Créez l'histogramme avec des hachures
Nous allons créer un histogramme avec des hachures en utilisant la fonction stack_hist que nous avons définie précédemment. Nous allons utiliser les stack_data, color_cycle et hist_func que nous avons définis précédemment. Nous allons également définir plot_kwargs pour inclure la couleur de bord et l'orientation.
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('comptes')
ax1.set_xlabel('x')
ax2.set_xlabel('comptes')
ax2.set_ylabel('x')
Créez l'histogramme avec des hachures et des étiquettes
Nous allons créer un histogramme avec des hachures et des étiquettes en utilisant la fonction stack_hist que nous avons définie précédemment. Nous allons utiliser les dict_data, color_cycle et hist_func que nous avons définis précédemment. Nous allons également définir labels sur ['ensemble 0', 'ensemble 3'] pour tracer seulement le premier et le dernier ensemble.
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=['ensemble 0', 'ensemble 3'])
ax1.xaxis.set_major_locator(mticker.MaxNLocator(5))
ax1.set_xlabel('comptes')
ax1.set_ylabel('x')
ax2.set_ylabel('x')
Récapitulatif
Dans ce laboratoire, nous avons appris à créer des histogrammes avec des hachures à l'aide de Matplotlib. Nous avons défini deux fonctions : filled_hist pour tracer un histogramme sous forme d'un patch en escalier, et stack_hist pour créer un histogramme empilé. Nous avons également configuré une fonction d'histogramme avec des bins fixes à l'aide de numpy.histogram, et défini trois cycles de style pour les histogrammes à l'aide de cycler. Enfin, nous avons généré des données aléatoires et créé deux histogrammes avec des hachures à l'aide de la fonction stack_hist.