Courbes et nuages de points (scatter plot) avec python

Voici un code à copier-coller pour avoir un petit jeu de données pour tester les graphiques

hematies = [4.51, 4.92, 4.66, 4.63, 4.67, 4.72, 4.76, 4.76, 4.57, 4.58, 4.46, 4.63, 4.59, 4.46] # nb de globules rouges

vgm = [94.0, 93.0, 93.0, 93.4, 93.4, 94.4, 93.6, 94.3, 94.9, 94.9, 96.8, 95.2, 95.0, 97.2] # taille des globules rouges

  • Importer le module nécessaire pyplot de matplotlib

import matplotlib.pyplot as plt

1- Graphique de base : plot

  • Un exemple de graphique de base

import matplotlib.pyplot as plt

plt.plot(hematies,vgm,"ob") # ob = type de points "o" ronds, "b" bleus

plt.show() # Obligatoire pour voir le graphique

Un raccourci utile : quand une fenêtre graphique fait planter la console python qui n'affiche plus ses >>>, faire un ctrl+C

  • Mise en forme des axes : ajouter un titre à l'axe des abscisses et des ordonnées

plt.plot(hematies,vgm,"ob") # ob = type de points "o" ronds, "b" bleus

plt.ylabel('VGM (taille des globules rouges)')

plt.xlabel('Hématies (nombre de globules rouges)')

plt.show()

Les axes ont maintenant des titres
  • Mise en forme des axes : changer les limites des axes x et y

plt.plot(hematies,vgm,"or") # ob = type de points "o" ronds, "r" red

plt.axis([4, 5.5, 90, 100])

plt.show()

Autres fonctions pou séparer les limites de x et y :

plt.ylim(90,100)

plt.xlim(4,5.5)

L'échelle des axes a changé
  • Afficher les axes sélectivement 4 axes possibles

fig, ax = plt.subplots(figsize=(10, 5))

plt.plot(hematies,vgm,"og") # ob = type de points "o" ronds, "r" red

ax.spines['top'].set_visible(False) ; ax.spines['right'].set_visible(False)

plt.show()

fig, ax = plt.subplots(figsize=(10, 5)) Cette écriture permet d'ajouter des sous propriétés au graphique pour supprimer ses axes.

spines().set_visible() permet d'afficher ou non les axes.

On n'affiche plus les axes haut et droit
  • Ajouter un titre

plt.plot(hematies,vgm,marker="s",mec="#57E537",ls="",mfc="red")

plt.title("Titre du graphique")

plt.show()

Voici ainsi un graphique pourvu d'un titre. ls (type de ligne) a permis d'inactiver les lignes. On a pu jouer subtilement sur la forme de marker (marker) et les couleurs internes (mfc) et périphériques (mec) des points.

  • Changer les types de points ou de traits

Couleurs disponibles par défaut : b (bleu), r (red), g (vert), c (cyan), k (noir), y (jaune)...Formes de points par défaut : o (rond), ^ (triangle), s (carré), v (triangle à l'envers)...Types de traits par défaut : - (normal), -- (pointillés)

plt.plot([1, 2, 3, 4],[4 ,5,10,7],"-gs") # green carré

plt.plot([2,3],[6,11],"-k") # ligne noire

plt.plot([2,3],[8,13],"^b") # triangle blue

plt.plot([2,3],[9,14],"--c") # ligne cyan pointillé

plt.plot([2,3],[10,15],"-vy") # ligne yellow triangle à l'envers

plt.ylabel('ylab')

plt.xlabel('xlab')

plt.axis([0, 6, 0, 20])

plt.show()


# Aller plus loin

help(plt.plot)

On voit dans cet exemple que la superposition de graphiques est très simple ! Il suffit d'insérer plusieurs lignes entre le premier tracé et la ligne plt.show().

Plusieurs courbes superposées, des points ronds, triangulaires, des changements de couleur, des traits ou des pointillés

2- Réaliser un scatter-plot : sensus stricto, un nuage de points dont les points changent de taille ou de couleur

Colorer les points en fonction de leurs catégories

Un exemple simple à reprendre :

cate = ["f","m","f","f","m"]

import pandas as pd

cate = pd.Series(cate)

plt.scatter([1,2,3,4,5],[1,2,3,4,5],c=cate.apply(lambda x : cat[x])) ; plt.show()

    • Prenons un jeu de données poids, tailles et IMC de filles et garçons (code à copier-coller directement pour simuler ces valeurs)

import numpy as np

from numpy.random import normal as norm # On tapera ainsi norm() au lien de np.random.normal()

import pandas as pd

f_poids = list(norm(loc = 55, size=20, scale=11)) # Conversion en list nécessaire pour faire des concaténation avec +

f_taille = list(norm(loc = 163, size=20, scale=14))

m_poids = list(norm(loc = 70, size=20, scale=11))

m_taille = list(norm(loc = 175, size=20, scale=15))

poids = f_poids+m_poids ; poids = np.array(poids) # conversion np.array nécessaire pour multiplier et additionner des listes

taille = f_taille+m_taille ; taille = np.array(taille)

imc = poids/(taille/100)**2

sexe = ["F"]*20+["M"]*20

compil = {"Sexe" : sexe , "Poids" : poids, "Taille" : taille, "IMC" : imc}

compil = pd.DataFrame(compil) ; print(compil)

  • 1) Méthode la plus simple : colorer avec seaborn

