Introduction
Un graphique radar (ou graphe polaire) est un excellent outil pour visualiser des données multivariées — par exemple, pour comparer plusieurs indicateurs ou catégories entre différentes entités.
Voici comment en créer un pas à pas en utilisant Matplotlib (et éventuellement Plotly pour l’interactivité).
Graphique Radar de Base avec Matplotlib
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import matplotlib.pyplot as plt import numpy as np # Données d’exemple categories = ['Précision', 'Exactitude', 'Rappel', 'F1-Score', 'Vitesse'] values = [0.9, 0.8, 0.85, 0.88, 0.7] # Fermer le cercle en répétant la première valeur values += values[:1] N = len(categories) # Calculer les angles pour chaque catégorie angles = np.linspace(0, 2 * np.pi, N, endpoint=False).tolist() angles += angles[:1] # Créer la figure fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True)) # Tracer un axe par catégorie + ajouter les étiquettes plt.xticks(angles[:-1], categories, color='black', size=12) # Tracer les étiquettes radiales ax.set_rlabel_position(30) plt.yticks([0.2, 0.4, 0.6, 0.8], ["0.2", "0.4", "0.6", "0.8"], color="gray", size=10) plt.ylim(0, 1) # Tracer les données ax.plot(angles, values, linewidth=2, linestyle='solid') ax.fill(angles, values, 'skyblue', alpha=0.4) plt.title("Performance du Modèle", size=14, y=1.1) plt.show() |

Explication
- Convertit les catégories en coordonnées angulaires (en radians).
- Ferme le tracé en répétant le premier élément.
- Utilise
polar=Truepour dessiner dans un espace circulaire. - Remplit la surface pour une meilleure lisibilité.
Comparer Plusieurs Modèles
Vous pouvez tracer plusieurs ensembles de données sur le même graphique radar :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | model_a = [0.9, 0.8, 0.85, 0.88, 0.7] model_b = [0.75, 0.82, 0.8, 0.77, 0.9] # Fermer le cercle model_a += model_a[:1] model_b += model_b[:1] fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True)) ax.plot(angles, model_a, 'b-', linewidth=2, label='Modèle A') ax.fill(angles, model_a, 'b', alpha=0.2) ax.plot(angles, model_b, 'r-', linewidth=2, label='Modèle B') ax.fill(angles, model_b, 'r', alpha=0.2) plt.xticks(angles[:-1], categories) plt.title("Comparaison de Modèles", size=14, y=1.1) plt.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1)) plt.show() |

Graphique Radar Interactif avec Plotly
Si vous souhaitez des infobulles et une rotation/zoom interactif :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | import plotly.graph_objects as go categories = ['Précision', 'Exactitude', 'Rappel', 'F1-Score', 'Vitesse'] model_a = [0.9, 0.8, 0.85, 0.88, 0.7] model_b = [0.75, 0.82, 0.8, 0.77, 0.9] fig = go.Figure() fig.add_trace(go.Scatterpolar( r=model_a, theta=categories, fill='toself', name='Modèle A' )) fig.add_trace(go.Scatterpolar( r=model_b, theta=categories, fill='toself', name='Modèle B' )) fig.update_layout( polar=dict(radialaxis=dict(visible=True, range=[0, 1])), showlegend=True, title="Graphique Radar Interactif" ) fig.show() |

