====== 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()