import seaborn as sns

On peut colorer les points selon une variable de catégories : ici, le sexe

sns.relplot(x="Poids",y="Taille",hue="Sexe",data=compil,height=6,s=70) ; plt.show()

On peut aussi colorer les points en fonction d'une 3ème variable numérique

sns.relplot(x="Poids",y="Taille",hue="IMC",data=compil,height=6,s=70) ; plt.show()

  • 2) Méthode relativement simple pour coloriser par catégories : en utilisant le format dataframe/category de pandas

# Chargement de données

import seaborn as sns ; iris = sns.load_dataset('iris')

# Détermination de la colonne de catégories

Species = iris.iloc[:,4] ; colors = Species.astype('category') ; print(colors.cat.codes)

# Tracer le scatter plot

import matplotlib.pyplot as plt

plt.scatter(iris.iloc[:,1],iris.iloc[:,2],c=colors.cat.codes)

plt.show()

  • 3) Colorier subtilement les points en fonction des catégories (méthode de base avec seulement 2 catégories)

    • 1) Prenons le jeu de données de l'exemple compil ci-dessus

value=(compil['Poids']>80) & (compil['Sexe']=="M") # Pour coloriser les hommes de plus de 80 kg

compil['color']= np.where( value==True , "red", "#3498db")

plt.scatter(compil.Poids,compil.IMC,color= compil.color) ; plt.show()

  • 4) Méthode plus subtile, paramétrage fin des caractéristiques de chaque catégorie :

    • 4.1) Définir les caractéristiques des points de chaque catégorie (Homme (M) et Femmes (F))

colors = {'F':'pink', 'M':'blue'} # Définition des colorations par catégories

cex = {'F':40, 'M':10} # Définition des tailles de points par catégories

pch = {'F':"o", 'M':"s"} # Définition des types de marqueurs par catégories

    • 4.2) Tracer le graphique en utilisant la fonction apply(lambda x : dic[x]) pour changer les points selon les catégories

import matplotlib.pyplot as plt


plt.scatter(compil.Poids,compil.Taille,

c=compil.Sexe.apply(lambda x: colors[x]),

s=compil.Sexe.apply(lambda x: cex[x]),

marker="s")

plt.xlabel("Poids (kg)") ; plt.ylabel("IMC")

plt.title("Relation poids IMC de filles et garçons")

plt.show()

Les points sont changés selon les catégories (ici le sexe) et une définition manuelle de chaque point pour chaque catégorie.

Un exemple brut de bubble chart

  • Simuler des données (code à copier-coller) :

# Données

data = {'x': np.arange(50),

'y': np.arange(50) + 10 * np.random.randn(50),

'taille': np.abs(np.random.randn(50)*100),

'color': np.random.randint(0, 50, 50)}

  • Tracer le bubble chart

from matplotlib import pyplot as plt

# Scatter plot (plot à point avec palette de couleur par défaut Viridis()

# scatter(x,y,c=color, s=taille)

plt.scatter('x', 'y', c='color', s='taille', data=data)

plt.xlabel('entry a')

plt.ylabel('entry b')

cbar= plt.colorbar()

cbar.set_label("Variable de coloration", labelpad=+1)

plt.show()

Gradient de couleur mise sous forme de barre de couleur légendée.

On notera que la couleur par défaut vient de la palette Viridis adaptée à la vue des daltoniens et à l'impression en niveau de gris (noir et blanc)

3- Superposer de l'information (droites de régressions linéaires, verticales, texte, flèches)

  • Ajouter un commentaire, du texte sur le graphique

