Création de Diagrammes de Pareto et Dessin de Formes sur les Tableaux Matplotlib

Visualisation de Données avec Matplotlib

Les diagrammes en barres sont des outils fondamentaux pour la visualisation de distributions catégorielles. Matplotlib offre une flexibilité étendue pour personnaliser ces graphiques.

Diagrames en Barres

Diagramme en Barres Vertical Pour représenter des données sous forme de barres verticales, il est courant d'ajouter des étiquettes affichant les pourcentages correspondants au-dessus de chaque barre.

import matplotlib.pyplot as plt

# Données d'exemple
categories_data = ['Catégorie A', 'Catégorie B', 'Catégorie C', 'Catégorie D']
values_data = [0.23, 0.45, 0.56, 0.78]  # Valeurs à convertir en pourcentages

# Initialisation de la figure et des axes
figure, axes = plt.subplots()

# Tracé du diagramme en barres
bars_plot = axes.bar(categories_data, values_data)

# Ajout des étiquettes de pourcentage sur chaque barre
axes.bar_label(bars_plot, labels=[f'{val * 100:.2f}%' for val in values_data])

# Configuration du titre et des légendes
axes.set_title('Diagramme en Barres avec Pourcentages')
axes.set_xlabel('Catégories')
axes.set_ylabel('Valeurs (%)')

# Affichage du graphique
plt.show()

Diagramme en Barres Horizontal Les diagrammes en barres horizontaux sont utiles lorsque les noms de catégories sont longs ou lorsqu'on souhaite une comparaison verticale.

import matplotlib.pyplot as plt
import numpy as np

# Données d'exemple
labels_h = ['Article X', 'Article Y', 'Article Z', 'Article W']
measures_h = np.random.rand(4) # Génère des nombres aléatoires entre 0 et 1

# Initialisation de la figure et des axes
fig_h, ax_h = plt.subplots()

# Tracé du diagramme en barres horizontal
horizontal_bars = ax_h.barh(labels_h, measures_h, color='lightblue')

# Ajout des étiquettes de pourcentage
ax_h.bar_label(horizontal_bars, labels=[f'{m * 100:.2f}%' for m in measures_h], padding=8)

# Configuration du titre et des légendes
ax_h.set_title('Diagramme en Barres Horizontal avec Pourcentages')
ax_h.set_xlabel('Proportion (%)')
ax_h.set_ylabel('Éléments')

# Affichage du graphique
plt.show()

Diagramme de Pareto Un diagramme de Pareto combine un diagramme en barres, affichant les fréquences individuelles par ordre décroissant, et une ligne de cumul qui montre le pourcentage cumulatif. La ligne rouge représente généralement le pourcentage cumulatif, tandis que les barres représentent les valeurs individuelles.

import matplotlib.pyplot as plt
import numpy as np

# Données : catégories et leurs fréquences ou valeurs
event_types = ['Défaut A', 'Défaut B', 'Défaut C', 'Défaut D', 'Défaut E']
frequencies = [30, 20, 15, 10, 25]

# Tri des données par ordre décroissant des fréquences
sorted_indices = np.argsort(frequencies)[::-1]
event_types_sorted = [event_types[i] for i in sorted_indices]
frequencies_sorted = [frequencies[i] for i in sorted_indices]

# Calcul des pourcentages et pourcentages cumulatifs
total_frequency = sum(frequencies_sorted)
individual_percentages = [freq / total_frequency for freq in frequencies_sorted]
cumulative_percentages = np.cumsum(individual_percentages) * 100

# Création de la figure et des deux axes (pour les barres et la ligne cumulative)
fig_pareto, ax_bar = plt.subplots(figsize=(10, 6))

# Axe principal pour les barres (fréquences)
ax_bar.set_xlabel('Types d\'Événements')
ax_bar.set_ylabel('Fréquence Absolue', color='tab:blue')
bar_plot = ax_bar.bar(event_types_sorted, frequencies_sorted, color='tab:blue')
ax_bar.bar_label(bar_plot, labels=[f'{p * 100:.1f}%' for p in individual_percentages], fmt='%s', padding=3)
ax_bar.tick_params(axis='y', labelcolor='tab:blue')

