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()
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()
Axe des ordonnées (source):
ax.set_ylim(bottom=0)
Axe des abscisses: (source):
ax.set_xlim(20000, 26000)
On peut récupérer les valeurs que Matplotlib avait prévu d'utiliser (source):
ymin, ymax = axes.get_ylim()
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 rougeo: les points seront représentés par des points (rien par défaut) (liste des symboles disponibles)-: la ligne est continueAucun de ces paramètres n'est obligatoire. Voir la 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 1linewidth: é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)plt.plot(x, y, label='curve') ax.legend()
Paramètres facultatifs de ax.legend() :
handletextpad : espacement entre le symbole et le texteborderpad : padding de la boîte de légendeborderaxespad : décalage par rapport aux bordures du graphiquehandlelength : longueur du symbolelabelspacing : 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égendeprop={'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-largetitle=“Un titre” : donne un titre à la légende (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 (source):
leg = plt.legend(title="Title") leg._legend_box.align = "left" # ou "right"
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)
# 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)
plt.axhline(y=0.5, color='r', linestyle='-')
# 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 (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)
ax.grid()
Afficher une grille par défaut, sur tous les futurs graphes (source):
plt.rcParams['axes.grid'] = True
La grille se placera par défaut au premier plan, pour éviter ça (source):
ax.set_axisbelow(True) # ou plt.rcParams['axes.axisbelow'] = True
Pour n'afficher qu'un seul axe de la grille (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())
La documentation est ici
from matplotlib.lines import Line2D Line2D.markers list(Line2D.markers)
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 doc.
fig = plt.gcf() # "get current figure"
ax = plt.gca() # "get current axis"
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)
plt.xticks(x) plt.xticks(x, " ")
En échelle logarithmique 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 (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)
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()
# 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)
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.
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 doc)
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
En Y:
axs[0].hist(x, bins=n_bins, log=True)
En X (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")
plt.gca().margins(x=0.01)
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)
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 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 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 (source) :
fig.suptitle(title, y=0.95)
Dessiner un rectangle (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 (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 (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")
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"])
Pour que Matplotlib calcule directement les statistiques : ax.boxplot() (documentation)
Pour fournir nous-mêmes les statistiques à Matplotlib : ax.bxp() (documentation)
boxplot = ax1.boxplot(all_data, patch_artist=True) for b in boxplot['boxes']: b.set_facecolor(color)
boxplot = ax.boxplot(all_data, patch_artist=True) ax.legend([boxplot["boxes"][0]], ["Label"])
Source (contient la liste des positions possibles)
plt.legend(loc="upper center")
Placer la légende sous le graphe (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()
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 (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.
handles, labels = ax.get_legend_handles_labels() ax.legend(handles[::-1], labels[::-1], title='Line', loc='upper left')
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")
from matplotlib.colors import LogNorm sm = plt.cm.ScalarMappable(cmap=cm, norm=LogNorm(vmin=x_size[0], vmax=x_size[-1]))
from matplotlib.colors import BoundaryNorm sm = plt.cm.ScalarMappable(cmap=cm, norm=BoundaryNorm([1.5 * d for d in data_size], len(data_size)))
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)
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)
Pour les palettes des couleurs divergentes (source) :
from matplotlib.colors import TwoSlopeNorm divnorm = TwoSlopeNorm(vmin=0, vcenter=1) im = ax.imshow(matrix, cmap="seismic", norm=divnorm)
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()
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)
plt.savefig("name.png")
À placer avant plt.show().
Pour ne pas avoir de larges bordures blanches, ajouter le paramètre bbox_inches=“tight”.
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"]
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'erreurecolor: couleur de la barre d'erreurelinewidth: épaisseur de la barre d'erreurfmt: 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.
Pour que le trait de barre d'erreur soit pointillé:
(_, _, barline) = ax.errorbar(...) barline[0].set_linestyle('--')
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')
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:
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)
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 (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})
# faire le graphe parent # sous-graphe: ax = plt.axes([.2, .6, .2, .2]) # faire le sous-graphe plt.show()
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
r = plt.plot(x, y, 'o-') color = r[0].get_color()
Donne la liste des couleurs utilisées par Matplotlib (Source):
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
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.
Pour que la couleur suivante soit bien distincte de la précédente.
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))]
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
import matplotlib print(matplotlib.rcsetup.interactive_bk) print(matplotlib.rcsetup.non_interactive_bk) print(matplotlib.rcsetup.all_backends)
print(matplotlib.get_backend()