Matplotlib : Le superhéros de la visualisation de données pour votre entreprise

by Dr Chérif Abdou Magid
26 minutes read

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éMatplotlibTableauPower BIExcel
CoûtGratuit$70/mois/utilisateur$10/mois/utilisateurInclus dans Office 365
PersonnalisationComplèteLimitéeMoyenneBasique
AutomatisationTotale (Python)LimitéeMoyenne (Power Automate)Limitée (VBA)
Courbe d’apprentissageMoyenneFaibleMoyenneFaible
Intégration donnéesComplèteBonneExcellenteLimité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 :

  1. Sauver la présentation de Lumina Retail en créant des visualisations personnalisées en quelques heures
  2. Offrir des insights que leurs outils habituels ne permettaient pas de visualiser
  3. 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

  1. Installez Python et les bibliothèques nécessaires : pip install matplotlib pandas numpy jupyter
  2. Explorez la documentation officielle de Matplotlib : matplotlib.org
  3. 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 !

You may also like

Leave a Comment

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.