# Deuxième axe pour la ligne cumulative (partage l'axe x)
ax_line = ax_bar.twinx()
ax_line.set_ylabel('Pourcentage Cumulatif (%)', color='tab:red')
ax_line.plot(event_types_sorted, cumulative_percentages, color='tab:red', marker='o', linestyle='-', linewidth=2, markersize=8)
ax_line.tick_params(axis='y', labelcolor='tab:red')
ax_line.set_ylim(0, 105) # S'assurer que la ligne cumulative monte jusqu'à 100%

# Ajout d'une grille pour une meilleure lisibilité
ax_bar.grid(axis='y', linestyle='--', alpha=0.7)

# Titre du graphique
fig_pareto.suptitle('Analyse de Pareto des Événements')
fig_pareto.tight_layout(rect=[0, 0.03, 1, 0.95]) # Ajuster pour le titre

plt.show()

Diagramme de Pareto avec Tableau Récapitulatif Pour une analyse plus détaillée, il est souvent utile d'intégrer un tableau récapitulatif sous le diagramme de Pareto, fournissant les valeurs numériques exactes.

import matplotlib.pyplot as plt
import numpy as np

# Données : catégories et leurs valeurs
categories_data_table = ['Cause 1', 'Cause 2', 'Cause 3', 'Cause 4', 'Cause 5']
values_data_table = [30, 20, 15, 10, 25]

# Tri des données par ordre décroissant
sorted_indices_table = np.argsort(values_data_table)[::-1]
categories_sorted_table = [categories_data_table[i] for i in sorted_indices_table]
values_sorted_table = [values_data_table[i] for i in sorted_indices_table]

# Calcul des pourcentages individuels et cumulatifs
total_value_table = sum(values_sorted_table)
percentages_table = [v / total_value_table for v in values_sorted_table]
cumulative_percentages_table = np.cumsum(percentages_table) * 100

# Création de la figure et des axes
fig_table, ax_bar_table = plt.subplots(figsize=(10, 7))

# Axe principal pour les barres
ax_bar_table.set_ylabel('Fréquence', color='tab:blue')
bar_plot_table = ax_bar_table.bar(categories_sorted_table, values_sorted_table, color='tab:blue')
ax_bar_table.bar_label(bar_plot_table, labels=[f'{p * 100:.1f}%' for p in percentages_table], fmt='%s', padding=3)
ax_bar_table.tick_params(axis='y', labelcolor='tab:blue')

# Deuxième axe pour la ligne cumulative
ax_line_table = ax_bar_table.twinx()
ax_line_table.set_ylabel('Pourcentage Cumulatif (%)', color='tab:red')
ax_line_table.plot(categories_sorted_table, cumulative_percentages_table, color='tab:red', marker='o', linestyle='-', linewidth=2, markersize=8)
ax_line_table.tick_params(axis='y', labelcolor='tab:red')
ax_line_table.set_ylim(0, 105)

# Préparation des données pour le tableau
table_data = [
    ['Catégorie', *categories_sorted_table],
    ['Valeur', *values_sorted_table],
    ['%', *[f'{p * 100:.1f}%' for p in percentages_table]],
    ['% Cumulatif', *[f'{p:.1f}%' for p in cumulative_percentages_table]]
]

# Ajout du tableau sous le graphique
table_ax = plt.table(cellText=[row[1:] for row in table_data],
                     rowLabels=[row[0] for row in table_data],
                     colLabels=categories_sorted_table,
                     loc='bottom', cellLoc='center',
                     bbox=[0, -0.35, 1, 0.25]) # Ajuster la position et la taille du tableau

