Afficher la pageAnciennes révisionsLiens de retourHaut de page Cette page est en lecture seule. Vous pouvez afficher le texte source, mais ne pourrez pas le modifier. Contactez votre administrateur si vous pensez qu'il s'agit d'une erreur. ====== 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 ==== <code python> 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() </code> === Ajouter un titre et légender les axes === <code python> 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() </code> === Délimiter les axes === Axe des ordonnées ([[https://stackoverflow.com/questions/22642511/change-y-range-to-start-from-0-with-matplotlib|source]]): <code python> ax.set_ylim(bottom=0) </code> Axe des abscisses: ([[https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.set_xlim.html|source]]): <code python> ax.set_xlim(20000, 26000) </code> On peut récupérer les valeurs que Matplotlib avait prévu d'utiliser ([[https://stackoverflow.com/questions/26131607/matplotlib-get-ylim-values|source]]): <code python> ymin, ymax = axes.get_ylim() </code> === Changer l'aspect de la courbe === <code python> plt.plot(x, y, 'ro-') </code> 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 === <code python> plt.plot(x, y, label='curve') ax.legend() </code> 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: <code python> plt.rcParams['legend.fontsize'] = 8 </code> Aligner le titre de la légende ([[https://stackoverflow.com/a/44620643|source]]): <code python> leg = plt.legend(title="Title") leg._legend_box.align = "left" # ou "right" </code> === Échelles logarithmiques === [[https://matplotlib.org/examples/pylab_examples/log_demo.html|Source]] <code python> 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) </code> === Placement des légendes des axes === [[https://matplotlib.org/gallery/pyplots/text_layout.html#sphx-glr-gallery-pyplots-text-layout-py|Source]] <code python> # 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) </code> === Ajouter une ligne horizontale === <code python> plt.axhline(y=0.5, color='r', linestyle='-') </code> === Graphe avec deux ordonnées === <code python> # 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") </code> Pour que toutes les légendes soient dans une même boîte de légende ([[https://stackoverflow.com/a/5487005|Source]]): <code python> 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) </code> === Afficher une grille === [[https://www.tutorialspoint.com/matplotlib/matplotlib_grids.htm|Source]] <code python> ax.grid() </code> Afficher une grille par défaut, sur tous les futurs graphes ([[https://stackoverflow.com/a/43007677|source]]): <code python> plt.rcParams['axes.grid'] = True </code> 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]]): <code python> ax.set_axisbelow(True) # ou plt.rcParams['axes.axisbelow'] = True </code> 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]]): <code python> ax.grid(axis='y') </code> Pour changer le style de la grille suivant les ticks majeurs ou mineurs : <code python> 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()) </code> === 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]] <code python> from matplotlib.lines import Line2D Line2D.markers list(Line2D.markers) </code> === Automatiquement changer le marqueur utilisé === [[https://matplotlib.org/stable/tutorials/intermediate/color_cycle.html|source]] <code python> 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)])) </code> Voir aussi cette [[https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_prop_cycle.html|doc]]. === Obtenir la figure actuelle === <code python> fig = plt.gcf() # "get current figure" </code> === Obtenir l'axe actuel === [[https://stackoverflow.com/questions/15067668/how-to-get-a-matplotlib-axes-instance-to-plot-to|Source]] <code python> ax = plt.gca() # "get current axis" </code> === Ne pas afficher le graphe === Seulement le sauvegarder dans une image. [[https://stackoverflow.com/questions/15713279/calling-pylab-savefig-without-display-in-ipython]] <code python> # 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) </code> ==== Labels des axes ==== === Changer les valeurs affichées sur les axes === <code python> plt.xticks(x) plt.xticks(x, " ") </code> En échelle logarithmique [[https://stackoverflow.com/questions/21920233/matplotlib-log-scale-tick-label-number-formatting|Source]]: <code python> for axis in [ax.xaxis, ax.yaxis]: formatter = ScalarFormatter() formatter.set_scientific(False) axis.set_major_formatter(formatter) </code> Cacher les valeurs de l'axe des abscisses ([[https://stackoverflow.com/questions/2176424/hiding-axis-text-in-matplotlib-plots|source]]): <code python> ax.xaxis.set_ticklabels([]) # or: plt.xticks([]) # also hide grid lines </code> Changer l'emplacement des graduations et leurs valeurs (depuis une version récente de Matplotlib) : <code python> plt.yticks(ticks, labels) # ou ax.set_yticks(ticks, labels) </code> === 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]] <code python> 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() </code> === Réduire la taille des labels des abscisses === [[https://stackoverflow.com/a/39566040|Source]] <code python> # 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) </code> === Forcer l'utilisation d'entiers === * [[https://matplotlib.org/stable/gallery/ticks/tick-locators.html]] <code python> 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. </code> ==== 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]] <code python> 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() </code> 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]] <code python> 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 </code> == Échelles logarithmiques == En Y: <code python> axs[0].hist(x, bins=n_bins, log=True) </code> En X ([[https://stackoverflow.com/questions/6855710/how-to-have-logarithmic-bins-in-a-python-histogram|source]]): <code python> 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") </code> == 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]] <code python> plt.gca().margins(x=0.01) </code> == 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 : <code python> ax.bar(..., hatch="+") </code> Pour avoir un motif différent sur chaque barre : <code python> 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) </code> === 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: <code python> 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() </code> Placer l'origine en bas à gauche : <code python> ax.imshow(matrix, origin="lower") </code> Changer les couleurs utilisées (voir la liste [[https://matplotlib.org/stable/tutorials/colors/colormaps.html#__do_not_save__|ici]]) : <code python> ax.imshow(matrix, cmap="Grey") </code> Placer l'axe des abscisses en haut du graphe: <code python> ax1.xaxis.tick_top() </code> 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]]) : <code python> plt.setp(ax2.get_xticklabels(), rotation=90, ha="right", va="center", rotation_mode="anchor") </code> Ajouter un titre englobant les deux graphes : <code python> fig.suptitle(title) </code> Il est possible de préciser à quelle hauteur placer le titre ([[https://stackoverflow.com/questions/55767312/how-to-position-suptitle|source]]) : <code python> fig.suptitle(title, y=0.95) </code> Dessiner un rectangle ([[https://stackoverflow.com/questions/67946418/how-to-add-rectangle-patches-in-python-heatmap|source]]) : <code python> import matplotlib.patches as patches ax.add_patch( patches.Rectangle( (5, 6), 1.0, 35.0, edgecolor='red', fill=False, lw=2 ) ) </code> 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]]) : <code python> ax.set_aspect("auto") </code> 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]]) : <code python> 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") </code> === Courbes empilées === [[https://matplotlib.org/stable/gallery/lines_bars_and_markers/stackplot_demo.html]] <code python> plt.stackplot(x, [comm_with_comp_bw, bw_with_comm], labels=["Comm bw", "Comp bw"]) </code> === 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]] <code python> boxplot = ax1.boxplot(all_data, patch_artist=True) for b in boxplot['boxes']: b.set_facecolor(color) </code> == Légende correspondante == [[https://stackoverflow.com/questions/47528955/adding-a-legend-to-a-matplotlib-boxplot-with-multiple-plots-on-same-axes|Source]] <code python> boxplot = ax.boxplot(all_data, patch_artist=True) ax.legend([boxplot["boxes"][0]], ["Label"]) </code> ==== 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) <code python> plt.legend(loc="upper center") </code> 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): <code python> plt.legend(loc="upper center", bbox_to_anchor=(0.5, -0.15)) plt.tight_layout() </code> === Créer une légende personnalisée === {{ :python:matplotlib:custom_legend.png|}} [[https://matplotlib.org/gallery/text_labels_and_annotations/custom_legends.html|Source]] <code python> 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) </code> Pour ajouter une légende qui ne correspond à aucune courbe tracée ([[https://stackoverflow.com/questions/53122592/legend-with-vertical-line-in-matplotlib|source]]): <code python> 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"]) </code> Pour ajouter un élément avec un motif, ajouter cet objet à la liste des handles : <code python> from matplotlib.patches import Patch Patch(hatch="+", label="Label", alpha=1, fill=False) # alpha=0 ne fonctionne pas pour l'export en PDF. </code> === Inverser l'ordre des éléments === [[https://stackoverflow.com/questions/34576059/reverse-the-order-of-legend|Source]] <code python> handles, labels = ax.get_legend_handles_labels() ax.legend(handles[::-1], labels[::-1], title='Line', loc='upper left') </code> ==== 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. <code python> 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") </code> {{ :python:matplotlib:colorbar.png |}} === Avoir une échelle logarithmique === [[https://matplotlib.org/examples/pylab_examples/log_demo.html|Source]] <code python> from matplotlib.colors import LogNorm sm = plt.cm.ScalarMappable(cmap=cm, norm=LogNorm(vmin=x_size[0], vmax=x_size[-1])) </code> === Une couleur par valeur === <code python> from matplotlib.colors import BoundaryNorm sm = plt.cm.ScalarMappable(cmap=cm, norm=BoundaryNorm([1.5 * d for d in data_size], len(data_size))) </code> === Colormap prédéfinies === [[https://matplotlib.org/examples/color/colormaps_reference.html]] <code python> cm = plt.get_cmap("jet", len(data_size)) </code> Pour obtenir directement la couleur: <code python> color = cm(i) # 0 <= i < len(data_size) </code> === Spécifier comment placer la colorbar === * [[https://matplotlib.org/3.1.1/gallery/axes_grid1/demo_colorbar_with_inset_locator.html]] <code python> 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) </code> === Définir le centre de la colorbar === Pour les palettes des couleurs divergentes ([[https://matplotlib.org/stable/tutorials/colors/colormapnorms.html|source]]) : <code python> from matplotlib.colors import TwoSlopeNorm divnorm = TwoSlopeNorm(vmin=0, vcenter=1) im = ax.imshow(matrix, cmap="seismic", norm=divnorm) </code> ==== 3D ==== === Afficher un nuage de points === <code python> 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() </code> === Ajouter un plan === <code python> 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) </code> ==== Sauvegarder le graphique ==== <code python> plt.savefig("name.png") </code> À 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: <code python> fig.set_size_inches(15, 9) plt.savefig("name.png", dpi=100) </code> Pour connaître la taille utilisée par défaut: <code python> plt.rcParams["figure.figsize"] </code> ==== 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: <code python> 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') </code> 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: <code python> ax.errorbar(X, Y, yerr=Y_error) </code> 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é: <code python> (_, _, barline) = ax.errorbar(...) barline[0].set_linestyle('--') </code> === Zone d'erreur === [[https://stackoverflow.com/a/13157955|Source]] <code python> 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') </code> ==== 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|}} <code python> 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() </code> 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]] <code python> 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) </code> === Mosaïque de graphes === <code python> fig, axs = plt.subplots(4, 4, sharex=True, sharey=True, gridspec_kw={'wspace':0.05, 'hspace':0.27}) axs[2,3].plot(...) </code> 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 : <code python> axs[i,j].label_outer() </code> S'il y a un deuxième axe des ordonnées à droite, pour faire la même chose : <code python> if i != 3: ax_right.yaxis.set_tick_params(which="both", labelright=False) </code> Pour enlever toutes les légendes des axes et mettre une unique légende pour tous les graphes : <code python> # 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) </code> Pour n'afficher qu'une légende, sous tous les graphes : <code python> 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)) </code> Pour ne pas afficher certains graphes dans la mosaïque ([[https://stackoverflow.com/questions/38522408/remove-empty-sub-plots-in-matplotlib-figure|source]]) : <code python> fig.delaxes(axs[i, j]) </code> Pour définir le titre de chaque sous-graphe : <code python> axes[j_msg_size,i_comm_size].set_title("Titre", fontdict={"fontsize": 9}) </code> === 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]] <code python> # faire le graphe parent # sous-graphe: ax = plt.axes([.2, .6, .2, .2]) # faire le sous-graphe plt.show() </code> ==== Changer les tailles de tous les textes ==== [[https://stackoverflow.com/questions/3899980/how-to-change-the-font-size-on-a-matplotlib-plot|Source]] <code python> 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 </code> ==== Couleurs ==== === Récupérer la couleur d'une courbe === <code python> r = plt.plot(x, y, 'o-') color = r[0].get_color() </code> === Obtenir la palette de couleurs du thème === Donne la liste des couleurs utilisées par Matplotlib ([[https://stackoverflow.com/a/38539010|Source]]): <code python> colors = plt.rcParams["axes.prop_cycle"].by_key()["color"] </code> === 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]] <code python> ax.axvspan(x_start, x_end, facecolor="0.9", zorder=0.1) </code> 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]] <code python> 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))] </code> ==== 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: <code bash> MPLBACKEND=agg python simple_plot.py </code> === Lister les backends disponibles === [[https://stackoverflow.com/questions/5091993/list-of-all-available-matplotlib-backends|Source]] <code python> import matplotlib print(matplotlib.rcsetup.interactive_bk) print(matplotlib.rcsetup.non_interactive_bk) print(matplotlib.rcsetup.all_backends) </code> === Obtenir le backend actuellement sélectionné === [[https://matplotlib.org/3.4.3/api/matplotlib_configuration_api.html#matplotlib.get_backend|Source]] <code python> print(matplotlib.get_backend() </code> python/matplotlib.txt Dernière modification : 2024/10/06 15:47de phsw