Une journée chez DataViz Solutions [Fiction]
8h30 du matin chez DataViz Solutions, une entreprise de conseil en business intelligence. Claire, data analyst senior, vient de recevoir un appel urgent du PDG de Lumina Retail, l’un de leurs plus importants clients.
« Nous avons une réunion du conseil d’administration dans 48 heures et nous devons présenter l’évolution de nos ventes trimestrielles avec des projections. Notre outil habituel de BI est en panne depuis hier soir. Pouvez-vous nous aider? »
Claire sourit. Cette situation, elle l’a déjà vécue des dizaines de fois. Alors que ses collègues s’agitent, elle ouvre tranquillement son terminal Python et tape une commande simple:
import matplotlib.pyplot as plt
« Ne vous inquiétez pas, » répond-elle au téléphone. « Je vous envoie des visualisations personnalisées avant la fin de la journée. »
C’est ça, la magie de Matplotlib. Dans un monde professionnel où chaque décision doit être appuyée par des données, cet outil est devenu l’arme secrète des entreprises agiles. Et aujourd’hui, cher lecteur, je vais vous montrer comment en faire votre allié le plus précieux.
Pourquoi Matplotlib est l’outil qu’il vous faut
Avant de plonger dans le code, laissez-moi vous poser une question : combien de temps passez-vous à préparer des visualisations pour vos rapports d’entreprise ? Si vous utilisez Excel ou des outils BI propriétaires, la réponse est probablement « trop ».
Matplotlib est la bibliothèque de visualisation la plus complète et flexible de l’écosystème Python. Contrairement aux solutions comme Power BI, Tableau ou même Excel, elle vous offre :
- Un contrôle total sur chaque aspect de vos graphiques
- Une intégration parfaite avec l’analyse de données en Python
- Une automatisation possible de vos rapports récurrents
- Zéro coût de licence, contrairement aux solutions propriétaires
Revenons à Claire. Voici comment elle commence son travail pour Lumina Retail :
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Chargement des données de ventes trimestrielles
sales_data = pd.read_excel('lumina_retail_sales.xlsx')
# Configuration du style pour un look professionnel
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = 'Arial'
plt.rcParams['axes.titlesize'] = 16
plt.rcParams['axes.labelsize'] = 14
En quelques lignes, Claire a défini un style cohérent avec la charte graphique de Lumina Retail. Essayez de faire ça aussi rapidement avec Excel !
Les fondamentaux de Matplotlib pour l’analyse business
Avant d’aller plus loin, comprenons la structure de base de Matplotlib :
# Création d'une figure et d'un axe
fig, ax = plt.subplots(figsize=(10, 6))
# Ajout de données à l'axe
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
sales = [1.2, 1.5, 1.3, 1.7]
ax.bar(quarters, sales, color='#3366CC')
# Personnalisation
ax.set_title('Ventes trimestrielles 2024 (en millions €)')
ax.set_xlabel('Trimestre')
ax.set_ylabel('Ventes (M€)')
# Ajout d'annotations
for i, v in enumerate(sales):
ax.text(i, v + 0.05, f'{v}M€', ha='center')
# Ajout d'une grille horizontale pour faciliter la lecture
ax.grid(axis='y', linestyle='--', alpha=0.7)
# Sauvegarde de l'image
plt.tight_layout()
plt.savefig('sales_quarterly.png', dpi=300)
# Affichage
plt.show()
Cette structure simple – figure, axes, données, personnalisation – est la base de tout graphique Matplotlib. Une fois maîtrisée, vous pourrez créer n’importe quelle visualisation dont votre entreprise a besoin.
Cas d’usage réels en entreprise
1. Analyse des tendances de ventes
Claire doit maintenant montrer l’évolution des ventes sur plusieurs années pour Lumina Retail :
# Données historiques sur 3 ans
years = ['2022', '2023', '2024']
quarterly_data = {
'Q1': [0.9, 1.1, 1.2],
'Q2': [1.0, 1.3, 1.5],
'Q3': [1.1, 1.2, 1.3],
'Q4': [1.2, 1.5, 1.7]
}
# Création du graphique
fig, ax = plt.subplots(figsize=(12, 7))
# Position des barres
x = np.arange(len(years))
width = 0.2 # largeur des barres
multiplier = 0
# Tracer les barres pour chaque trimestre
for quarter, sales in quarterly_data.items():
offset = width * multiplier
ax.bar(x + offset, sales, width, label=quarter)
multiplier += 1
# Personnalisation
ax.set_title('Évolution des ventes trimestrielles (2022-2024)')
ax.set_xlabel('Année')
ax.set_ylabel('Ventes (M€)')
ax.set_xticks(x + width * 1.5)
ax.set_xticklabels(years)
ax.legend(title='Trimestre')
ax.grid(axis='y', linestyle='--', alpha=0.5)
# Ajout d'une ligne de tendance annuelle
yearly_totals = [sum(quarterly_data[q][i] for q in quarterly_data) for i in range(len(years))]
ax2 = ax.twinx() # axe secondaire
ax2.plot(x + width * 1.5, yearly_totals, 'o-', color='red', linewidth=2, markersize=8)
ax2.set_ylabel('Total annuel (M€)', color='red')
ax2.tick_params(axis='y', colors='red')
plt.tight_layout()
plt.savefig('sales_evolution.png', dpi=300)
plt.show()
Ce graphique combine des barres groupées pour les données trimestrielles avec une ligne de tendance pour le total annuel – une visualisation qu’il faudrait construire en plusieurs étapes avec Excel ou Tableau.
2. Analyse de la performance produit
Claire continue avec une visualisation des ventes par catégorie de produits :
# Données de ventes par catégorie
categories = ['Électronique', 'Vêtements', 'Maison', 'Sports', 'Beauté']
sales_2023 = [4.5, 3.2, 2.8, 1.5, 2.0]
sales_2024 = [5.2, 3.0, 3.5, 1.8, 2.5]
profit_margin_2024 = [0.15, 0.40, 0.25, 0.30, 0.45] # marges bénéficiaires
# Création du graphique
fig, ax = plt.subplots(figsize=(12, 8))
# Barres pour 2023 et 2024
x = np.arange(len(categories))
width = 0.35
bars_2023 = ax.bar(x - width/2, sales_2023, width, label='2023', color='skyblue')
bars_2024 = ax.bar(x + width/2, sales_2024, width, label='2024', color='navy')
# Personnalisation
ax.set_title('Ventes par catégorie de produits')
ax.set_xlabel('Catégorie')
ax.set_ylabel('Ventes (M€)')
ax.set_xticks(x)
ax.set_xticklabels(categories)
ax.legend()
# Ajout des valeurs sur les barres
def add_labels(bars):
for bar in bars:
height = bar.get_height()
ax.annotate(f'{height}M€',
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), # décalage vertical
textcoords="offset points",
ha='center', va='bottom')
add_labels(bars_2023)
add_labels(bars_2024)
# Axe secondaire pour les marges bénéficiaires
ax2 = ax.twinx()
ax2.plot(x, profit_margin_2024, 'o-', color='green', linewidth=2)
ax2.set_ylabel('Marge bénéficiaire', color='green')
ax2.tick_params(axis='y', colors='green')
ax2.set_ylim(0, 0.7) # ajustement de l'échelle
# Affichage des pourcentages de marge
for i, margin in enumerate(profit_margin_2024):
ax2.annotate(f'{int(margin*100)}%',
xy=(i, margin),
xytext=(0, 5),
textcoords="offset points",
ha='center',
va='bottom',
color='green')
plt.tight_layout()
plt.savefig('category_performance.png', dpi=300)
plt.show()
Ce graphique combiné permet aux dirigeants de Lumina Retail de visualiser à la fois les volumes de ventes et les marges par catégorie – une information cruciale pour orienter leur stratégie produit.
3. Segmentation client et analyse RFM
Claire sait que Lumina Retail utilise un modèle RFM (Récence, Fréquence, Montant) pour segmenter sa clientèle. Elle crée une visualisation pour représenter leurs segments clients :
# Données de segmentation client
segments = {
'Champions': {'count': 450, 'avg_purchase': 250, 'retention': 0.85},
'Loyaux': {'count': 650, 'avg_purchase': 150, 'retention': 0.70},
'Potentiels': {'count': 800, 'avg_purchase': 120, 'retention': 0.45},
'Nouveaux': {'count': 1200, 'avg_purchase': 80, 'retention': 0.30},
'À risque': {'count': 350, 'avg_purchase': 200, 'retention': 0.15},
'Perdus': {'count': 550, 'avg_purchase': 100, 'retention': 0.05}
}
# Extraction des données pour le graphique
segment_names = list(segments.keys())
customer_counts = [segments[s]['count'] for s in segment_names]
avg_purchases = [segments[s]['avg_purchase'] for s in segment_names]
retention_rates = [segments[s]['retention'] for s in segment_names]
# Création d'un graphique à bulles
fig, ax = plt.subplots(figsize=(14, 8))
# Définition d'une palette de couleurs
colors = plt.cm.viridis(np.linspace(0, 1, len(segment_names)))
# Création des bulles
scatter = ax.scatter(avg_purchases, retention_rates, s=[count/10 for count in customer_counts],
c=colors, alpha=0.7, edgecolors='black')
# Personnalisation
ax.set_title('Segmentation client RFM', fontsize=18)
ax.set_xlabel('Panier moyen (€)', fontsize=14)
ax.set_ylabel('Taux de rétention', fontsize=14)
ax.grid(True, linestyle='--', alpha=0.5)
ax.set_xlim(0, 300)
ax.set_ylim(0, 1)
# Ajout des étiquettes pour chaque bulle
for i, name in enumerate(segment_names):
ax.annotate(f"{name}\n({customer_counts[i]} clients)",
(avg_purchases[i], retention_rates[i]),
ha='center', va='center',
fontweight='bold')
# Formater l'axe y en pourcentage
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{int(y*100)}%'))
# Légende pour la taille des bulles
handles, labels = scatter.legend_elements(prop="sizes", alpha=0.6, num=3,
func=lambda s: s*10)
legend = ax.legend(handles, ['Petit segment', 'Segment moyen', 'Grand segment'],
loc="upper left", title="Taille du segment")
plt.tight_layout()
plt.savefig('customer_segmentation.png', dpi=300)
plt.show()
Ce graphique à bulles permet de visualiser trois dimensions simultanément : le nombre de clients (taille), le panier moyen (axe X) et le taux de rétention (axe Y), donnant aux dirigeants une vue d’ensemble de leur base client.
4. Prévisions et planification stratégique
Pour finaliser sa présentation, Claire doit inclure des projections de ventes pour les prochains trimestres :
# Données historiques
quarters_past = ['2023-Q1', '2023-Q2', '2023-Q3', '2023-Q4',
'2024-Q1', '2024-Q2', '2024-Q3', '2024-Q4']
sales_past = [1.0, 1.3, 1.2, 1.5, 1.2, 1.5, 1.3, 1.7]
# Projections
quarters_future = ['2025-Q1', '2025-Q2', '2025-Q3', '2025-Q4']
sales_forecast = [1.8, 2.1, 1.9, 2.3]
forecast_upper = [1.9, 2.3, 2.1, 2.5] # limite haute de l'intervalle de confiance
forecast_lower = [1.7, 1.9, 1.7, 2.1] # limite basse de l'intervalle de confiance
# Création du graphique
fig, ax = plt.subplots(figsize=(14, 8))
# Données historiques
ax.plot(quarters_past, sales_past, 'o-', linewidth=2, markersize=8, label='Ventes réalisées')
# Projections
ax.plot(quarters_future, sales_forecast, 'o--', linewidth=2, markersize=8, color='red', label='Prévisions')
# Intervalle de confiance
ax.fill_between(quarters_future, forecast_lower, forecast_upper, color='red', alpha=0.2, label='Intervalle de confiance (95%)')
# Personnalisation
ax.set_title('Évolution des ventes et projections 2025', fontsize=18)
ax.set_xlabel('Trimestre', fontsize=14)
ax.set_ylabel('Ventes (M€)', fontsize=14)
ax.grid(True, linestyle='--', alpha=0.5)
# Rotation des étiquettes sur l'axe x pour une meilleure lisibilité
plt.xticks(rotation=45)
# Ligne verticale pour séparer historique et prévisions
ax.axvline(x=7.5, color='gray', linestyle='-', linewidth=1)
ax.text(7.5, 0.5, 'Aujourd\'hui', ha='center', va='bottom', color='gray', rotation=90)
# Objectifs commerciaux
targets = [1.5, 1.8, 1.6, 2.0]
ax.plot(quarters_future, targets, 'D--', color='green', linewidth=2, markersize=8, label='Objectifs')
# Ajouter une zone verte lorsque les prévisions dépassent les objectifs
for i in range(len(quarters_future)):
if sales_forecast[i] > targets[i]:
ax.fill_between([quarters_future[i]], [targets[i]], [sales_forecast[i]],
color='green', alpha=0.3)
else:
ax.fill_between([quarters_future[i]], [sales_forecast[i]], [targets[i]],
color='red', alpha=0.3)
# Annotations pour les projections
for i, (q, v) in enumerate(zip(quarters_future, sales_forecast)):
ax.annotate(f'{v}M€', xy=(q, v), xytext=(0, 5),
textcoords='offset points', ha='center')
ax.legend(loc='upper left')
plt.tight_layout()
plt.savefig('sales_forecast.png', dpi=300)
plt.show()
Ce graphique combine données historiques, projections et objectifs commerciaux – une visualisation complexe qui serait fastidieuse à créer avec des outils conventionnels.
Techniques avancées pour impressionner vos dirigeants
Tableaux de bord interactifs
Claire sait que l’interactivité est cruciale pour l’exploration des données. Voici comment elle pourrait créer un tableau de bord simple avec Matplotlib et ipywidgets (dans un notebook Jupyter) :
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as np
import ipywidgets as widgets # pip install ipywidgets
from IPython.display import display
# Configuration du dashboard
def create_dashboard(year_selected, include_forecast):
# Création de la figure avec GridSpec pour organiser les graphiques
fig = plt.figure(figsize=(18, 10))
gs = GridSpec(2, 2, figure=fig)
# Premier graphique: Ventes trimestrielles
ax1 = fig.add_subplot(gs[0, 0])
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
# Simuler des données différentes selon l'année sélectionnée
if year_selected == 2022:
sales = [0.9, 1.0, 1.1, 1.2]
elif year_selected == 2023:
sales = [1.1, 1.3, 1.2, 1.5]
else: # 2024
sales = [1.2, 1.5, 1.3, 1.7]
ax1.bar(quarters, sales, color='navy')
ax1.set_title(f'Ventes trimestrielles {year_selected}')
ax1.set_ylabel('Ventes (M€)')
ax1.grid(axis='y', linestyle='--', alpha=0.7)
# Deuxième graphique: Répartition par catégorie
ax2 = fig.add_subplot(gs[0, 1])
categories = ['Électronique', 'Vêtements', 'Maison', 'Sports', 'Beauté']
# Simuler des données différentes selon l'année
if year_selected == 2022:
category_sales = [3.8, 2.9, 2.4, 1.3, 1.8]
elif year_selected == 2023:
category_sales = [4.5, 3.2, 2.8, 1.5, 2.0]
else: # 2024
category_sales = [5.2, 3.0, 3.5, 1.8, 2.5]
ax2.pie(category_sales, labels=categories, autopct='%1.1f%%',
startangle=90, shadow=True)
ax2.set_title(f'Répartition des ventes par catégorie {year_selected}')
# Troisième graphique: Évolution mensuelle
ax3 = fig.add_subplot(gs[1, :])
months = ['Jan', 'Fév', 'Mar', 'Avr', 'Mai', 'Juin',
'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Déc']
# Générer des données mensuelles selon l'année
np.random.seed(year_selected) # Pour avoir des données cohérentes
monthly_sales = np.random.normal(loc=year_selected/10, scale=0.1, size=12)
monthly_sales = np.cumsum(monthly_sales) # Pour créer une tendance
monthly_sales = monthly_sales - monthly_sales[0] + 0.3 # Normaliser
ax3.plot(months, monthly_sales, 'o-', linewidth=2, markersize=8)
# Ajouter des prévisions si demandé
if include_forecast and year_selected == 2024:
future_months = ['Jan 25', 'Fév 25', 'Mar 25']
forecast = [monthly_sales[-1] + 0.1*i for i in range(1, 4)]
# Concaténer les données et étiquettes
all_months = months + future_months
all_sales = np.concatenate([monthly_sales, forecast])
ax3.plot(all_months, all_sales, 'o-', linewidth=2)
ax3.plot(future_months, forecast, 'o--', color='red', linewidth=2)
ax3.axvline(x=11.5, color='gray', linestyle='--')
ax3.text(11.5, 0.5, 'Prévisions', rotation=90)
ax3.set_title(f'Évolution mensuelle des ventes {year_selected}')
ax3.set_ylabel('Ventes (M€)')
ax3.grid(True, linestyle='--', alpha=0.5)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# Widgets interactifs
year_slider = widgets.IntSlider(
value=2024,
min=2022,
max=2024,
step=1,
description='Année:',
continuous_update=False
)
forecast_checkbox = widgets.Checkbox(
value=False,
description='Inclure prévisions',
disabled=False
)
# Fonction interactive
def update_dashboard(year, forecast):
create_dashboard(year, forecast)
# Lier les widgets à la fonction
widgets.interactive(update_dashboard, year=year_slider, forecast=forecast_checkbox)
Cette technique permet aux dirigeants d’explorer eux-mêmes les données, en changeant les paramètres selon leurs besoins.
Cartographie des données géographiques
Pour Lumina Retail, qui a des magasins dans toute la France, Claire peut créer une visualisation de la performance par région :
# Carte de France avec Cartopy
# Assurez-vous d'avoir installé les bibliothèques nécessaires
import matplotlib.pyplot as plt
import cartopy.crs as ccrs # pip install cartopy
import cartopy.feature as cfeature
import numpy as np
# Création de la figure avec projection
fig = plt.figure(figsize=(14, 10))
ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
# Définir les limites de la carte (France métropolitaine)
ax.set_extent([-5.0, 10.0, 41.0, 52.0], crs=ccrs.PlateCarree())
# Ajouter les caractéristiques géographiques
ax.add_feature(cfeature.COASTLINE.with_scale('50m'), linewidth=0.5)
ax.add_feature(cfeature.BORDERS.with_scale('50m'), linewidth=0.5)
ax.add_feature(cfeature.LAND, color='#f2f2f2')
ax.add_feature(cfeature.OCEAN, color='#46bcec')
# Données des magasins
store_locations = {
'Paris': {'lat': 48.8566, 'lon': 2.3522, 'sales': 5.2},
'Lyon': {'lat': 45.7640, 'lon': 4.8357, 'sales': 3.1},
'Marseille': {'lat': 43.2965, 'lon': 5.3698, 'sales': 2.8},
'Toulouse': {'lat': 43.6047, 'lon': 1.4442, 'sales': 1.9},
'Bordeaux': {'lat': 44.8378, 'lon': -0.5792, 'sales': 2.2},
'Lille': {'lat': 50.6292, 'lon': 3.0573, 'sales': 1.7},
'Strasbourg': {'lat': 48.5734, 'lon': 7.7521, 'sales': 1.5},
'Nantes': {'lat': 47.2184, 'lon': -1.5536, 'sales': 1.8},
'Nice': {'lat': 43.7102, 'lon': 7.2620, 'sales': 2.0}
}
# Normalisation des ventes
max_sales = max(store['sales'] for store in store_locations.values())
# Tracé des magasins
for city, info in store_locations.items():
# Calcul de la taille et de la couleur
size = (info['sales'] / max_sales) * 1000
color_intensity = info['sales'] / max_sales
circle_color = plt.cm.Reds(color_intensity)
# Tracé du cercle
ax.scatter(info['lon'], info['lat'], s=size, color=circle_color,
alpha=0.6, edgecolor='black', linewidth=1,
transform=ccrs.PlateCarree())
# Ajout du texte
ax.text(info['lon'], info['lat']+0.2, f"{city}\n{info['sales']}M€",
ha='center', va='center', fontweight='bold', fontsize=9,
transform=ccrs.PlateCarree())
# Titre et légende
plt.title('Performance des magasins Lumina Retail en France')
# Création de la colorbar
sm = plt.cm.ScalarMappable(cmap=plt.cm.Reds, norm=plt.Normalize(vmin=0, vmax=max_sales))
sm.set_array([]) # Alternative plus propre à sm._A = []
cbar = plt.colorbar(sm, ax=ax, shrink=0.7)
cbar.set_label('Ventes annuelles (M€)')
plt.tight_layout()
plt.savefig('store_performance_map_cartopy.png', dpi=300, bbox_inches='tight')
plt.show()
Cette carte permet d’identifier en un coup d’œil les régions les plus performantes.
Méthodologie pour implémenter Matplotlib dans votre entreprise
À ce stade, vous êtes peut-être convaincu de l’utilité de Matplotlib, mais vous vous demandez comment l’intégrer dans vos processus existants. Voici une méthodologie en 4 étapes que Claire recommande à ses clients :
1. Identification des besoins
Commencez par un audit de vos besoins en visualisation :
- Quels graphiques produisez-vous régulièrement ?
- Quels sont les formats attendus par vos dirigeants ?
- Quel niveau de personnalisation vous est nécessaire ?
2. Mise en place de l’environnement
# Installation des bibliothèques nécessaires
# pip install matplotlib pandas numpy jupyter
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Script pour configurer un style d'entreprise
def setup_company_style():
"""Configure le style Matplotlib selon la charte graphique de l'entreprise"""
plt.style.use('seaborn-v0_8-whitegrid') # style de base propre
# Couleurs de l'entreprise
company_colors = {
'primary': '#3366CC', # bleu principal
'secondary': '#DC3912', # rouge accentuation
'tertiary': '#FF9900', # orange
'quaternary': '#109618', # vert
'quinary': '#990099' # violet
}
# Configuration des polices
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Arial', 'Helvetica', 'sans-serif']
# Tailles
plt.rcParams['axes.titlesize'] = 16
plt.rcParams['axes.labelsize'] = 12
plt.rcParams['xtick.labelsize'] = 10
plt.rcParams['ytick.labelsize'] = 10
# Grille
plt.rcParams['grid.linestyle'] = '--'
plt.rcParams['grid.alpha'] = 0.7
# Format des figures
plt.rcParams['figure.figsize'] = (10, 6)
plt.rcParams['figure.dpi'] = 100
return company_colors
# Initialisation du style
COMPANY_COLORS = setup_company_style()
3. Création de fonctions réutilisables
Développez une bibliothèque de fonctions pour vos graphiques les plus courants :
def create_monthly_sales_chart(data, year, title=None, save_path=None):
"""
Crée un graphique des ventes mensuelles
Parameters:
-----------
data : pandas.DataFrame
Doit contenir une colonne 'month' et une colonne 'sales'
year : int
Année à visualiser
title : str, optional
Titre du graphique
save_path : str, optional
Chemin pour sauvegarder l'image
Returns:
--------
matplotlib.figure.Figure
La figure créée
"""
# Filtrer les données pour l'année sélectionnée
year_data = data[data['year'] == year]
# Création du graphique
fig, ax = plt.subplots()
ax.plot(year_data['month'], year_data['sales'], 'o-',
color=COMPANY_COLORS['primary'], linewidth=2, markersize=8)
# Personnalisation
if title:
ax.set_title(title)
else:
ax.set_title(f'Ventes mensuelles {year}')
ax.set_xlabel('Mois')
ax.set_ylabel('Ventes (M€)')
ax.grid(True, linestyle='--', alpha=0.7)
# Formater l'axe y avec le symbole €
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{y}M€'))
# Rotation des étiquettes
plt.tight_layout()
# Sauvegarde si nécessaire
if save_path:
plt.savefig(save_path, dpi=300)
return fig
def create_sales_comparison_chart(data, categories, years, title=None, save_path=None):
"""
Crée un graphique comparatif des ventes par catégorie sur plusieurs années
Parameters:
-----------
data : dict
Dictionnaire avec les années comme clés et les listes de ventes par catégorie comme valeurs
categories : list
Liste des noms de catégories
years : list
Liste des années à comparer
title : str, optional
Titre du graphique
save_path : str, optional
Chemin pour sauvegarder l'image
Returns:
--------
matplotlib.figure.Figure
La figure créée
"""
# Création du graphique
fig, ax = plt.subplots(figsize=(12, 7))
# Position des barres
x = np.arange(len(categories))
width = 0.8 / len(years) # Largeur des barres adaptée au nombre d'années
# Couleurs pour les différentes années
colors = [COMPANY_COLORS['primary'], COMPANY_COLORS['secondary'],
COMPANY_COLORS['tertiary'], COMPANY_COLORS['quaternary']]
# Création des barres pour chaque année
for i, year in enumerate(years):
offset = width * i - width * (len(years) - 1) / 2
bars = ax.bar(x + offset, data[year], width, label=str(year),
color=colors[i % len(colors)])
# Ajout des valeurs sur les barres
for bar in bars:
height = bar.get_height()
ax.annotate(f'{height}',
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), # décalage vertical
textcoords="offset points",
ha='center', va='bottom', fontsize=8)
# Personnalisation
if title:
ax.set_title(title)
else:
ax.set_title(f'Comparaison des ventes par catégorie')
ax.set_xlabel('Catégorie')
ax.set_ylabel('Ventes (M€)')
ax.set_xticks(x)
ax.set_xticklabels(categories, rotation=45, ha='right')
ax.legend()
plt.tight_layout()
# Sauvegarde si nécessaire
if save_path:
plt.savefig(save_path, dpi=300)
return fig
4. Automatisation des rapports
Une fois votre bibliothèque de fonctions créée, vous pouvez automatiser la génération de vos rapports :
def generate_monthly_report(data_file, output_dir, month, year):
"""
Génère un rapport mensuel complet avec plusieurs visualisations
Parameters:
-----------
data_file : str
Chemin vers le fichier de données
output_dir : str
Répertoire de sortie pour les images générées
month : int
Mois du rapport (1-12)
year : int
Année du rapport
Returns:
--------
dict
Dictionnaire contenant les chemins des images générées
"""
import os
from datetime import datetime
# Chargement des données
data = pd.read_excel(data_file)
# Création du répertoire de sortie si nécessaire
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# Formatage de la date pour les noms de fichiers
date_str = datetime.strptime(f"{year}-{month}", "%Y-%m").strftime("%Y_%m")
# Dictionnaire pour stocker les chemins des visualisations
report_visuals = {}
# 1. Graphique des ventes mensuelles YTD
ytd_data = data[(data['year'] == year) & (data['month'] <= month)]
fig1 = plt.figure(figsize=(12, 6))
ax1 = fig1.add_subplot(111)
months = ytd_data['month']
sales = ytd_data['sales']
ax1.bar(months, sales, color=COMPANY_COLORS['primary'])
ax1.plot(months, sales.cumsum(), 'o-', color=COMPANY_COLORS['secondary'],
linewidth=2, label='Cumulé')
# Objectif annuel
annual_target = data[data['year'] == year]['annual_target'].iloc[0]
monthly_target = annual_target / 12
ax1.axhline(y=monthly_target, color='green', linestyle='--',
label=f'Objectif mensuel: {monthly_target}M€')
ax1.set_title(f'Ventes mensuelles {year} (jusqu\'à {month})')
ax1.set_xlabel('Mois')
ax1.set_ylabel('Ventes (M€)')
ax1.legend()
# Formatage
ax1.grid(True, linestyle='--', alpha=0.7)
ax1.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{y}M€'))
# Sauvegarde
ytd_path = os.path.join(output_dir, f'sales_ytd_{date_str}.png')
plt.tight_layout()
plt.savefig(ytd_path, dpi=300)
plt.close(fig1)
report_visuals['ytd_sales'] = ytd_path
# 2. Comparaison avec l'année précédente
prev_year = year - 1
current_month_data = data[(data['year'] == year) & (data['month'] == month)]
prev_year_month_data = data[(data['year'] == prev_year) & (data['month'] == month)]
# S'assurer que nous avons des données pour les deux années
if not prev_year_month_data.empty and not current_month_data.empty:
fig2 = plt.figure(figsize=(10, 8))
# Sous-graphique pour les ventes par catégorie
ax2a = fig2.add_subplot(211)
# Extraire les données par catégorie
categories = ['Électronique', 'Vêtements', 'Maison', 'Sports', 'Beauté']
# Simuler des données par catégorie (dans un cas réel, celles-ci viendraient du fichier)
current_by_cat = current_month_data[categories].values[0]
prev_by_cat = prev_year_month_data[categories].values[0]
x = np.arange(len(categories))
width = 0.35
ax2a.bar(x - width/2, prev_by_cat, width, label=str(prev_year),
color=COMPANY_COLORS['tertiary'])
ax2a.bar(x + width/2, current_by_cat, width, label=str(year),
color=COMPANY_COLORS['primary'])
ax2a.set_title(f'Ventes par catégorie: {month}/{prev_year} vs {month}/{year}')
ax2a.set_xticks(x)
ax2a.set_xticklabels(categories, rotation=45, ha='right')
ax2a.legend()
# Sous-graphique pour la croissance
ax2b = fig2.add_subplot(212)
growth = [(current - prev) / prev * 100 for current, prev in zip(current_by_cat, prev_by_cat)]
colors = ['green' if g >= 0 else 'red' for g in growth]
ax2b.bar(categories, growth, color=colors)
ax2b.set_title('Croissance par catégorie (% vs année précédente)')
ax2b.set_ylabel('Croissance (%)')
ax2b.grid(axis='y', linestyle='--', alpha=0.7)
# Ajouter les valeurs
for i, g in enumerate(growth):
ax2b.annotate(f'{g:.1f}%', xy=(i, g),
xytext=(0, 5 if g >= 0 else -15),
textcoords='offset points', ha='center')
plt.tight_layout()
# Sauvegarde
comp_path = os.path.join(output_dir, f'category_comparison_{date_str}.png')
plt.savefig(comp_path, dpi=300)
plt.close(fig2)
report_visuals['category_comparison'] = comp_path
# 3. Projection pour le reste de l'année
if month < 12:
fig3 = plt.figure(figsize=(14, 7))
ax3 = fig3.add_subplot(111)
# Données réalisées jusqu'à maintenant
actual_months = list(range(1, month + 1))
actual_sales = data[(data['year'] == year) & (data['month'] <= month)]['sales'].values
# Projection pour les mois restants (dans un cas réel, utiliser un modèle de prévision)
remaining_months = list(range(month + 1, 13))
# Simuler des projections (dans un cas réel, utiliser un vrai modèle)
avg_growth = actual_sales[-1] / actual_sales[0] if len(actual_sales) > 1 else 1.05
projected_sales = [actual_sales[-1] * (avg_growth ** (i+1)) for i in range(len(remaining_months))]
# Tracer les données réelles
ax3.bar(actual_months, actual_sales, color=COMPANY_COLORS['primary'], label='Réalisé')
# Tracer les projections
ax3.bar(remaining_months, projected_sales, color=COMPANY_COLORS['tertiary'], alpha=0.7, label='Projection')
# Ligne pour l'objectif mensuel
all_months = list(range(1, 13))
ax3.plot(all_months, [monthly_target] * 12, 'g--', label=f'Objectif mensuel: {monthly_target}M€')
# Ligne pour le total cumulé
cumulative = list(actual_sales) + projected_sales
cumulative = np.cumsum(cumulative)
ax3.plot(all_months, cumulative, 'ro-', linewidth=2, label='Cumulé')
# Ligne pour l'objectif annuel
ax3.axhline(y=annual_target, color='green', linestyle='-',
label=f'Objectif annuel: {annual_target}M€')
# Annotations
total_projected = sum(actual_sales) + sum(projected_sales)
ax3.annotate(f'Total projeté: {total_projected:.1f}M€\n({(total_projected/annual_target-1)*100:.1f}% vs objectif)',
xy=(12, cumulative[-1]), xytext=(-100, 20),
textcoords='offset points', ha='center',
arrowprops=dict(arrowstyle='->'))
ax3.set_title(f'Projection des ventes pour {year}')
ax3.set_xlabel('Mois')
ax3.set_ylabel('Ventes (M€)')
ax3.set_xticks(all_months)
ax3.legend()
# Formatage
ax3.grid(True, linestyle='--', alpha=0.7)
# Sauvegarde
proj_path = os.path.join(output_dir, f'sales_projection_{date_str}.png')
plt.tight_layout()
plt.savefig(proj_path, dpi=300)
plt.close(fig3)
report_visuals['sales_projection'] = proj_path
return report_visuals
Comparaison avec les solutions commerciales
Maintenant que vous avez vu la puissance de Matplotlib, comparons-la avec les solutions commerciales couramment utilisées en entreprise :
Fonctionnalité | Matplotlib | Tableau | Power BI | Excel |
---|---|---|---|---|
Coût | Gratuit | $70/mois/utilisateur | $10/mois/utilisateur | Inclus dans Office 365 |
Personnalisation | Complète | Limitée | Moyenne | Basique |
Automatisation | Totale (Python) | Limitée | Moyenne (Power Automate) | Limitée (VBA) |
Courbe d’apprentissage | Moyenne | Faible | Moyenne | Faible |
Intégration données | Complète | Bonne | Excellente | Limitée |
Comme vous pouvez le constater, Matplotlib se distingue par sa flexibilité totale et son coût nul – des avantages considérables pour les entreprises de toute taille.
Conclusion : Pourquoi adopter Matplotlib dès aujourd’hui
Revenons à Claire de DataViz Solutions. Grâce à Matplotlib, elle a pu :
- Sauver la présentation de Lumina Retail en créant des visualisations personnalisées en quelques heures
- Offrir des insights que leurs outils habituels ne permettaient pas de visualiser
- Mettre en place un système automatisé de génération de rapports mensuels
Pour votre entreprise, adopter Matplotlib peut représenter :
- Des économies substantielles sur les licences logicielles
- Une flexibilité accrue pour adapter vos visualisations à vos besoins spécifiques
- Une intégration parfaite avec vos pipelines de données existants
- Une évolutivité sans limites pour accompagner votre croissance
Pour commencer dès aujourd’hui
- Installez Python et les bibliothèques nécessaires :
pip install matplotlib pandas numpy jupyter
- Explorez la documentation officielle de Matplotlib : matplotlib.org
- Adaptez les exemples de cet article à vos propres données
N’oubliez pas que la véritable puissance de Matplotlib réside dans sa flexibilité. Contrairement aux solutions commerciales qui vous enferment dans leurs limites, Matplotlib s’adapte à vos besoins, et non l’inverse.
Alors, êtes-vous prêt à transformer vos données en insights visuels irrésistibles ? Comme Claire aime à le dire : « Avec Matplotlib, la seule limite est votre imagination. »
Partagez-nous vos expériences avec Matplotlib en entreprise dans les commentaires ci-dessous !