# Ajustements pour éviter le chevauchement avec le tableau
plt.subplots_adjust(left=0.1, bottom=0.3)
ax_bar_table.set_xticks([]) # Masquer les étiquettes de l'axe X si elles sont redondantes avec le tableau

# Titre du graphique
fig_table.suptitle('Diagramme de Pareto avec Tableau Détaillé')
fig_table.tight_layout(rect=[0, 0.3, 1, 0.95])

plt.show()

Systèmes de Coordonnées et Dessin sur les Tableaux

Dans Matplotlib, plusieurs systèmes de coordonnées permettent de positionner des éléments graphiques. Les plus courants sont les coordonnées de données (liées aux valeurs du graphique), les coordonnées d'axes (normalisées de 0 à 1 par rapport à la zone de l'axe), et les coordonnées de figure (normalisées de 0 à 1 par rapport à la figure entière).

Lorsque l'on manipule des objets comme ax.table, il est essentiel de comprendre quel système de coordonnées est utilisé pour placer les formes. Par défaut, Rectangle et Ellipse prennent des coordonnées de données, tandis que des méthodes comme axhline et axvline utilisent des coordonnées de données pour la position principale et des coordonnées d'axes pour les limites (xmin, xmax, etc.).

Pour dessiner des formes sur un tableau ax.table de manière contrôlée, il est préférable de définir les limites des axes (ax.set_xlim, ax.set_ylim) de manière à ce qu'elles correspondent directement aux dimensions logiques du tableau (par exemple, de 0 à nombre_colonnes et de 0 à nombre_lignes). Cela simplifie le calcul des positions des formes dans les cellules du tableau.

Considérons un tableau N lignes par M colonnes. Nous pouvons définir les limites de l'axe de (0,0) à (M,N) en coordonnées de données. Une cellule à l'index (ligne, colonne) (où ligne est 0-indexée du haut vers le bas, et colonne de gauche à droite) aura son coin inférieur gauche aux coordonnées de données (colonne, N - 1 - ligne).

Exemple : Dessiner des Formes et Lignes sur un Tableau Matplotlib Cet exemple illustre comment dessiner des rectangles, ellipses, et lignes horizontales/verticales sur les cellules d'un tableau, en gérant de manière cohérente le système de coordonnées.

import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle, Ellipse

def draw_cell_rectangle(axes, num_rows, num_cols, row_idx, col_idx, width_factor=0.8, height_factor=0.8, color='blue'):
    """Dessine un rectangle dans une cellule spécifiée."""
    # Convertir les indices de ligne/colonne en coordonnées de données
    # Le coin inférieur gauche de la cellule (row_idx, col_idx)
    x_bottom_left = col_idx
    y_bottom_left = num_rows - 1 - row_idx # Y-axis increases upwards, rows from top-down

    # Positionner le rectangle au centre de la cellule
    rect_width = width_factor
    rect_height = height_factor
    x_center = x_bottom_left + 0.5
    y_center = y_bottom_left + 0.5

    # Calculer le coin inférieur gauche du rectangle centré
    rect_xy = (x_center - rect_width / 2, y_center - rect_height / 2)

    rect = Rectangle(rect_xy, rect_width, rect_height,
                     linewidth=1.5, edgecolor=color, facecolor='none',
                     transform=axes.transData) # Utilise les coordonnées de données
    axes.add_patch(rect)

def draw_cell_ellipse(axes, num_rows, num_cols, row_idx, col_idx, width_factor=0.9, height_factor=0.9, color='red'):
    """Dessine une ellipse dans une cellule spécifiée."""
    # Le centre de la cellule (row_idx, col_idx)
    x_center = col_idx + 0.5
    y_center = num_rows - 1 - row_idx + 0.5

    ellipse_width = width_factor # Diamètre sur l'axe X
    ellipse_height = height_factor # Diamètre sur l'axe Y

    ellipse = Ellipse((x_center, y_center), ellipse_width, ellipse_height,
                      edgecolor=color, facecolor='none', linewidth=1.5,
                      transform=axes.transData) # Utilise les coordonnées de données
    axes.add_patch(ellipse)