plt.scatter(hematies,vgm,marker="s",color="#57E537")

plt.text(4.6,96,"Ici un commentaire",fontsize=12)

plt.show()

commande à retenir : plt.text()

  • Tracer des lignes verticales et horizontales sur le graphique

plt.scatter(hematies,vgm,marker="s",color="#FB0BD6")

import numpy as np # pour calculer les moyennes de x et y dans cet exemple

# Traits vertical et horizontal (R abline in python)

plt.axvline(x=np.mean(hematies),color="k")

plt.axhline(y=np.mean(vgm),color="g",linewidth=10) # linewidth permet de jouer sur l'épaisseur

plt.show()

commandes à retenir : plt.axvline() et plt.axhline()

  • Tracer une flèche (méthode simple (et moche) et méthode complexe (et belle))

plt.scatter(hematies,vgm,marker="s",color="#22FBD6")

# Méthode 1 - coordonnées de départ, hauteur et largeur

plt.arrow(4.8, 96,-0.1,-1.2, head_width=0.05, head_length=0.50, fc='red', ec='blue')

# Méthode 2 avec la fonction annotate (flèche cyan dans l'exemple)

plt.annotate('dernier point', xy = (4.65, 94.5), xytext = (4.5, 93),

arrowprops = {'facecolor': 'cyan', 'edgecolor': 'cyan',

'width': 15, 'headwidth': 30, 'shrink': 0.1})

plt.show()

commandes à retenir : plt.arrow() et plt.annotate()

Deux types de flèches, à vous de choisir
  • Tracer une ellipse de confiance

hematies = np.array(hematies)

vgm = np.array(vgm)

fig, ax = plt.subplots()

plt.scatter(hematies,vgm,marker="s",color="#22FBD6")

confidence_ellipse(hematies, vgm , ax, edgecolor='red') # nécessite la fonction confidence_ellipse (cf. lien)

plt.show()

  • Tracer une nappe convexe (convexe hull) : entourer un nuage de points

from scipy.spatial import ConvexHull

points = np.random.rand(30, 2) # 30 random points in 2-D

hull = ConvexHull(points)


import matplotlib.pyplot as plt

plt.plot(points[:,0], points[:,1], 'o')

for simplex in hull.simplices:

plt.plot(points[simplex, 0], points[simplex, 1], 'k-')

#plt.plot(points[hull.vertices,0], points[hull.vertices,1], 'r--', lw=2)

#plt.plot(points[hull.vertices[0],0], points[hull.vertices[0],1], 'ro')

plt.show()

4- Ajouter une légende

Ajouter une légende (méthode simple, à paramétrer manuellement)

1) Prenons un jeu de données poids et tailles de filles et garçons

poids = [60,50,40,35,55,48,65,67,58,55,72]

taille = [173,135,140,150,150,160,165,170,180,177,178]

sexe = ["F"]*5+["M"]*6

color = ["pink"]*5+["blue"]*6

2) Traçons le graphique

import matplotlib.patches as mpatches

import matplotlib.pyplot as plt

plt.scatter(poids,taille,

c=color)

pop_f = mpatches.Patch(color='pink', label='F')

pop_m = mpatches.Patch(color='blue', label='M')

plt.legend(handles=[pop_f,pop_m])

plt.show()

Dans cet exemple, la légende ne se construit pas automatiquement, elle est paramétrée manuellement.

3) Même exemple, légende sur courbes

plt.plot(list(range(0,5)),[1,2,3,4,7],label="boys",c="blue")

plt.plot(list(range(0,5)),[0.5,1.5,2.5,5,6],label="girls",c="pink")

plt.legend()

plt.show()

Ajouter une légende (méthode simple, à paramétrer semi-automatiquement)

    • 1) Voici un jeu de données à colorer par catégories ("F", "M", et "NA" non caractérisée)

poids = [60,50,40,35,55,48,65,67,58,55,72]

taille = [173,135,140,150,150,160,165,170,180,177,178]

sexe = ["F"]*5+["NA"]+["M"]*5

compil = {"Poids":poids, "Taille":taille, "Sexe":sexe} # Etape de mise en dictionnaire avant conversion en dataframe

import pandas as pd

compil = pd.DataFrame(compil) # Les données doivent être au format dataframe

    • 2) Définir les caractéristiques de chaque catégorie au format dictionnaire

category = {'F':0, 'M':1, 'NA':2} # Numéroter les catégories

