"""plot_utils.py Ce module contient des fonctions utilitaires pour la visualisation des données, notamment des graphiques linéaires, histogrammes, boxplots, scatterplots et heatmaps de corrélation, ainsi que des fonctions spécifiques pour visualiser les résultats d'une analyse en composantes principales (ACP). Les fonctions incluent : - lineplot_graphic : pour visualiser les tendances de plusieurs variables au fil du temps ou d'une autre variable - histrogram_graphic : pour visualiser la distribution d'une variable - boxplot_graphic : pour visualiser la distribution d'une variable en fonction d'une autre variable - scatterplot_graphic : pour visualiser la relation entre deux variables - pearson_heatmap_graphic : pour visualiser la corrélation entre les variables d'un dataframe en utilisant la méthode de Pearson - spearman_heatmap_graphic : pour visualiser la corrélation entre les variables d'un dataframe en utilisant la méthode de Spearman 'un dataframe en utilisant la méthode de Spearman - heatmap_by_group : pour visualiser la corrélation entre les variables d'un dataframe en fonction d'une variable de regroupement - plot_pca_projection : pour visualiser la projection des données dans le plan défini par les composantes principales - plot_scree : pour visualiser l'éboulis des valeurs propres (scree plot) pour l'ACP - plot_correlation_circle : pour visualiser le cercle des corrélations pour les composantes principales """ import matplotlib.pyplot as plt import seaborn as sns import pandas as pd import numpy as np def lineplot_graphic(df: pd.DataFrame, x: str, y_list: list, title: str, xlabel: str, ylabel: str, hue: str=None): """ graphiques linéaire pour visualiser le pourcentage des valeurs pour un axe x et plusieurs axes y df: dataframe contenant les données à visualiser x: nom de la colonne à utiliser pour l'axe x y_list: liste des colonnes à utiliser pour les axes y hue: nom de la colonne à utiliser pour colorer les points (optionnel) title: titre du graphique xlabel: label de l'axe x ylabel: label de l'axe y """ try: plt.figure(figsize=(12, 6)) for y in y_list: if hue is not None: sns.lineplot(data=df, x=x, y=y, hue=hue) else: sns.lineplot(data=df, x=x, y=y, label=y) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.legend() plt.show() except ImportError as e: print("Erreur d'importation : ", e) return def histrogram_graphic(df: pd.DataFrame, x: str, title: str, xlabel: str, ylabel: str): """ graphique histogramme pour visualiser la distribution d'une variable df: dataframe contenant les données à visualiser x: nom de la colonne à utiliser pour l'axe x title: titre du graphique xlabel: label de l'axe x ylabel: label de l'axe y """ try: plt.figure(figsize=(12, 6)) sns.histplot(data=df, x=x, kde=True) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.show() except ImportError as e: print("Erreur d'importation : ", e) return def boxplot_graphic(df: pd.DataFrame, x: str, y: str=None, title: str="", xlabel: str="", ylabel: str=""): """ graphique boxplot pour visualiser la distribution d'une variable en fonction d'une autre variable df: dataframe contenant les données à visualiser x: nom de la colonne à utiliser pour l'axe x y: nom de la colonne à utiliser pour l'axe y optionnel title: titre du graphique xlabel: label de l'axe x ylabel: label de l'axe y """ try: plt.figure(figsize=(12, 6)) sns.boxplot(data=df, x=x, y=y) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.show() except ImportError as e: print("Erreur d'importation : ", e) return def scatterplot_graphic(df: pd.DataFrame, x: str, y: str, title: str, xlabel: str, ylabel: str, hue: str=None): """ graphique scatterplot pour visualiser la relation entre deux variables df: dataframe contenant les données à visualiser x: nom de la colonne à utiliser pour l'axe x y: nom de la colonne à utiliser pour l'axe y title: titre du graphique xlabel: label de l'axe x ylabel: label de l'axe y hue: nom de la colonne à utiliser pour colorer les points (optionnel) """ try: plt.figure(figsize=(12, 6)) sns.scatterplot(data=df, x=x, y=y, hue=hue) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.show() except ImportError as e: print("Erreur d'importation : ", e) return def spearman_heatmap_graphic(df: pd.DataFrame, cols: list, title: str): """ graphique heatmap pour visualiser la corrélation entre les variables d'un dataframe df: dataframe contenant les données à visualiser cols: liste des colonnes à utiliser pour le calcul de la corrélation title: titre du graphique """ try: plt.figure(figsize=(12, 6)) corr = df[cols].corr(method='spearman') sns.heatmap(corr, annot=True, cmap='coolwarm', vmin=-1, vmax=1, mask=np.triu(corr)) plt.title(title) plt.show() except ImportError as e: print("Erreur d'importation : ", e) return def pearson_heatmap_graphic(df: pd.DataFrame, cols: list, title: str): """ graphique heatmap pour visualiser la corrélation entre les variables d'un dataframe df: dataframe contenant les données à visualiser cols: liste des colonnes à utiliser pour le calcul de la corrélation title: titre du graphique """ try: plt.figure(figsize=(12, 6)) corr = df[cols].corr(method='pearson') sns.heatmap(corr, annot=True, cmap='coolwarm', vmin=-1, vmax=1, mask=np.triu(corr)) plt.title(title) plt.show() except ImportError as e: print("Erreur d'importation : ", e) return def heatmap_by_group(df, group_col, cols, method="pearson"): """ Affiche une heatmap de corrélation pour chaque groupe défini par group_col df: dataframe contenant les données à visualiser group_col: nom de la colonne à utiliser pour regrouper les données cols: liste des colonnes à utiliser pour le calcul de la corrélation method: méthode de corrélation ("pearson" ou "spearman") """ groups = df[group_col].unique() n = len(groups) fig, axes = plt.subplots(nrows=n//2 + n%2, ncols=2, figsize=(14, 5*n//2)) axes = axes.flatten() for i, group in enumerate(groups): df_group = df[df[group_col] == group] corr = df_group[cols].corr(method=method) sns.heatmap( corr, ax=axes[i], annot=True, cmap="coolwarm", vmin=-1, vmax=1, mask=np.triu(corr) ) axes[i].set_title(f"{method.capitalize()} - {group}") # supprime les axes vides for j in range(i+1, len(axes)): fig.delaxes(axes[j]) plt.tight_layout() plt.show() def plot_pca_projection(X_pca, df, label_col="item", hue_col=None, pc1=1, pc2=2, title=None): """ affiche la projection des données dans le plan défini par les composantes principales spécifiées. arguments: - X_pca : array-like, les données transformées dans l'espace des composantes principales - df : pd.DataFrame, le DataFrame original contenant les données - label_col : str, le nom de la colonne à utiliser pour les étiquettes des points (par défaut "item") - hue_col : str, le nom de la colonne à utiliser pour la coloration des points (par défaut None) - pc1 : int, le numéro de la première composante principale à afficher (par défaut 1) - pc2 : int, le numéro de la deuxième composante principale à afficher (par défaut 2) - title : str, le titre du graphique (par défaut None, affichera un titre générique) """ try: pca_df = pd.DataFrame({ f"PC{pc1}": X_pca[:, pc1 - 1], f"PC{pc2}": X_pca[:, pc2 - 1], label_col: df[label_col].values }) if hue_col is not None: pca_df[hue_col] = df[hue_col].values plt.figure(figsize=(10, 7)) if hue_col is not None: # détecter si numérique if pd.api.types.is_numeric_dtype(pca_df[hue_col]): sc = plt.scatter( pca_df[f"PC{pc1}"], pca_df[f"PC{pc2}"], c=pca_df[hue_col], cmap="viridis", alpha=0.7 ) cbar = plt.colorbar(sc) cbar.set_label(hue_col) else: # catégoriel sns.scatterplot( data=pca_df, x=f"PC{pc1}", y=f"PC{pc2}", hue=hue_col, alpha=0.7 ) plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') else: # fallback : label_col sns.scatterplot( data=pca_df, x=f"PC{pc1}", y=f"PC{pc2}", hue=label_col, alpha=0.7 ) plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.title(title if title else f"Projection ACP - PC{pc1} vs PC{pc2}") plt.xlabel(f"PC{pc1}") plt.ylabel(f"PC{pc2}") plt.grid(True) plt.tight_layout() plt.show() except Exception as e: print(f"Erreur lors de la projection ACP : {e}") def plot_scree(explained_var, cumulative_var): """ Affiche l'éboulis des valeurs propres (scree plot) pour visualiser la variance expliquée par chaque composante principale. arguments: - explained_var : array-like, pourcentage de variance expliquée par chaque composante principale - cumulative_var : array-like, pourcentage de variance cumulée expliquée par les composantes principales """ # Graphique plt.figure(figsize=(8,5)) # Barres (variance individuelle) plt.bar(range(1, len(explained_var)+1), explained_var, alpha=0.7) # Ligne (variance cumulée) plt.plot(range(1, len(cumulative_var)+1), cumulative_var, marker='o', color='red') # Labels plt.xlabel("Rang de l'axe d'inertie") plt.ylabel("Pourcentage d'inertie") plt.title("Éboulis des valeurs propres") plt.xticks(range(1, len(explained_var)+1)) plt.ylim(0, 100) plt.grid(True) plt.show() def plot_correlation_circle(pca, features): """ Affiche le cercle des corrélations pour les deux premières composantes principales. arguments: - pca : objet PCA après ajustement - features : liste des noms des variables utilisées dans la PCA """ x, y = 0,1 fig, ax = plt.subplots(figsize=(10, 9)) # On peut ajuster la taille du graphique selon les besoins # Affichage des flèches pour chaque variable for i in range(0, pca.components_.shape[1]): ax.arrow(0, 0, # Start the arrow at the origin pca.components_[0, i], #0 for PC1 pca.components_[1, i], #1 for PC2 head_width=0.07, head_length=0.07, width=0.02, ) # Affichage des noms des variables à la fin de chaque flèche plt.text(pca.components_[0, i] + 0.05, pca.components_[1, i] + 0.05, features[i]) # affichage des lignes horizontales et verticales plt.plot([-1, 1], [0, 0], color='grey', ls='--') plt.plot([0, 0], [-1, 1], color='grey', ls='--') # nom des axes, avec le pourcentage d'inertie expliqué plt.xlabel('F{} ({}%)'.format(x+1, round(100*pca.explained_variance_ratio_[x],1))) plt.ylabel('F{} ({}%)'.format(y+1, round(100*pca.explained_variance_ratio_[y],1))) plt.title("Cercle des corrélations (F{} et F{})".format(x+1, y+1)) an = np.linspace(0, 2 * np.pi, 100) plt.plot(np.cos(an), np.sin(an)) # Add a unit circle for scale plt.axis('equal') plt.show(block=False)