def draw_cell_horizontal_line(axes, num_rows, num_cols, row_idx, col_start, col_end, color='green'):
    """Dessine une ligne horizontale traversant des cellules."""
    # Y position (data coordinates) for the line (e.g., center of the row)
    y_line = num_rows - 1 - row_idx + 0.5

    # X limits (data coordinates)
    x_min_line = col_start
    x_max_line = col_end + 1 # +1 to span fully to the end of the last cell

    axes.hlines(y_line, x_min_line, x_max_line,
                linewidth=2, color=color, linestyle='--',
                transform=axes.transData) # Utilise les coordonnées de données pour x et y

def draw_cell_vertical_line(axes, num_rows, num_cols, row_start, row_end, col_idx, color='purple'):
    """Dessine une ligne verticale traversant des cellules."""
    # X position (data coordinates) for the line (e.g., center of the column)
    x_line = col_idx + 0.5

    # Y limits (data coordinates)
    y_min_line = num_rows - 1 - row_end - 1 # +1 for end of cell, -1 for index start
    y_max_line = num_rows - 1 - row_start

    axes.vlines(x_line, y_min_line, y_max_line,
                linewidth=2, color=color, linestyle=':',
                transform=axes.transData) # Utilise les coordonnées de données pour x et y


if __name__ == '__main__':
    num_table_rows = 6
    num_table_cols = 8

    # Création des données pour le tableau
    cell_matrix = [[f'{r},{c}' for c in range(num_table_cols)] for r in range(num_table_rows)]

    fig_shapes, ax_shapes = plt.subplots(figsize=(10, 8))

    # Dessiner le tableau
    table = ax_shapes.table(cellText=cell_matrix,
                            loc='center', cellLoc='center',
                            bbox=[0, 0, 1, 1], # Le tableau occupe toute la zone des axes
                            edges='all')
    table.auto_set_font_size(False)
    table.set_fontsize(10)

    # Ajuster les limites des axes pour qu'elles correspondent directement aux cellules du tableau
    # x: de 0 à num_table_cols, y: de 0 à num_table_rows
    ax_shapes.set_xlim(0, num_table_cols)
    ax_shapes.set_ylim(0, num_table_rows)

    # Masquer les ticks et labels des axes pour ne voir que le tableau
    ax_shapes.set_xticks([])
    ax_shapes.set_yticks([])

    # Désactiver le cadre de l'axe
    ax_shapes.spines['top'].set_visible(False)
    ax_shapes.spines['right'].set_visible(False)
    ax_shapes.spines['bottom'].set_visible(False)
    ax_shapes.spines['left'].set_visible(False)

    # Dessin de formes sur les cellules du tableau
    draw_cell_rectangle(ax_shapes, num_table_rows, num_table_cols, 1, 1, width_factor=0.7, height_factor=0.7, color='blue')
    draw_cell_ellipse(ax_shapes, num_table_rows, num_table_cols, 2, 3, width_factor=0.9, height_factor=0.6, color='red')
    draw_cell_horizontal_line(ax_shapes, num_table_rows, num_table_cols, 4, 1, 4, color='green')
    draw_cell_vertical_line(ax_shapes, num_table_rows, num_table_cols, 0, 3, 6, color='purple')
    draw_cell_rectangle(ax_shapes, num_table_rows, num_table_cols, 5, 7, width_factor=0.9, height_factor=0.9, color='orange')
    draw_cell_ellipse(ax_shapes, num_table_rows, num_table_cols, 0, 0, width_factor=0.8, height_factor=0.8, color='cyan')


    plt.title("Dessin de Formes sur un Tableau Matplotlib", fontsize=14)
    plt.tight_layout()
    plt.show()

Étiquettes: Matplotlib Python visualisation de données Diagramme de Pareto Diagramme en Barres

Publié le 9 juin à 17h53