col = {'F':'pink', 'M':'blue', 'NA':'green'} # Définition des colorations par catégories

cex = {'F':60, 'M':40, 'NA':70} # Définition des tailles de points par catégories

pch = {'F':"o", 'M':"s", 'NA':'^'} # Définition des types de marqueurs par catégories

Gestion de plusieurs catégories et tracé automatique de la légende selon les caractéristiques des points
    • 3) Réaliser une liste des couleurs et des formes de chaque point pour chaque catégorie

col_s = compil.Sexe.apply(lambda x: col[x])

cex_s = compil.Sexe.apply(lambda x: cex[x])

pch_s = compil.Sexe.apply(lambda x: pch[x])

category_s = compil.Sexe.apply(lambda x: category[x])

    • 4) Tracer. La seule façon d'avoir une légende qui prenne automatiquement en compte les caractéristiques de chaque catégorie est de les tracer les unes après les autres (boucle for ou n lignes à copier-coller)

fig, ax = plt.subplots(figsize=(10, 5))

for i in range(3) :

print("Voici la catégorie : ",i)

ax.scatter(compil.Poids[category_s==i],compil.Taille[category_s==i],

c=col_s[category_s==i], s=cex_s[category_s==i],

marker="o",label=list(cex.keys())[i])


ax.legend() ; ax.grid(True)

plt.show()

5- Ajouter des barres d'erreur

  • Ajouter des barres d'erreur avec la fonction errorbar()

x = list(range(1,11,1)) ; y = [2,4,3,5,4,6,7,8,9,8]

erreur = [1,0.5,2,1,0.5,0.5,1,2,1,2] # Classiquement, l'erreur est un intervalle de confiance

import matplotlib.pyplot as plt

plt.scatter(x,y,s=50) ; # Tracer le nuage de points

# Ajouter les barres d'erreur

plt.errorbar(x,y, yerr= erreur, # yerr : barres verticales, xerr : barres horizontales

ecolor = "#0B1131",capsize = 7, # capsize : longueur du trait horizontal

elinewidth = 3,capthick = 3, # epaisseurs de la barre d'erreur et du trait horizontal

fmt="none") ; plt.grid() ; plt.show()

On constate un petit problème : les points sont derrières les barres d'erreur (et c'est moche)

  • Tracer scatter-plot et barres d'erreur avec la fonction errorbar() pour ne plus avoir les points derrière

plt.errorbar(x,y, yerr= erreur,

ecolor = "#0B1131",capsize = 7, # Couleur au format html : pour éditer

elinewidth = 3,capthick = 3,

fmt="-ro") ; plt.show() # -ro : comme pour plot : lignes ("-") rouge ("r") avec des points ronds ("o")

Là, c'est mieux...

  • Et si je voulais des barres horizontales en plus :

x = list(range(1,11,1)) ; y = [2,4,3,5,4,6,7,8,9,8]

y_erreur = [1,0.5,0.5,1,0.5,0.5,1,0.5,1,0.6]

x_erreur = [1,0.5,1,1,0.5,0.5,1,0.5,1,1]

plt.errorbar(x,y, yerr= y_erreur,xerr = x_erreur,

ecolor = "green",capsize = 4,

elinewidth = 2,capthick = 2,

fmt="-bo") ; plt.show()

6- Scatter plot 3D - courbe 3D - graphique y = f(x1*x2) en 3D

6.1- Scatter 3D simple

# Voici des données simulées

import numpy as np

x = np.random.normal(size=15,loc=10,scale=3)

y = np.random.normal(size=15,loc=10,scale=3)

z = np.random.normal(size=15,loc=10,scale=3)

# Tracer le graphique

import matplotlib.pyplot as plt

from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()

ax = fig.gca(projection='3d')

ax.scatter(x,y,z, zdir='z',s=40,depthshade=True)

# Paramétrer le graphique

ax.set_xlim3d([0.0, 20.0]) ; ax.set_xlabel('X')

ax.set_ylim3d([0.0, 20.0]) ; ax.set_ylabel('Y')

ax.set_zlim3d([0.0, 20.0]) ; ax.set_zlabel('Z')

# Afficher

plt.show()

6.2- Scatter 3D et nuages de points mutiples

  • Voici des nuages de points tracés ligne par ligne

# Voici un jeu de données pour 3 nuages de points

import numpy as np

data1 = (np.random.normal(size=15,loc=10,scale=3),

np.random.normal(size=15,loc=15,scale=3),

np.random.normal(size=15,loc=10,scale=4))

