====== Matplotlib ======
* [[https://hal.inria.fr/hal-03427242/document|Scientific Visualization: Python + Matplotlib]]
* [[https://duetosymmetry.com/code/latex-mpl-fig-tips/|Fonts/sizes in matplotlib figures for LaTeX publications]]
* https://datavizcatalogue.com/FR/
==== Un simple graphique ====
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [e**2 for e in x]
plt.plot(x, y) # un plt.plot par courbe à afficher
plt.show()
=== Ajouter un titre et légender les axes ===
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [e**2 for e in x]
fig, ax = plt.subplots()
plt.plot(x, y)
ax.set(xlabel='X', ylabel='X^2', title='y=x^2')
plt.show()
=== Délimiter les axes ===
Axe des ordonnées ([[https://stackoverflow.com/questions/22642511/change-y-range-to-start-from-0-with-matplotlib|source]]):
ax.set_ylim(bottom=0)
Axe des abscisses: ([[https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.set_xlim.html|source]]):
ax.set_xlim(20000, 26000)
On peut récupérer les valeurs que Matplotlib avait prévu d'utiliser ([[https://stackoverflow.com/questions/26131607/matplotlib-get-ylim-values|source]]):
ymin, ymax = axes.get_ylim()
=== Changer l'aspect de la courbe ===
plt.plot(x, y, 'ro-')
Le troisième paramètre permet de rapidement spécifier l'aspect de la courbe:
* ''r'': la courbe sera en rouge
* ''o'': les points seront représentés par des points (rien par défaut) ([[https://matplotlib.org/3.1.0/api/markers_api.html|liste des symboles disponibles]])
* ''-'': la ligne est continue
Aucun de ces paramètres n'est obligatoire. Voir la [[https://matplotlib.org/2.1.1/api/_as_gen/matplotlib.pyplot.plot.html|documentation]] pour toutes les possibilités.
Paramètres optionnels:
* ''color'': la valeur peut être la lettre d'une couleur, le code hexadécimal, ou un tuple RGB (ou RGBA) avec des valeurs entre 0 et 1
* ''linewidth'': épaisseur de la ligne (1 est une petite valeur)
* ''markersize'': taille des points (4 est une petite valeur, la valeur par défaut est 6, elle est dans ''plt.rcParams['lines.markersize']'')
* ''alpha'': transparence des points (flottant entre 0 et 1)
* ''ls'' ou ''linestyle'': style de la ligne (voir la [[https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D.set_linestyle|doc]] pour les possibilités)
=== Légende ===
plt.plot(x, y, label='curve')
ax.legend()
Paramètres facultatifs de ''[[https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html|ax.legend()]]'' :
* ''handletextpad'' : espacement entre le symbole et le texte
* ''borderpad'' : padding de la boîte de légende
* ''borderaxespad'' : décalage par rapport aux bordures du graphique
* ''handlelength'' : longueur du symbole
* ''labelspacing'' : espace entre deux éléments de la légende (par défaut 0,5)
* ''ncol'' : sur combien de colonnes répartir les éléments de la légende
* ''prop={'size': 6}'' ou ''fontsize'' : change la taille du texte de la légende (accepte un entier ou les valeurs ''xx-small'', ''x-small'', ''small'', ''medium'', ''large'', ''x-large'', ''xx-large''
* ''title="Un titre"'' : donne un titre à la légende ([[https://matplotlib.org/stable/gallery/text_labels_and_annotations/legend_demo.html#sphx-glr-gallery-text-labels-and-annotations-legend-demo-py|source]])
La taille de la police de la légende peut être définie par défaut:
plt.rcParams['legend.fontsize'] = 8
Aligner le titre de la légende ([[https://stackoverflow.com/a/44620643|source]]):
leg = plt.legend(title="Title")
leg._legend_box.align = "left" # ou "right"
=== Échelles logarithmiques ===
[[https://matplotlib.org/examples/pylab_examples/log_demo.html|Source]]
plt.semilogy(t, np.exp(-t/5.0))
plt.semilogx(t, np.sin(2*np.pi*t))
plt.loglog(t, 20*np.exp(-t/10.0), basex=2)
# ou
plt.plot(...)
ax.set_xscale("log", basex=2)
ax.set_yscale("log", basey=10)
=== Placement des légendes des axes ===
[[https://matplotlib.org/gallery/pyplots/text_layout.html#sphx-glr-gallery-pyplots-text-layout-py|Source]]
# Axe des abscisses: placement en bas à gauche de l'axe:
ax.text(0, -0.025, 'Taille de la matrice', horizontalalignment='left', verticalalignment='top', transform=ax.transAxes)
# Axe des ordonnées: placement en haut à gauche de l'axe:
ax.text(-0.01, 1, 'Gflops', horizontalalignment='right', verticalalignment='top', transform=ax.transAxes)
=== Ajouter une ligne horizontale ===
plt.axhline(y=0.5, color='r', linestyle='-')
=== Graphe avec deux ordonnées ===
# courbes de l'axes gauche: comme d'habitude
plt.subplots_adjust(right=0.85) # pour éviter que la légende de l'axe à droite se retrouve coupée avec la taille par défaut
ax2 = ax.twinx()
ax2.set_ylabel("CPU frequency (MHz)")
plt.plot(cpu_freqs_x, cpu_freqs, color='r', label="AVG of CPU frequencies")
Pour que toutes les légendes soient dans une même boîte de légende ([[https://stackoverflow.com/a/5487005|Source]]):
lns1 = ax.plot(time, Swdown, '-', label = 'Swdown')
lns2 = ax.plot(time, Rn, '-', label = 'Rn')
ax2 = ax.twinx()
lns3 = ax2.plot(time, temp, '-r', label = 'temp')
lns = lns1+lns2+lns3
labs = [l.get_label() for l in lns]
ax.legend(lns, labs, loc=0)
=== Afficher une grille ===
[[https://www.tutorialspoint.com/matplotlib/matplotlib_grids.htm|Source]]
ax.grid()
Afficher une grille par défaut, sur tous les futurs graphes ([[https://stackoverflow.com/a/43007677|source]]):
plt.rcParams['axes.grid'] = True
La grille se placera par défaut au premier plan, pour éviter ça ([[https://stackoverflow.com/questions/1726391/matplotlib-draw-grid-lines-behind-other-graph-elements|source]]):
ax.set_axisbelow(True)
# ou
plt.rcParams['axes.axisbelow'] = True
Pour n'afficher qu'un seul axe de la grille ([[https://stackoverflow.com/questions/54714018/horizontal-grid-only-in-python-using-pandas-plot-pyplot|source]]):
ax.grid(axis='y')
Pour changer le style de la grille suivant les ticks majeurs ou mineurs :
from matplotlib.ticker import AutoMinorLocator
ax.grid(axis="y", which="major", linestyle="-")
ax.grid(axis="y", which="minor", linestyle="-", alpha=0.2)
ax.yaxis.set_minor_locator(AutoMinorLocator())
=== Obtenir la liste des symboles possibles ===
[[https://stackoverflow.com/questions/59647765/how-to-obtain-a-list-of-all-markers-in-matplotlib|source]]
La documentation est [[https://matplotlib.org/stable/api/markers_api.html|ici]]
from matplotlib.lines import Line2D
Line2D.markers
list(Line2D.markers)
=== Automatiquement changer le marqueur utilisé ===
[[https://matplotlib.org/stable/tutorials/intermediate/color_cycle.html|source]]
from matplotlib.lines import Line2D
from cycler import cycler
ax.set_prop_cycle(cycler(color=plt.rcParams["axes.prop_cycle"].by_key()["color"]) + cycler(marker=list(Line2D.markers)[:len(colors)]))
Voir aussi cette [[https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_prop_cycle.html|doc]].
=== Obtenir la figure actuelle ===
fig = plt.gcf() # "get current figure"
=== Obtenir l'axe actuel ===
[[https://stackoverflow.com/questions/15067668/how-to-get-a-matplotlib-axes-instance-to-plot-to|Source]]
ax = plt.gca() # "get current axis"
=== Ne pas afficher le graphe ===
Seulement le sauvegarder dans une image.
[[https://stackoverflow.com/questions/15713279/calling-pylab-savefig-without-display-in-ipython]]
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
==== Labels des axes ====
=== Changer les valeurs affichées sur les axes ===
plt.xticks(x)
plt.xticks(x, " ")
En échelle logarithmique [[https://stackoverflow.com/questions/21920233/matplotlib-log-scale-tick-label-number-formatting|Source]]:
for axis in [ax.xaxis, ax.yaxis]:
formatter = ScalarFormatter()
formatter.set_scientific(False)
axis.set_major_formatter(formatter)
Cacher les valeurs de l'axe des abscisses ([[https://stackoverflow.com/questions/2176424/hiding-axis-text-in-matplotlib-plots|source]]):
ax.xaxis.set_ticklabels([])
# or:
plt.xticks([]) # also hide grid lines
Changer l'emplacement des graduations et leurs valeurs (depuis une version récente de Matplotlib) :
plt.yticks(ticks, labels)
# ou
ax.set_yticks(ticks, labels)
=== Pivoter les labels des abscisses ===
* [[https://matplotlib.org/gallery/ticks_and_spines/ticklabels_rotation.html]]
* [[https://stackoverflow.com/questions/10998621/rotate-axis-text-in-python-matplotlib]]
plt.plot(x, y)
# You can specify a rotation for the tick labels in degrees or with keywords.
plt.xticks(x, labels, rotation='vertical')
plt.xticks(x, labels, rotation=90)
# or just:
plt.xticks(rotation="vertical")
# or:
for tick in ax.get_xticklabels():
tick.set_rotation(45)
# or (with Matplotlib >= 3.5):
ax.set_xticks(ax.get_xticks(), ax.get_xticklabels(), rotation=45, ha='right')
# Pad margins so that markers don't get clipped by the axes
plt.margins(0.2)
# Tweak spacing to prevent clipping of tick-labels
plt.subplots_adjust(bottom=0.15)
plt.show()
=== Réduire la taille des labels des abscisses ===
[[https://stackoverflow.com/a/39566040|Source]]
# De façon générale :
plt.rc('xtick', labelsize=8) # 8 est petit
# Uniquement pour un axe :
for label in ax.get_xticklabels():
label.set_fontsize(8)
=== Forcer l'utilisation d'entiers ===
* [[https://matplotlib.org/stable/gallery/ticks/tick-locators.html]]
from matplotlib.ticker import MaxNLocator
ax.xaxis.set_major_locator(MaxNLocator(integer=True))
# ou bien :
ax.set_major_locator(MaxNLocator(nbins="auto", steps=[1, 2, 2.5, 5, 10], integer=True)) # AutoLocator utilise les deux premières options.
==== Types de graphiques ====
=== Histogramme ===
== Avec deux séries ==
* [[https://matplotlib.org/gallery/lines_bars_and_markers/barchart.html#sphx-glr-gallery-lines-bars-and-markers-barchart-py]]
* [[https://matplotlib.org/3.1.1/gallery/lines_bars_and_markers/bar_stacked.html]]
* [[https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.bar.html]]
width = 0.35
fig, ax = plt.subplots()
ax.bar([i - (width / 2) for i in range(nb_x)], y1, width, label='Y1', log=False)
ax.bar([i + (width / 2) for i in range(nb_x)], y2, width, label='Y2', log=False)
plt.xlabel("X label")
plt.ylabel("Y label")
plt.title("Titre")
plt.xticks(range(nb_x))
# ou
plt.xticks(range(nb_x), list_labels, rotation="vertical")
plt.legend()
plt.show()
Il est possible d'ajouter des barres d'erreur avec les paramètres optionnels ''xerr'' et ''yerr'', les valeurs peuvent varier selon les dimensions du tableau passé en argument (voir la [[https://matplotlib.org/api/_as_gen/matplotlib.axes.Axes.bar.html|doc]])
== de distribution ==
* [[https://matplotlib.org/gallery/statistics/hist.html#sphx-glr-gallery-statistics-hist-py]]
* [[https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.hist.html]]
* [[https://matplotlib.org/stable/gallery/statistics/histogram_multihist.html]]
N_points = 100000
n_bins = 20
# Generate a normal distribution, center at x=0 and y=5
x = np.random.randn(N_points)
y = .4 * x + np.random.randn(100000) + 5
fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True)
# We can set the number of bins with the `bins` kwarg
axs[0].hist(x, bins=n_bins)
axs[1].hist(y, bins=n_bins, rwidth=0.8) # rwidth permet de laisser de l'espace entre les barres
== Échelles logarithmiques ==
En Y:
axs[0].hist(x, bins=n_bins, log=True)
En X ([[https://stackoverflow.com/questions/6855710/how-to-have-logarithmic-bins-in-a-python-histogram|source]]):
import numpy as np
axs[0].hist(durations, bins=np.logspace(np.log10(1), np.log10(max(durations)), 50), rwidth=0.8)
axs[0].set_xscale("log")
== Réduire l'espace entre les barres et la bordure du graphique ==
[[https://stackoverflow.com/questions/63719618/how-to-reduce-the-space-between-the-axes-and-the-first-and-last-bar-in-pyplot|Source]]
plt.gca().margins(x=0.01)
== Changer le motif des barres ==
* [[https://matplotlib.org/stable/gallery/shapes_and_collections/hatch_style_reference.html]]
Pour avoir le même motif sur toutes les barres :
ax.bar(..., hatch="+")
Pour avoir un motif différent sur chaque barre :
bars = ax.bar(...)
for i in range(len(bars)):
bars[i].set_hatch(hatches[i])
# pour avoir un export correct dans les PDFs, utiliser plutôt :
bars[i].set(hatch="//", alpha=1)
=== Heatmap ===
* [[https://matplotlib.org/gallery/images_contours_and_fields/multi_image.html]]
* [[https://matplotlib.org/gallery/images_contours_and_fields/image_annotated_heatmap.html]]
* [[https://matplotlib.org/gallery/subplots_axes_and_figures/subplots_adjust.html]]
* [[https://stackoverflow.com/questions/55663030/plotting-two-heat-maps-side-by-side-in-matplotlib]]
* [[https://stackoverflow.com/questions/13784201/matplotlib-2-subplots-1-colorbar]]
Deux heatmaps normalisés avec une unique barre de légende:
CMAP = "binary"
vmin = min([min(l) for l in data_coop + data_seq])
vmax = max([max(l) for l in data_coop + data_seq])
norm = colors.Normalize(vmin=vmin, vmax=vmax)
fig, axes = plt.subplots(ncols=2)
ax1, ax2 = axes
im1 = ax1.imshow(data_seq[::-1], cmap=CMAP)
im1.set_norm(norm)
ax1.set_xticks([i for i in range(0, nb_nodes_seq, 5)])
ax1.set_xticklabels(["dst " + str(i) for i in range(0, nb_nodes_seq, 5)])
ax1.set_yticks([i for i in range(0, nb_nodes_seq, 5)])
ax1.set_yticklabels(["src " + str(i) for i in range(nb_nodes_seq-1, -1, -5)])
ax1.set_title("Seq")
im2 = ax2.imshow(data_coop[::-1], cmap=CMAP)
im2.set_norm(norm)
ax2.set_xticks([i for i in range(0, nb_nodes_coop, 5)])
ax2.set_xticklabels(["dst " + str(i) for i in range(0, nb_nodes_coop, 5)])
ax2.set_yticks([i for i in range(0, nb_nodes_coop, 5)])
ax2.set_yticklabels(["src " + str(i) for i in range(nb_nodes_coop-1, -1, -5)])
ax2.set_title("Coop")
c_bar = fig.colorbar(im1, ax=axes.ravel().tolist())
c_bar.set_label(cbar_legend)
plt.show()
Placer l'origine en bas à gauche :
ax.imshow(matrix, origin="lower")
Changer les couleurs utilisées (voir la liste [[https://matplotlib.org/stable/tutorials/colors/colormaps.html#__do_not_save__|ici]]) :
ax.imshow(matrix, cmap="Grey")
Placer l'axe des abscisses en haut du graphe:
ax1.xaxis.tick_top()
Les fonctions avec juste ''ticks'' indiquent où placer des labels, les fonctions ''ticklabels'' donnent les labels à affichent.
Pivoter les labels de l'axe des abscisses (voir la [[https://matplotlib.org/3.1.1/gallery/text_labels_and_annotations/demo_text_rotation_mode.html|ref]]) :
plt.setp(ax2.get_xticklabels(), rotation=90, ha="right", va="center", rotation_mode="anchor")
Ajouter un titre englobant les deux graphes :
fig.suptitle(title)
Il est possible de préciser à quelle hauteur placer le titre ([[https://stackoverflow.com/questions/55767312/how-to-position-suptitle|source]]) :
fig.suptitle(title, y=0.95)
Dessiner un rectangle ([[https://stackoverflow.com/questions/67946418/how-to-add-rectangle-patches-in-python-heatmap|source]]) :
import matplotlib.patches as patches
ax.add_patch(
patches.Rectangle(
(5, 6),
1.0,
35.0,
edgecolor='red',
fill=False,
lw=2
) )
Pour ne pas forcer que les cases soient carrées ([[https://stackoverflow.com/questions/32256586/how-to-control-the-cell-size-of-a-pyplot-pcolor-heatmap|source]]) :
ax.set_aspect("auto")
Pour agrandir la heatmap, il peut être aussi utile de ne pas utiliser ''tight_layout''.
Ajouter du texte dans chaque case de la heatmap ([[https://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html|source]]) :
for i in range(len(vegetables)):
for j in range(len(farmers)):
text = ax.text(j, i, harvest[i, j], ha="center", va="center", color="w")
=== Courbes empilées ===
[[https://matplotlib.org/stable/gallery/lines_bars_and_markers/stackplot_demo.html]]
plt.stackplot(x, [comm_with_comp_bw, bw_with_comm], labels=["Comm bw", "Comp bw"])
=== Boxplots ===
Pour que Matplotlib calcule directement les statistiques : ''ax.boxplot()'' ([[https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html#__do_not_save__|documentation]])
Pour fournir nous-mêmes les statistiques à Matplotlib : ''ax.bxp()'' ([[https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.bxp.html#__do_not_save__|documentation]])
== Changer la couleur de fond ==
[[https://matplotlib.org/stable/gallery/statistics/boxplot_color.html#sphx-glr-gallery-statistics-boxplot-color-py|Source]]
boxplot = ax1.boxplot(all_data, patch_artist=True)
for b in boxplot['boxes']:
b.set_facecolor(color)
== Légende correspondante ==
[[https://stackoverflow.com/questions/47528955/adding-a-legend-to-a-matplotlib-boxplot-with-multiple-plots-on-same-axes|Source]]
boxplot = ax.boxplot(all_data, patch_artist=True)
ax.legend([boxplot["boxes"][0]], ["Label"])
==== Légendes ====
=== Indiquer la position de la légende ===
[[https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html|Source]] (contient la liste des positions possibles)
plt.legend(loc="upper center")
Placer la légende sous le graphe ([[https://stackoverflow.com/a/4701285|source]], qui contient aussi d'autres infos pour le placement général des légendes):
plt.legend(loc="upper center", bbox_to_anchor=(0.5, -0.15))
plt.tight_layout()
=== Créer une légende personnalisée ===
{{ :python:matplotlib:custom_legend.png|}}
[[https://matplotlib.org/gallery/text_labels_and_annotations/custom_legends.html|Source]]
from matplotlib.lines import Line2D
legend_elements = [
Line2D([0], [0], marker='o', label='A'),
Line2D([0], [0], marker='+', label='B')
# linewidth et linestyle sont aussi dispo
]
# handlelength: taille du trait sous le point
ax.legend(handles=legend_elements, handletextpad=1, borderpad=1, borderaxespad=1, handlelength=0)
Pour ajouter une légende qui ne correspond à aucune courbe tracée ([[https://stackoverflow.com/questions/53122592/legend-with-vertical-line-in-matplotlib|source]]):
cholesky_dots = ax.plot(cholesky['Id'], cholesky['gflops'], 'o')
vertical_line = lines.Line2D([], [], color='r', marker='|', linestyle='None', markersize=10, markeredgewidth=1.5)
plt.legend([vertical_line]+cholesky_dots, ["Trace flush", "POTRF"])
Pour ajouter un élément avec un motif, ajouter cet objet à la liste des handles :
from matplotlib.patches import Patch
Patch(hatch="+", label="Label", alpha=1, fill=False) # alpha=0 ne fonctionne pas pour l'export en PDF.
=== Inverser l'ordre des éléments ===
[[https://stackoverflow.com/questions/34576059/reverse-the-order-of-legend|Source]]
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles[::-1], labels[::-1], title='Line', loc='upper left')
==== Ajouter une colorbar ====
[[https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots/11558629#11558629|Source]]
[[https://stackoverflow.com/questions/8342549/matplotlib-add-colorbar-to-a-sequence-of-line-plots|Ceci]] est aussi intéressant si on souhaite que toutes les courbes aient une couleur différente suivant une échelle qui sera la colorbar.
from matplotlib.colors import LinearSegmentedColormap
cm = LinearSegmentedColormap.from_list("mylist", [(0, 1, 0), (1, 0, 0)], N=len(y)) # from green to red
sm = plt.cm.ScalarMappable(cmap=cm, norm=plt.Normalize(vmin=y[0], vmax=y[-1]))
sm._A = []
cbar = fig.colorbar(sm, ticks=y)
cbar.set_label("Color of y")
{{ :python:matplotlib:colorbar.png |}}
=== Avoir une échelle logarithmique ===
[[https://matplotlib.org/examples/pylab_examples/log_demo.html|Source]]
from matplotlib.colors import LogNorm
sm = plt.cm.ScalarMappable(cmap=cm, norm=LogNorm(vmin=x_size[0], vmax=x_size[-1]))
=== Une couleur par valeur ===
from matplotlib.colors import BoundaryNorm
sm = plt.cm.ScalarMappable(cmap=cm, norm=BoundaryNorm([1.5 * d for d in data_size], len(data_size)))
=== Colormap prédéfinies ===
[[https://matplotlib.org/examples/color/colormaps_reference.html]]
cm = plt.get_cmap("jet", len(data_size))
Pour obtenir directement la couleur:
color = cm(i) # 0 <= i < len(data_size)
=== Spécifier comment placer la colorbar ===
* [[https://matplotlib.org/3.1.1/gallery/axes_grid1/demo_colorbar_with_inset_locator.html]]
axins = inset_axes(ax2,
width="5%", # width = 5% of parent_bbox width
height="100%", # height : 50%
loc='lower left',
bbox_to_anchor=(1.05, 0., 1, 1),
bbox_transform=ax2.transAxes,
borderpad=0,
)
c_bar = fig.colorbar(im2, cax=axins)
c_bar.set_label(cbar_legend)
=== Définir le centre de la colorbar ===
Pour les palettes des couleurs divergentes ([[https://matplotlib.org/stable/tutorials/colors/colormapnorms.html|source]]) :
from matplotlib.colors import TwoSlopeNorm
divnorm = TwoSlopeNorm(vmin=0, vcenter=1)
im = ax.imshow(matrix, cmap="seismic", norm=divnorm)
==== 3D ====
=== Afficher un nuage de points ===
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
ax.scatter(x_msg_size, y_comm_size, z_ratio, color=color)
ax.set(xlabel="Msg size", ylabel="Comm size", zlabel="Ratio")
plt.show()
=== Ajouter un plan ===
import numpy as np
x_surface, y_surface = np.meshgrid(np.arange(min(x_msg_size), max(x_msg_size)), np.arange(min(y_comm_size), max(y_comm_size)))
ax.plot_surface(x_surface, y_surface, np.full_like(x_surface, 1), alpha=0.2)
==== Sauvegarder le graphique ====
plt.savefig("name.png")
À placer avant ''plt.show()''.
Pour ne pas avoir de larges bordures blanches, ajouter le paramètre ''bbox_inches="tight"''.
=== Préciser la taille ===
[[https://stackoverflow.com/questions/332289/how-do-you-change-the-size-of-figures-drawn-with-matplotlib|Source]]
Pour agrandir, notamment:
fig.set_size_inches(15, 9)
plt.savefig("name.png", dpi=100)
Pour connaître la taille utilisée par défaut:
plt.rcParams["figure.figsize"]
==== Barres d'erreur ====
[[https://web.archive.org/web/20190917055332/http://codewithmax.com/2018/03/17/plotting-error-bars-in-python-using-matplotlib-and-numpy-random/#__do_not_save__|Source]]
Quand les barres d'erreur sont différentes pour chaque point:
for i in range(len(errors)):
ax.errorbar(x[i], y[i], yerr=[[y[i] - errors[i][0], [errors[i][-1] - y[i]]],
elinewidth=0.8, capsize=5, ecolor='k')
Les valeurs données pour les barres d'erreurs sont les distances au point décrit par les premiers paramètres de la fonction.
Paramètres:
* ''capsize'': longueur des tirets aux extrémités des barres d'erreur
* ''ecolor'': couleur de la barre d'erreur
* ''elinewidth'': épaisseur de la barre d'erreur
* ''fmt'': marqueur du point décrit par les premiers paramètres de la fonction, en l'absence, le point n'est pas affiché
Pour une barre d'erreur constante:
ax.errorbar(X, Y, yerr=Y_error)
Ici ''X'' et ''Y'' sont les listes qui contiennent les coordonnées des points et ''Y_error'' est une constante indiquant l'erreur relative.
=== Changer le style d'une barre d'erreur ===
Pour que le trait de barre d'erreur soit pointillé:
(_, _, barline) = ax.errorbar(...)
barline[0].set_linestyle('--')
=== Zone d'erreur ===
[[https://stackoverflow.com/a/13157955|Source]]
y_error_coop_inf = [y_flops_coop[i] - (y_error_coop[i]/2) for i in range(len(results_coop))]
y_error_coop_sup = [y_flops_coop[i] + (y_error_coop[i]/2) for i in range(len(results_seq))]
plt.plot(x_matrix_size, y_flops_coop, 'o-', color='r', label='Coop ')
plt.fill_between(x_matrix_size, y_error_coop_inf, y_error_coop_sup, alpha=0.3, color='r')
==== Sous-graphes ====
* [[https://matplotlib.org/gallery/subplots_axes_and_figures/gridspec_multicolumn.html]]
* [[https://matplotlib.org/3.1.1/tutorials/intermediate/gridspec.html]]
* [[https://aaronmcdaid.com/blog.posts/multiplot_from_generator/]]
* [[https://stackoverflow.com/questions/21754976/ipython-notebook-arrange-plots-horizontally]]
=== Alignés sur un axe ===
* [[https://matplotlib.org/3.1.1/gallery/subplots_axes_and_figures/subplot.html]]
* [[https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.subplot.html#matplotlib.pyplot.subplot]]
{{ https://matplotlib.org/3.1.1/_images/sphx_glr_subplot_001.png?0x400|}}
import numpy as np
import matplotlib.pyplot as plt
x1 = np.linspace(0.0, 5.0)
x2 = np.linspace(0.0, 2.0)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)
plt.subplot(2, 1, 1)
plt.plot(x1, y1, 'o-')
plt.title('A tale of 2 subplots')
plt.ylabel('Damped oscillation')
plt.subplot(2, 1, 2)
plt.plot(x2, y2, '.-')
plt.xlabel('time (s)')
plt.ylabel('Undamped')
plt.show()
Le triplet de paramètres pour ''subplot'', correspond, dans l'ordre:
- nombre de lignes
- nombre de colonnes
- index du graphe actuel dans cette matrice
=== Partager les axes ===
* [[https://matplotlib.org/3.1.0/gallery/subplots_axes_and_figures/shared_axis_demo.html]]
ax1 = plt.subplot(311)
plt.plot(t, s1)
plt.setp(ax1.get_xticklabels(), fontsize=6)
# share x only
ax2 = plt.subplot(312, sharex=ax1)
plt.plot(t, s2)
# make these tick labels invisible
plt.setp(ax2.get_xticklabels(), visible=False)
=== Mosaïque de graphes ===
fig, axs = plt.subplots(4, 4, sharex=True, sharey=True, gridspec_kw={'wspace':0.05, 'hspace':0.27})
axs[2,3].plot(...)
Les paramètres dans ''gridpsec_kw'' permettent de préciser l'espacement entre les graphes.
On peut définir la largeur relative de chaque graphe : ''gridspec_kw={"width_ratios": width_ratios}'' (''width_ratios'' est une liste de taille le nombre de graphes horizontalement et le graphe ''i'' aura la largeur ''width_ratios[i]/sum(width_ratios)'').
Pour ne garder les valeurs sur les axes des ordonnées que sur les graphiques de la première colonne :
axs[i,j].label_outer()
S'il y a un deuxième axe des ordonnées à droite, pour faire la même chose :
if i != 3:
ax_right.yaxis.set_tick_params(which="both", labelright=False)
Pour enlever toutes les légendes des axes et mettre une unique légende pour tous les graphes :
# pour tous les i, j :
axs[i,j].set_xlabel(None)
axs[i,j].set_ylabel(None)
fig.text(0.5, 0.07, "Axe des X", va='center', ha='center', fontsize=17)
fig.text(0.09, 0.5, "Axe des Y", va='center', ha='center', rotation='vertical', fontsize=17)
Pour n'afficher qu'une légende, sous tous les graphes :
handles_left, labels_left = axs[0,0].get_legend_handles_labels()
fig.legend(handles_left, labels_left, loc='lower left', bbox_to_anchor=(0.11, -0.05))
Pour ne pas afficher certains graphes dans la mosaïque ([[https://stackoverflow.com/questions/38522408/remove-empty-sub-plots-in-matplotlib-figure|source]]) :
fig.delaxes(axs[i, j])
Pour définir le titre de chaque sous-graphe :
axes[j_msg_size,i_comm_size].set_title("Titre", fontdict={"fontsize": 9})
=== Un graphe dans un autre ===
[[https://matplotlib.org/3.1.0/gallery/subplots_axes_and_figures/axes_demo.html#sphx-glr-gallery-subplots-axes-and-figures-axes-demo-py|Source]]
# faire le graphe parent
# sous-graphe:
ax = plt.axes([.2, .6, .2, .2])
# faire le sous-graphe
plt.show()
==== Changer les tailles de tous les textes ====
[[https://stackoverflow.com/questions/3899980/how-to-change-the-font-size-on-a-matplotlib-plot|Source]]
SMALL_SIZE = 11
MEDIUM_SIZE = 12
plt.rc('font', size=SMALL_SIZE) # controls default text sizes
plt.rc('axes', titlesize=SMALL_SIZE) # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels
plt.rc('xtick', labelsize=SMALL_SIZE) # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE) # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE) # legend fontsize
plt.rc('figure', titlesize=MEDIUM_SIZE) # fontsize of the figure title
==== Couleurs ====
=== Récupérer la couleur d'une courbe ===
r = plt.plot(x, y, 'o-')
color = r[0].get_color()
=== Obtenir la palette de couleurs du thème ===
Donne la liste des couleurs utilisées par Matplotlib ([[https://stackoverflow.com/a/38539010|Source]]):
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
=== Couleur de fond sur des zones en arrière-plan ===
[[https://stackoverflow.com/questions/9957637/how-can-i-set-the-background-color-on-specific-areas-of-a-pyplot-figure/9957832|Source]]
ax.axvspan(x_start, x_end, facecolor="0.9", zorder=0.1)
Le ''zorder'' permet de mettre la zone à l'arrière-plan du graphe. La même fonction en horizontal: ''axhspan''.
=== Générer de nombreuses couleurs ===
Pour que la couleur suivante soit bien distincte de la précédente.
* [[https://gamedev.stackexchange.com/questions/46463/how-can-i-find-an-optimum-set-of-colors-for-10-players/46469#46469]]
* [[https://stackoverflow.com/questions/4971269/how-to-pick-a-new-color-for-each-plotted-line-within-a-figure-in-matplotlib]]
* [[https://stackoverflow.com/questions/8389636/creating-over-20-unique-legend-colors-using-matplotlib]]
from matplotlib import colors
data_colors = [colors.hsv_to_rgb([(i * 0.618033988749895) % 1.0, 0.7, 1]) for i in range(len(stacked_data))]
==== Backends ====
* [[https://matplotlib.org/3.4.3/tutorials/introductory/usage.html?highlight=backend#what-is-a-backend]]
Définir le backend, pour éviter que Matplotlib n'essaie de lancer quelquechose d'interactif et plante car il n'arrive pas à se connecter au serveur X:
MPLBACKEND=agg python simple_plot.py
=== Lister les backends disponibles ===
[[https://stackoverflow.com/questions/5091993/list-of-all-available-matplotlib-backends|Source]]
import matplotlib
print(matplotlib.rcsetup.interactive_bk)
print(matplotlib.rcsetup.non_interactive_bk)
print(matplotlib.rcsetup.all_backends)
=== Obtenir le backend actuellement sélectionné ===
[[https://matplotlib.org/3.4.3/api/matplotlib_configuration_api.html#matplotlib.get_backend|Source]]
print(matplotlib.get_backend()