Graphique Radar avec Pygal
Qu’est-ce que Pygal ?
Pygal est une bibliothèque Python qui génère des graphiques SVG interactifs — des graphiques vectoriels indépendants de la résolution, légers et parfaits pour le web ou l’impression.
Vous pouvez exporter les graphiques Pygal sous forme de :
- Fichiers SVG (interactifs, zoomables, avec infobulles)
- PNG, PDF, ou HTML intégrable dans le navigateur
Avantages de Pygal
| Fonctionnalité | Avantage |
|---|---|
| Syntaxe simple et élégante | API très claire, haut niveau, peu de configuration. |
| Sortie SVG interactive | Graphiques légers, scalables et interactifs (infobulles, légendes cliquables). |
| Intégrable facilement | Idéal pour les tableaux de bord ou les pages web (export facile en HTML). |
| Léger | Ne dépend pas de gros fichiers JavaScript (contrairement à Plotly). |
| Haute résolution | Les SVG se redimensionnent parfaitement pour les présentations ou impressions. |
| Hors ligne et statique | Ne nécessite ni serveur ni JavaScript — fonctionne hors connexion. |
Installer Pygal
Dans votre terminal ou notebook :
1 | pip install pygal |
Si vous utilisez Jupyter Notebook, vous pouvez aussi exécuter :
1 | !pip install pygal |
Puis tester l’importation :
1 2 | import pygal print(pygal.__version__) |
Si cela fonctionne, Pygal est prêt à être utilisé.
Exemple : Graphique Radar avec Pygal
Voici un exemple minimal :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import pygal from pygal.style import LightStyle # Données d’exemple categories = ['Précision', 'Exactitude', 'Rappel', 'F1-Score', 'Vitesse'] radar_chart = pygal.Radar(fill=True, style=LightStyle) radar_chart.title = 'Comparaison de Modèles' radar_chart.x_labels = categories radar_chart.add('Modèle A', [0.9, 0.8, 0.85, 0.88, 0.7]) radar_chart.add('Modèle B', [0.75, 0.82, 0.8, 0.77, 0.9]) # Afficher dans le navigateur ou exporter radar_chart.render_in_browser() # ou enregistrer en SVG radar_chart.render_to_file('comparaison_modeles.svg') |
💡 Astuce : render_in_browser() ouvre le graphique dans votre navigateur par défaut.
Le fichier SVG généré est entièrement interactif — survolez les points pour afficher les valeurs.
Comparaison avec d’Autres Bibliothèques
| Bibliothèque | Interactivité | Type de sortie | Points forts | Quand l’utiliser |
|---|---|---|---|---|
| Matplotlib | Statique | PNG/PDF | Hautement personnalisable, précision scientifique | Graphiques statiques pour publications |
| Plotly | Élevée | HTML/JS | Interactivité complète pour tableaux de bord | Exploration de données ou applications Dash |
| Pygal | Moyenne | SVG | Léger, esthétique, facile à intégrer | Visualisations statiques ou web légères |
Quand Utiliser Pygal
- Vous souhaitez des visuels interactifs mais légers (sans dépendances lourdes).
- Vous voulez intégrer vos graphiques dans un blog, un rapport ou une page web statique.
- Vous préférez une syntaxe simple et déclarative sans configuration complexe.
- Vous avez besoin d’une qualité vectorielle (PDF, présentations, impressions).
Références
| Liens | Site |
|---|---|
| https://matplotlib.org/stable/gallery/specialty_plots/radar_chart.html | Matplotlib — Exemple officiel de graphique radar |
| https://plotly.com/python/radar-chart/ | Plotly — Documentation officielle du graphique radar |
| http://www.pygal.org/en/stable/documentation/types/radar.html | Pygal — Documentation officielle du graphique radar |
Ancienne Version
Exemple intéressant de graphique en radar (radar chart) avec matplotlib réalisé par Nicolas P. Rougier.
Code source:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | #!/usr/bin/env python # -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Copyright (C) 2011 Nicolas P. Rougier # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # * Neither the name of the glumpy Development Team nor the names of its # contributors may be used to endorse or promote products derived from this # software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # ----------------------------------------------------------------------------- import numpy as np import matplotlib import matplotlib.path as path import matplotlib.pyplot as plt import matplotlib.patches as patches # Data to be represented # ---------- properties = ['property 1', 'property 2', 'property 3', 'property 4', 'property 5', 'property 6', 'property 7', 'property 8', 'property 9'] values = np.random.uniform(5,9,len(properties)) # ---------- # Choose some nice colors matplotlib.rc('axes', facecolor = 'white') # Make figure background the same colors as axes fig = plt.figure(figsize=(10,8), facecolor='white') # Use a polar axes axes = plt.subplot(111, polar=True) # Set ticks to the number of properties (in radians) t = np.arange(0,2*np.pi,2*np.pi/len(properties)) plt.xticks(t, []) # Set yticks from 0 to 10 plt.yticks(np.linspace(0,10,11)) # Draw polygon representing values points = [(x,y) for x,y in zip(t,values)] points.append(points[0]) points = np.array(points) codes = [path.Path.MOVETO,] + \ [path.Path.LINETO,]*(len(values) -1) + \ [ path.Path.CLOSEPOLY ] _path = path.Path(points, codes) _patch = patches.PathPatch(_path, fill=True, color='blue', linewidth=0, alpha=.1) axes.add_patch(_patch) _patch = patches.PathPatch(_path, fill=False, linewidth = 2) axes.add_patch(_patch) # Draw circles at value points plt.scatter(points[:,0],points[:,1], linewidth=2, s=50, color='white', edgecolor='black', zorder=10) # Set axes limits plt.ylim(0,10) # Draw ytick labels to make sure they fit properly for i in range(len(properties)): angle_rad = i/float(len(properties))*2*np.pi angle_deg = i/float(len(properties))*360 ha = "right" if angle_rad < np.pi/2 or angle_rad > 3*np.pi/2: ha = "left" plt.text(angle_rad, 10.75, properties[i], size=14, horizontalalignment=ha, verticalalignment="center") # A variant on label orientation # plt.text(angle_rad, 11, properties[i], size=14, # rotation=angle_deg-90, # horizontalalignment='center', verticalalignment="center") # Done plt.savefig('radar-chart.png', facecolor='white') plt.show() |