data2 = (np.random.normal(size=15,loc=15,scale=4),

np.random.normal(size=15,loc=15,scale=3),

np.random.normal(size=15,loc=15,scale=3))

data3 = (np.random.normal(size=15,loc=14,scale=3),

np.random.normal(size=15,loc=13,scale=5),

np.random.normal(size=15,loc=10,scale=3))

# Affichage simple ligne par ligne

from mpl_toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

fig = plt.figure()

ax = fig.gca(projection='3d')

ax.scatter(data1[0],data1[1],data1[2],c="red",s=40)

ax.scatter(data2[0],data2[1],data2[2],c="green",s=40)

ax.scatter(data3[0],data3[1],data3[2],c="blue",s=40)

plt.show()

Axes3D.scatter() pour tracer les nuages

  • Voici des nuages de points tracés avec une mise en forme automatique (on reprend les données de l'exemple ci-dessus)

datas = (data1, data2, data3)

colors = ("red", "green", "blue")

groups = ("env1", "env2", "env3")

from mpl_toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

# Configurer le graphique

fig = plt.figure()

ax = fig.gca(projection='3d')

# Ajouter les 3 nuages de points

for d, c, g in zip(datas, colors, groups):

x, y, z = d # on découpe chaque paquet en x, y, z

ax.scatter(x, y, z, alpha=0.8, c=c, s=30, label=g)

# Affichage

plt.title('Nuages de points 3D')

plt.legend(loc=2)

# Affichage

plt.show()

plt.legend() pour ajouter une légende.

Une boucle for pour tracer les nuages

6.3- Afficher une nappe 3D

  • Nappe 3D : surfaçage d'un nuage de points

# Des données à surfacer

import numpy as np

x = np.random.normal(size=15,loc=10,scale=3)#;x.sort()

y = np.random.normal(size=15,loc=10,scale=3)#;y.sort()

z = x**2 + y**2 - 3*x - 3*y - 3

# Afficher le graphique

from mpl_toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

fig = plt.figure()

ax = fig.gca(projection='3d')

ax.plot_trisurf(x, y, z, cmap = "viridis")

plt.show()

Axes3D.plot_trisurf()

  • Lissage 3D : surface d'une courbe 3D

# Données simulées

X = np.arange(-5, 5, 0.25)

Y = np.arange(-5, 5, 0.25)

# Grille de lissage faite pour toutes valeur de X et Y (équivalent de expand.grid() de R)

X, Y = np.meshgrid(X, Y)

R = np.sqrt(X**2 + Y**2)

Z = np.sin(R)

# Affichage de la nappe

fig = plt.figure()

ax = fig.gca(projection='3d')

surface = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap="plasma",

linewidth=0, antialiased=False)

ax.set_zlim(-1.01, 1.01)

fig.colorbar(surface, shrink=0.5, aspect=5)

plt.show()

Grille faite avec numpy.meshgrid() et surface faire avec Axes3D.plot_surface()

6.4- Sauvegarder un graphique 3D au format GIF animé

  • Pour sauvegarder un gif animé, copier-coller ce code en l'insérant juste avec la dernière ligne plt.show()

print("Faire une animation")

def rotate(angle):

ax.view_init(azim=angle)

import matplotlib.animation as animation; animation.writers.list()

rot_animation = animation.FuncAnimation(fig, rotate, frames=np.arange(0, 362, 2), interval=100)

import os as os

os.chdir("C:/dossier") # A personnaliser en mettant des / à la place des \

rot_animation.save('rotation.gif', dpi=80, writer='pillow')

7- Kernel density - Nappes convexes : jeu de données denses

7.1- Kernel density

Un exemple de données : les données iris.

import seaborn as sns

print(sns.get_dataset_names())

iris = sns.load_dataset("iris") ; print(iris.head())


x_c = iris.iloc[:,0]

y_c = iris.iloc[:,1]

Affichage d'un graphique de densité simple

sns.set_style("white")

sns.kdeplot(x="sepal_length",y="sepal_width",data=iris) # Traits de contours

sns.kdeplot(x="sepal_length",y="sepal_width",data=iris, cmap="hot", shade=True, thresh=0)

plt.show()

En changeant un peu la mise en forme...

sns.set_style("white")

sns.kdeplot(x="sepal_length",y="sepal_width",data=iris, cmap="Blues", shade=True)

plt.show()

En croisant plusieurs catégories...

sns.kdeplot(x="sepal_length",y="sepal_width",data=iris[iris.species=="setosa"], cmap="YlGn",shade=True, thresh=0.25,alpha=0.5)

sns.kdeplot(x="sepal_length",y="sepal_width",data=iris[iris.species=="versicolor"], cmap="YlOrBr",shade=True, thresh=0.25,alpha=0.5)

sns.kdeplot(x="sepal_length",y="sepal_width",data=iris[iris.species=="virginica"], cmap="Purples",shade=True, thresh=0.25,alpha=0.5)

plt.show()

7.2- Nappes convexes

On peut entourer les nuages de points de chaque catégories ou d'un nuage de points simple lorsqu'on a trop de points à afficher. Une ellipse à 95% est tout aussi envisageable... cf. ci-dessus dans cette page...

Nappes convexes entourant 3 nuages de points

Nappes convexes seules pour alléger l'affichage

En reprenant x_c et y_c de l'exemple ci-dessus des données iris.

Définir une variable de catégories :

cat = df.Series(iris.species).astype("category")

Importer les modules nécessaires et définir une couleur automatique pour chaque catégorie :

import numpy as np

from scipy.spatial import ConvexHull

# Définir les couleurs des nappes convexes

import matplotlib.cm as cm

import matplotlib as mpl

norm = mpl.colors.Normalize(vmin=0, vmax=(len(np.unique(cat.cat.codes)))) #-(len(np.unique(c)))

cmap = "viridis_r" # "YlGn"

m = cm.ScalarMappable(norm=norm, cmap=cmap)

Affichage

# Optionnel et à éviter si on a trop de points : affichage des points

plt.scatter(x_c,y_c, c = cat.cat.codes,cmap="viridis_r")

# Affichage des nappes convexes qui entourent chaque catégorie

for cat_temp in cat.cat.codes.unique() :

x_c_temp = [x_c[i] for i in range(len(x_c)) if (cat.cat.codes[i] == cat_temp)]

y_c_temp = [y_c[i] for i in range(len(y_c)) if (cat.cat.codes[i] == cat_temp)]

# Former pour chaque couple (X;Y) d'une catégorie, une nappe de points

points = [ [ None ] * len(x_c_temp) ] * 2

points = np.array(points)

points = points.reshape(len(x_c_temp),2)

points[:,0] = x_c_temp

points[:,1] = y_c_temp

# Déterminer les coordonnées de la nappe qui entoure ces points

hull = ConvexHull(points)

temp = 0

# Coloration puis tracé de la nappe convexe

for simplex in hull.simplices:

color_temp = m.to_rgba(cat_temp)

plt.plot(points[simplex, 0], points[simplex, 1],color=color_temp)#, linestyle='dashed')#linewidth=2,color=cat)


plt.show()

Même chose avec une ellipse de confiance : Pensez à télécharger la fonction confidence_ellipse()

#####

# ELLIPSE DE CONFIANCE

####

fig, ax = plt.subplots()

plt.scatter(diamonds.carat,diamonds.price,color="white")

for cat_temp in cat.cat.codes.unique() :

print("Patience...")

x_c_temp = [x_c[i] for i in range(len(x_c)) if (cat.cat.codes[i] == cat_temp)]

y_c_temp = [y_c[i] for i in range(len(y_c)) if (cat.cat.codes[i] == cat_temp)]

# Former pour chaque couple (X;Y) d'une catégorie, une nappe de points

points = [ [ None ] * len(x_c_temp) ] * 2

points = np.array(points)

points = points.reshape(len(x_c_temp),2)

points[:,0] = x_c_temp

points[:,1] = y_c_temp

x_c_temp = np.array(x_c_temp)

y_c_temp = np.array(y_c_temp)

# Déterminer les coordonnées de la nappe qui entoure ces points

color_temp = m.to_rgba(cat_temp)

confidence_ellipse(x_c_temp , y_c_temp , ax, edgecolor=color_temp)

temp = 0

# Coloration puis tracé de la nappe convexe

# for simplex in hull.simplices:

# color_temp = m.to_rgba(cat_temp)

# plt.plot(points[simplex, 0], points[simplex, 1],color=color_temp)#, linestyle='dashed')#linewidth=2,color=cat)

plt.show()

8- Sauvegarder un graphique au format image

import os as os

os.chdir("C:/Users/python") # remplacer \ par /

  • 2- Tracer le graphique et sauvegarder dans la foulée

plt.scatter(hematies,vgm,marker="s",color="black")

plt.savefig("test.png", bbox_inches='tight')