# Fichier: python_cheats/cheatsheets/seaborn.txt
# Cheatsheet Seaborn - Guide Complet de Visualisation Statistique


[OK] INSTALLATION & IMPORTS

# Installation
pip install seaborn
pip install seaborn matplotlib pandas numpy

# Imports standards
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Version
print(sns.__version__)

# Vérifier installation
sns.get_dataset_names()  # Liste datasets intégrés


[OK] CONFIGURATION & STYLE

# === STYLES PRÉDÉFINIS ===

# Styles disponibles
sns.set_style("darkgrid")    # Grille sombre (défaut)
sns.set_style("whitegrid")   # Grille blanche
sns.set_style("dark")        # Fond sombre sans grille
sns.set_style("white")       # Fond blanc sans grille
sns.set_style("ticks")       # Avec graduations

# Contexte (taille des éléments)
sns.set_context("paper")     # Plus petit (publications)
sns.set_context("notebook")  # Moyen (défaut)
sns.set_context("talk")      # Grand (présentations)
sns.set_context("poster")    # Très grand (posters)

# Contexte avec scaling personnalisé
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})

# === PALETTES DE COULEURS ===

# Palettes qualitatives
sns.set_palette("deep")      # Défaut
sns.set_palette("muted")     # Couleurs atténuées
sns.set_palette("bright")    # Couleurs vives
sns.set_palette("pastel")    # Couleurs pastel
sns.set_palette("dark")      # Couleurs sombres
sns.set_palette("colorblind") # Accessible daltoniens

# Palettes séquentielles
sns.set_palette("Blues")
sns.set_palette("Greens")
sns.set_palette("Reds")

# Palettes divergentes
sns.set_palette("RdBu")      # Rouge-Bleu
sns.set_palette("coolwarm")  # Froid-Chaud

# Palette personnalisée
colors = ["#FF6B6B", "#4ECDC4", "#45B7D1"]
sns.set_palette(colors)

# Voir palette actuelle
sns.color_palette()
sns.palplot(sns.color_palette())  # Visualiser

# === THÈME COMPLET ===

# Configuration complète
sns.set_theme(
    style="darkgrid",
    palette="deep",
    context="notebook",
    font="sans-serif",
    font_scale=1,
    color_codes=True,
    rc=None
)

# Réinitialiser aux valeurs par défaut
sns.reset_defaults()
sns.reset_orig()  # Retour matplotlib défaut

# === PARAMÈTRES RC (MATPLOTLIB) ===

# Configurer via dictionnaire
sns.set(rc={
    'figure.figsize': (12, 8),
    'axes.titlesize': 16,
    'axes.labelsize': 14,
    'xtick.labelsize': 12,
    'ytick.labelsize': 12,
    'legend.fontsize': 12,
    'font.family': 'sans-serif'
})


[OK] GRAPHIQUES DE DISTRIBUTION

# === HISTOGRAMME ===

# Histogramme simple
sns.histplot(data=df, x="column")

# Avec KDE (Kernel Density Estimate)
sns.histplot(data=df, x="column", kde=True)

# Histogramme empilé
sns.histplot(data=df, x="column", hue="category", multiple="stack")

# Histogramme côte à côte
sns.histplot(data=df, x="column", hue="category", multiple="dodge")

# Histogramme normalisé
sns.histplot(data=df, x="column", stat="density")
sns.histplot(data=df, x="column", stat="probability")

# Contrôler les bins
sns.histplot(data=df, x="column", bins=30)
sns.histplot(data=df, x="column", binwidth=5)

# Histogramme 2D
sns.histplot(data=df, x="col1", y="col2")

# === KDE PLOT (DENSITÉ) ===

# KDE simple
sns.kdeplot(data=df, x="column")

# KDE avec remplissage
sns.kdeplot(data=df, x="column", fill=True)

# KDE multiple
sns.kdeplot(data=df, x="column", hue="category")

# KDE 2D (contours)
sns.kdeplot(data=df, x="col1", y="col2")

# KDE 2D rempli
sns.kdeplot(data=df, x="col1", y="col2", fill=True)

# Ajuster bandwidth
sns.kdeplot(data=df, x="column", bw_adjust=0.5)  # Plus lisse
sns.kdeplot(data=df, x="column", bw_adjust=2)    # Plus détaillé

# === ECDF (FONCTION DE RÉPARTITION) ===

# ECDF simple
sns.ecdfplot(data=df, x="column")

# ECDF par catégorie
sns.ecdfplot(data=df, x="column", hue="category")

# ECDF complémentaire
sns.ecdfplot(data=df, x="column", complementary=True)

# === RUG PLOT (MARQUEURS) ===

# Afficher observations individuelles
sns.rugplot(data=df, x="column")

# Combiner avec KDE
sns.kdeplot(data=df, x="column")
sns.rugplot(data=df, x="column", height=0.05)

# === DIST PLOT (DÉPRÉCIÉ mais encore utilisé) ===

# Distribution complète (hist + kde + rug)
sns.displot(data=df, x="column", kde=True, rug=True)

# Distribution par catégorie
sns.displot(data=df, x="column", hue="category", kind="kde")

# Facettes
sns.displot(data=df, x="column", col="category")
sns.displot(data=df, x="column", row="cat1", col="cat2")


[OK] GRAPHIQUES CATÉGORIELS

# === STRIP PLOT (NUAGE DE POINTS) ===

# Strip plot simple
sns.stripplot(data=df, x="category", y="value")

# Strip plot horizontal
sns.stripplot(data=df, x="value", y="category")

# Avec couleurs par sous-catégorie
sns.stripplot(data=df, x="category", y="value", hue="subcategory")

# Éviter superposition (jitter)
sns.stripplot(data=df, x="category", y="value", jitter=True)
sns.stripplot(data=df, x="category", y="value", jitter=0.2)

# Taille des points
sns.stripplot(data=df, x="category", y="value", size=8)

# === SWARM PLOT (ESSAIM) ===

# Swarm plot (pas de superposition)
sns.swarmplot(data=df, x="category", y="value")

# Avec couleurs
sns.swarmplot(data=df, x="category", y="value", hue="subcategory")

# Taille des points
sns.swarmplot(data=df, x="category", y="value", size=5)

# === BOX PLOT (BOÎTE À MOUSTACHES) ===

# Box plot simple
sns.boxplot(data=df, x="category", y="value")

# Box plot horizontal
sns.boxplot(data=df, x="value", y="category")

# Avec sous-catégories
sns.boxplot(data=df, x="category", y="value", hue="subcategory")

# Personnaliser
sns.boxplot(
    data=df,
    x="category",
    y="value",
    showfliers=True,      # Afficher outliers
    notch=True,           # Encoche (IC médiane)
    width=0.5,            # Largeur boîtes
    linewidth=2.5,        # Épaisseur lignes
    fliersize=5           # Taille outliers
)

# === VIOLIN PLOT (VIOLON) ===

# Violin plot simple
sns.violinplot(data=df, x="category", y="value")

# Avec split par catégorie
sns.violonplot(data=df, x="category", y="value", hue="subcategory", split=True)

# Montrer médiane et quartiles
sns.violinplot(data=df, x="category", y="value", inner="quartile")
sns.violinplot(data=df, x="category", y="value", inner="box")
sns.violinplot(data=df, x="category", y="value", inner="point")

# Ajuster bandwidth
sns.violinplot(data=df, x="category", y="value", bw=0.2)

# === BAR PLOT (BARRES) ===

# Bar plot avec moyenne et IC
sns.barplot(data=df, x="category", y="value")

# Changer estimateur
sns.barplot(data=df, x="category", y="value", estimator=np.median)
sns.barplot(data=df, x="category", y="value", estimator=sum)

# Sans barres d'erreur
sns.barplot(data=df, x="category", y="value", errorbar=None)

# Avec sous-catégories
sns.barplot(data=df, x="category", y="value", hue="subcategory")

# Changer intervalle de confiance
sns.barplot(data=df, x="category", y="value", errorbar=("ci", 95))

# === COUNT PLOT (COMPTAGE) ===

# Compter occurrences
sns.countplot(data=df, x="category")

# Avec sous-catégories
sns.countplot(data=df, x="category", hue="subcategory")

# Ordre personnalisé
order = ["A", "B", "C"]
sns.countplot(data=df, x="category", order=order)

# === POINT PLOT (POINTS ET LIGNES) ===

# Point plot (moyenne + IC)
sns.pointplot(data=df, x="category", y="value")

# Avec sous-catégories
sns.pointplot(data=df, x="category", y="value", hue="subcategory")

# Changer style marqueurs
sns.pointplot(data=df, x="category", y="value", markers=["o", "s", "D"])

# Changer style lignes
sns.pointplot(data=df, x="category", y="value", linestyles=["-", "--", ":"])

# === COMBINAISONS ===

# Box plot + Strip plot
sns.boxplot(data=df, x="category", y="value", color="white")
sns.stripplot(data=df, x="category", y="value", color="black", alpha=0.3)

# Violin plot + Swarm plot
sns.violinplot(data=df, x="category", y="value", inner=None, color="lightgray")
sns.swarmplot(data=df, x="category", y="value", size=3)


[OK] GRAPHIQUES RELATIONNELS

# === SCATTER PLOT (NUAGE DE POINTS) ===

# Scatter plot simple
sns.scatterplot(data=df, x="col1", y="col2")

# Avec couleurs par catégorie
sns.scatterplot(data=df, x="col1", y="col2", hue="category")

# Avec taille variable
sns.scatterplot(data=df, x="col1", y="col2", size="value")

# Avec style par catégorie
sns.scatterplot(data=df, x="col1", y="col2", style="category")

# Combinaison complète
sns.scatterplot(
    data=df,
    x="col1",
    y="col2",
    hue="category",
    size="value",
    style="type",
    alpha=0.7,
    palette="deep"
)

# Contrôler légende
sns.scatterplot(data=df, x="col1", y="col2", hue="category", legend="full")
sns.scatterplot(data=df, x="col1", y="col2", hue="category", legend=False)

# === LINE PLOT (COURBE) ===

# Line plot simple
sns.lineplot(data=df, x="time", y="value")

# Avec moyenne et IC
sns.lineplot(data=df, x="time", y="value", errorbar="sd")
sns.lineplot(data=df, x="time", y="value", errorbar=("ci", 95))

# Par catégorie
sns.lineplot(data=df, x="time", y="value", hue="category")

# Avec style de ligne
sns.lineplot(data=df, x="time", y="value", style="category")

# Avec marqueurs
sns.lineplot(data=df, x="time", y="value", markers=True)
sns.lineplot(data=df, x="time", y="value", markers=["o", "s"])

# Sans intervalle de confiance
sns.lineplot(data=df, x="time", y="value", errorbar=None)

# Estimateur personnalisé
sns.lineplot(data=df, x="time", y="value", estimator=np.median)

# === REL PLOT (FACETTES) ===

# Scatter avec facettes
sns.relplot(data=df, x="col1", y="col2", col="category", kind="scatter")

# Line avec facettes
sns.relplot(data=df, x="time", y="value", hue="cat1", col="cat2", kind="line")

# Grille de facettes
sns.relplot(
    data=df,
    x="col1",
    y="col2",
    row="cat1",
    col="cat2",
    hue="cat3",
    kind="scatter"
)

# Contrôler grille
sns.relplot(
    data=df,
    x="col1",
    y="col2",
    col="category",
    col_wrap=3,          # Colonnes par ligne
    height=4,            # Hauteur chaque subplot
    aspect=1.5           # Ratio largeur/hauteur
)


[OK] MATRICES & HEATMAPS

# === HEATMAP (CARTE DE CHALEUR) ===

# Heatmap simple
sns.heatmap(data=df)

# Avec annotations
sns.heatmap(data=df, annot=True)

# Format annotations
sns.heatmap(data=df, annot=True, fmt=".2f")
sns.heatmap(data=df, annot=True, fmt="d")  # Entiers

# Palette de couleurs
sns.heatmap(data=df, cmap="YlGnBu")
sns.heatmap(data=df, cmap="coolwarm")
sns.heatmap(data=df, cmap="RdBu_r")

# Centrer couleurs
sns.heatmap(data=df, center=0, cmap="coolwarm")

# Contrôler barre de couleur
sns.heatmap(data=df, cbar=True, cbar_kws={"label": "Score"})

# Limites couleurs
sns.heatmap(data=df, vmin=0, vmax=100)

# Lignes de séparation
sns.heatmap(data=df, linewidths=0.5, linecolor="white")

# Masquer triangle (matrices symétriques)
mask = np.triu(np.ones_like(df, dtype=bool))
sns.heatmap(data=df, mask=mask, annot=True)

# === MATRICE DE CORRÉLATION ===

# Corrélation complète
corr = df.corr()
sns.heatmap(corr, annot=True, cmap="coolwarm", center=0)

# Triangle inférieur seulement
mask = np.triu(np.ones_like(corr, dtype=bool))
sns.heatmap(corr, mask=mask, annot=True, cmap="coolwarm", center=0, square=True)

# Avec hiérarchie (clustering)
sns.clustermap(corr, annot=True, cmap="coolwarm", center=0)

# === CLUSTER MAP (DENDROGRAMMES) ===

# Clustermap simple
sns.clustermap(data=df)

# Sans clustering lignes/colonnes
sns.clustermap(data=df, row_cluster=False)
sns.clustermap(data=df, col_cluster=False)

# Normalisation Z-score
sns.clustermap(data=df, standard_scale=1)  # Par colonne
sns.clustermap(data=df, standard_scale=0)  # Par ligne

# Méthode de clustering
sns.clustermap(data=df, method="average")
sns.clustermap(data=df, method="ward")

# Distance métrique
sns.clustermap(data=df, metric="euclidean")
sns.clustermap(data=df, metric="correlation")


[OK] REGRESSION & DISTRIBUTIONS JOINTES

# === REG PLOT (RÉGRESSION) ===

# Régression linéaire simple
sns.regplot(data=df, x="col1", y="col2")

# Sans intervalle de confiance
sns.regplot(data=df, x="col1", y="col2", ci=None)

# Changer IC
sns.regplot(data=df, x="col1", y="col2", ci=95)

# Régression polynomiale
sns.regplot(data=df, x="col1", y="col2", order=2)
sns.regplot(data=df, x="col1", y="col2", order=3)

# Régression logistique
sns.regplot(data=df, x="col1", y="col2", logistic=True)

# Régression robuste
sns.regplot(data=df, x="col1", y="col2", robust=True)

# Personnaliser points
sns.regplot(
    data=df,
    x="col1",
    y="col2",
    scatter_kws={"alpha": 0.5, "s": 50},
    line_kws={"color": "red", "linewidth": 2}
)

# === LM PLOT (RÉGRESSION PAR CATÉGORIE) ===

# Régression par catégorie
sns.lmplot(data=df, x="col1", y="col2", hue="category")

# Régressions séparées
sns.lmplot(data=df, x="col1", y="col2", col="category")

# Grille de régressions
sns.lmplot(data=df, x="col1", y="col2", row="cat1", col="cat2")

# Sans régression
sns.lmplot(data=df, x="col1", y="col2", fit_reg=False)

# Ordre polynomial
sns.lmplot(data=df, x="col1", y="col2", order=2)

# Régression logistique
sns.lmplot(data=df, x="col1", y="col2", logistic=True)

# Ajuster hauteur/aspect
sns.lmplot(data=df, x="col1", y="col2", height=5, aspect=1.5)

# === JOINT PLOT (DISTRIBUTION JOINTE) ===

# Joint plot simple (scatter + histogrammes)
sns.jointplot(data=df, x="col1", y="col2")

# Avec régression
sns.jointplot(data=df, x="col1", y="col2", kind="reg")

# Avec KDE 2D
sns.jointplot(data=df, x="col1", y="col2", kind="kde")

# Hexbin (pour gros datasets)
sns.jointplot(data=df, x="col1", y="col2", kind="hex")

# Avec couleurs
sns.jointplot(data=df, x="col1", y="col2", hue="category")

# Personnaliser
sns.jointplot(
    data=df,
    x="col1",
    y="col2",
    kind="scatter",
    height=8,
    ratio=5,                    # Ratio plot central vs marginaux
    marginal_kws={"bins": 30},
    joint_kws={"alpha": 0.5}
)

# === PAIR PLOT (MATRICE DE DISPERSION) ===

# Pair plot simple
sns.pairplot(data=df)

# Sélectionner colonnes
sns.pairplot(data=df, vars=["col1", "col2", "col3"])

# Avec couleurs par catégorie
sns.pairplot(data=df, hue="category")

# Changer diagonale
sns.pairplot(data=df, diag_kind="kde")
sns.pairplot(data=df, diag_kind="hist")

# Changer hors-diagonale
sns.pairplot(data=df, kind="reg")
sns.pairplot(data=df, kind="kde")

# Combinaison complète
sns.pairplot(
    data=df,
    vars=["col1", "col2", "col3"],
    hue="category",
    diag_kind="kde",
    markers=["o", "s", "D"],
    palette="husl",
    height=2.5,
    aspect=1.2
)

# Avec fonction personnalisée
def scatter_with_corr(x, y, **kwargs):
    plt.scatter(x, y, **kwargs)
    r = np.corrcoef(x, y)[0, 1]
    plt.text(0.05, 0.95, f'r={r:.2f}', transform=plt.gca().transAxes)

g = sns.pairplot(data=df)
g.map_lower(scatter_with_corr)


[OK] GRAPHIQUES SPÉCIALISÉS

# === RESIDUAL PLOT (RÉSIDUS) ===

# Résidus régression
sns.residplot(data=df, x="col1", y="col2")

# Résidus lowess
sns.residplot(data=df, x="col1", y="col2", lowess=True)

# Ordre polynomial
sns.residplot(data=df, x="col1", y="col2", order=2)

# === FACET GRID (GRILLE PERSONNALISÉE) ===

# Créer grille
g = sns.FacetGrid(df, col="category")
g.map(sns.histplot, "value")

# Grille 2D
g = sns.FacetGrid(df, row="cat1", col="cat2")
g.map(sns.scatterplot, "x", "y")

# Avec couleurs
g = sns.FacetGrid(df, col="category", hue="subcategory")
g.map(sns.scatterplot, "x", "y")
g.add_legend()

# Contrôler dimensions
g = sns.FacetGrid(df, col="category", col_wrap=3, height=4, aspect=1.5)
g.map(sns.histplot, "value", kde=True)

# Fonction personnalisée
def custom_plot(x, y, **kwargs):
    plt.scatter(x, y, **kwargs)
    plt.axline((0, 0), slope=1, color='red', linestyle='--')

g = sns.FacetGrid(df, col="category")
g.map(custom_plot, "x", "y", alpha=0.5)

# Ajouter titres
g.set_titles("{col_name}")
g.set_axis_labels("X Label", "Y Label")

# === PAIR GRID (GRILLE DISPERSION PERSONNALISÉE) ===

# Créer grille
g = sns.PairGrid(df, vars=["col1", "col2", "col3"])

# Mapper différents plots
g.map_upper(sns.scatterplot)
g.map_lower(sns.kdeplot)
g.map_diag(sns.histplot)

# Avec couleurs
g = sns.PairGrid(df, hue="category")
g.map_diag(sns.histplot)
g.map_offdiag(sns.scatterplot)
g.add_legend()

# === JOINT GRID (DISTRIBUTION JOINTE PERSONNALISÉE) ===

# Créer grille
g = sns.JointGrid(data=df, x="col1", y="col2")

# Mapper plots
g.plot_joint(sns.scatterplot)
g.plot_marginals(sns.histplot)

# Personnaliser
g = sns.JointGrid(data=df, x="col1", y="col2", height=8, ratio=5)
g.plot_joint(sns.kdeplot, fill=True, cmap="Blues")
g.plot_marginals(sns.kdeplot, fill=True)


[OK] DATASETS INTÉGRÉS

# Lister datasets disponibles
sns.get_dataset_names()

# Charger datasets populaires
tips = sns.load_dataset("tips")
iris = sns.load_dataset("iris")
titanic = sns.load_dataset("titanic")
diamonds = sns.load_dataset("diamonds")
flights = sns.load_dataset("flights")
penguins = sns.load_dataset("penguins")
planets = sns.load_dataset("planets")
exercise = sns.load_dataset("exercise")
car_crashes = sns.load_dataset("car_crashes")
mpg = sns.load_dataset("mpg")

# Exemple d'utilisation
df = sns.load_dataset("tips")
sns.scatterplot(data=df, x="total_bill", y="tip", hue="day")


[OK] PERSONNALISATION AVANCÉE

# === AXES & FIGURES ===

# Créer figure matplotlib
fig, ax = plt.subplots(figsize=(10, 6))
sns.scatterplot(data=df, x="col1", y="col2", ax=ax)
ax.set_title("Mon Titre")
ax.set_xlabel("X Label")
ax.set_ylabel("Y Label")

# Subplots multiples
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
sns.histplot(data=df, x="col1", ax=axes[0, 0])
sns.boxplot(data=df, x="cat", y="val", ax=axes[0, 1])
sns.scatterplot(data=df, x="col1", y="col2", ax=axes[1, 0])
sns.violinplot(data=df, x="cat", y="val", ax=axes[1, 1])
plt.tight_layout()

# === TITRES & LABELS ===

# Via matplotlib
ax = sns.scatterplot(data=df, x="col1", y="col2")
ax.set_title("Mon Titre", fontsize=16, fontweight="bold")
ax.set_xlabel("X Label", fontsize=14)
ax.set_ylabel("Y Label", fontsize=14)

# Via plt
sns.scatterplot(data=df, x="col1", y="col2")
plt.title("Mon Titre", fontsize=16)
plt.xlabel("X Label", fontsize=14)
plt.ylabel("Y Label", fontsize=14)

# === LÉGENDES ===

# Positionner légende
ax = sns.scatterplot(data=df, x="col1", y="col2", hue="cat")
ax.legend(loc="upper right")
ax.legend(loc="best")
ax.legend(bbox_to_anchor=(1.05, 1), loc="upper left")

# Personnaliser légende
ax.legend(
    title="Catégorie",
    title_fontsize=14,
    fontsize=12,
    frameon=True,
    fancybox=True,
    shadow=True
)

# Supprimer légende
ax.legend().remove()
ax.get_legend().remove()

# === LIMITES & ÉCHELLES ===

# Limites axes
ax = sns.scatterplot(data=df, x="col1", y="col2")
ax.set_xlim(0, 100)
ax.set_ylim(-10, 10)

# Échelle log
ax.set_xscale("log")
ax.set_yscale("log")

# Aspect ratio
ax.set_aspect("equal")
ax.set_aspect(1.5)

# === GRILLES ===

# Ajouter grille
ax = sns.scatterplot(data=df, x="col1", y="col2")
ax.grid(True)
ax.grid(True, alpha=0.3, linestyle="--")

# Contrôler grille
ax.grid(True, which="major", axis="both")
ax.grid(True, which="minor", axis="x")

# === ROTATIONS & FORMATS ===

# Rotation labels
ax = sns.boxplot(data=df, x="category", y="value")
ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha="right")

# Format nombres
from matplotlib.ticker import FuncFormatter

def millions(x, pos):
    return f'{x/1e6:.1f}M'

ax.yaxis.set_major_formatter(FuncFormatter(millions))

# === ANNOTATIONS ===

# Annoter points
ax = sns.scatterplot(data=df, x="col1", y="col2")
ax.annotate(
    "Point important",
    xy=(x_val, y_val),
    xytext=(x_text, y_text),
    arrowprops=dict(arrowstyle="->", color="red")
)

# Ligne horizontale/verticale
ax.axhline(y=50, color="r", linestyle="--", label="Seuil")
ax.axvline(x=10, color="g", linestyle="--")

# Ligne diagonale
ax.axline((0, 0), slope=1, color="gray", linestyle="--")

# Zone colorée
ax.axhspan(20, 40, alpha=0.2, color="yellow")
ax.axvspan(5, 15, alpha=0.2, color="green")


[OK] COULEURS & PALETTES DÉTAILLÉES

# === PALETTES QUALITATIVES ===

# Palettes named
sns.color_palette("deep")         # 10 couleurs (défaut)
sns.color_palette("muted")        # Atténuées
sns.color_palette("bright")       # Vives
sns.color_palette("pastel")       # Pastel
sns.color_palette("dark")         # Sombres
sns.color_palette("colorblind")   # Accessible

# Palettes matplotlib
sns.color_palette("tab10")        # Tableau 10 couleurs
sns.color_palette("Set1")
sns.color_palette("Set2")
sns.color_palette("Paired")

# Nombre de couleurs
sns.color_palette("deep", 6)
sns.color_palette("Set2", 8)

# === PALETTES SÉQUENTIELLES ===

# Mono-couleur
sns.color_palette("Blues")
sns.color_palette("Greens")
sns.color_palette("Reds")
sns.color_palette("Oranges")
sns.color_palette("Purples")
sns.color_palette("Greys")

# Multi-couleurs
sns.color_palette("viridis")      # Perceptuellement uniforme
sns.color_palette("plasma")
sns.color_palette("inferno")
sns.color_palette("magma")
sns.color_palette("cividis")

# Inverser palette
sns.color_palette("Blues_r")
sns.color_palette("viridis_r")

# Nombre de couleurs dans palette
sns.color_palette("Blues", 5)
sns.color_palette("viridis", 10)

# === PALETTES DIVERGENTES ===

# Palettes centrées (pour données pos/neg)
sns.color_palette("RdBu")         # Rouge-Bleu
sns.color_palette("RdBu_r")       # Inversé
sns.color_palette("RdYlBu")       # Rouge-Jaune-Bleu
sns.color_palette("coolwarm")     # Froid-Chaud
sns.color_palette("Spectral")
sns.color_palette("seismic")

# === PALETTES PERSONNALISÉES ===

# Liste de couleurs
my_colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#FFA07A"]
sns.set_palette(my_colors)

# Palette depuis 2 couleurs
sns.blend_palette(["red", "blue"], n_colors=10)

# Palette circulaire (hue)
sns.color_palette("husl", 8)
sns.color_palette("hls", 8)

# Gradient personnalisé
sns.light_palette("navy")
sns.light_palette("navy", n_colors=6)
sns.light_palette("navy", reverse=True)

sns.dark_palette("purple")
sns.dark_palette("#69d", reverse=True, as_cmap=True)

# Divergente personnalisée
sns.diverging_palette(250, 10, n=9)
sns.diverging_palette(145, 280, s=85, l=25, n=7)

# === UTILISER PALETTES ===

# Dans un plot
palette = sns.color_palette("husl", 8)
sns.scatterplot(data=df, x="x", y="y", hue="cat", palette=palette)

# Comme cmap (heatmap, etc.)
cmap = sns.color_palette("viridis", as_cmap=True)
sns.heatmap(data=df, cmap=cmap)

# === VISUALISER PALETTES ===

# Afficher palette
pal = sns.color_palette("Set2", 8)
sns.palplot(pal)

# Toutes les palettes
for pal in ["deep", "muted", "bright", "pastel", "dark"]:
    sns.palplot(sns.color_palette(pal))
    plt.title(pal)
    plt.show()


[OK] FORMATAGE & EXPORT

# === SAUVEGARDER FIGURES ===

# Sauvegarder PNG
plt.savefig("plot.png")
plt.savefig("plot.png", dpi=300)
plt.savefig("plot.png", dpi=300, bbox_inches="tight")

# Sauvegarder PDF (vectoriel)
plt.savefig("plot.pdf")
plt.savefig("plot.pdf", bbox_inches="tight")

# Sauvegarder SVG (vectoriel)
plt.savefig("plot.svg")

# Sauvegarder avec transparence
plt.savefig("plot.png", transparent=True)

# Sauvegarder avec qualité spécifique
plt.savefig("plot.jpg", quality=95)

# === DIMENSIONS & RÉSOLUTION ===

# Taille figure
plt.figure(figsize=(12, 8))
sns.scatterplot(data=df, x="x", y="y")

# DPI (résolution)
plt.figure(dpi=100)              # Écran
plt.figure(dpi=300)              # Impression

# Avec seaborn (FacetGrid, etc.)
g = sns.FacetGrid(df, col="cat", height=4, aspect=1.5)

# === MARGES & ESPACEMENT ===

# Ajuster automatiquement
plt.tight_layout()

# Marges personnalisées
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)

# Espacement entre subplots
plt.subplots_adjust(hspace=0.3, wspace=0.3)

# === STYLE PUBLICATION ===

# Configuration publication
sns.set_theme(
    style="white",
    context="paper",
    font_scale=1.2,
    rc={
        "figure.figsize": (8, 6),
        "figure.dpi": 300,
        "savefig.dpi": 300,
        "font.family": "serif",
        "font.serif": ["Times New Roman"],
        "text.usetex": False,
        "axes.linewidth": 1.5,
        "axes.labelsize": 14,
        "axes.titlesize": 16,
        "xtick.labelsize": 12,
        "ytick.labelsize": 12,
        "legend.fontsize": 12,
        "legend.frameon": True,
        "legend.edgecolor": "black"
    }
)

# Supprimer spines (cadres)
ax = sns.scatterplot(data=df, x="x", y="y")
sns.despine()                    # Top et right
sns.despine(left=True)           # Tous sauf bottom
sns.despine(offset=10)           # Avec offset


[OK] EXEMPLES COMPLETS

# === EXEMPLE 1: ANALYSE DISTRIBUTION ===

import seaborn as sns
import matplotlib.pyplot as plt

# Charger données
df = sns.load_dataset("tips")

# Configuration
sns.set_theme(style="whitegrid", palette="muted")
fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# Histogramme avec KDE
sns.histplot(data=df, x="total_bill", kde=True, ax=axes[0, 0])
axes[0, 0].set_title("Distribution des Additions")

# Box plot par jour
sns.boxplot(data=df, x="day", y="total_bill", ax=axes[0, 1])
axes[0, 1].set_title("Additions par Jour")

# Violin plot par temps
sns.violinplot(data=df, x="time", y="total_bill", hue="sex", ax=axes[1, 0])
axes[1, 0].set_title("Additions par Moment")

# Count plot
sns.countplot(data=df, x="day", hue="time", ax=axes[1, 1])
axes[1, 1].set_title("Nombre de Repas")

plt.tight_layout()
plt.savefig("analyse_tips.png", dpi=300, bbox_inches="tight")
plt.show()

# === EXEMPLE 2: CORRÉLATIONS ===

import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# Charger données
df = sns.load_dataset("penguins").dropna()

# Matrice de corrélation
fig, axes = plt.subplots(1, 2, figsize=(16, 6))

# Heatmap corrélation
numeric_cols = ["bill_length_mm", "bill_depth_mm", 
                "flipper_length_mm", "body_mass_g"]
corr = df[numeric_cols].corr()

mask = np.triu(np.ones_like(corr, dtype=bool))
sns.heatmap(
    corr,
    mask=mask,
    annot=True,
    fmt=".2f",
    cmap="coolwarm",
    center=0,
    square=True,
    linewidths=1,
    cbar_kws={"shrink": 0.8},
    ax=axes[0]
)
axes[0].set_title("Matrice de Corrélation", fontsize=16, fontweight="bold")

# Clustermap
sns.clustermap(
    df[numeric_cols].corr(),
    annot=True,
    fmt=".2f",
    cmap="coolwarm",
    center=0,
    linewidths=1,
    figsize=(8, 8),
    cbar_pos=(0.02, 0.8, 0.03, 0.15)
)

plt.savefig("correlation_penguins.png", dpi=300, bbox_inches="tight")
plt.show()

# === EXEMPLE 3: PAIRPLOT AVANCÉ ===

import seaborn as sns
import matplotlib.pyplot as plt

# Charger données
df = sns.load_dataset("iris")

# Pairplot personnalisé
g = sns.pairplot(
    df,
    hue="species",
    diag_kind="kde",
    plot_kws={"alpha": 0.6, "s": 50, "edgecolor": "k"},
    diag_kws={"alpha": 0.7, "linewidth": 2},
    palette="Set2",
    height=2.5,
    corner=True  # Seulement triangle inférieur
)

g.fig.suptitle("Analyse Iris Dataset", y=1.02, fontsize=16, fontweight="bold")

# Personnaliser légende
g._legend.set_bbox_to_anchor((0.95, 0.5))
g._legend.set_title("Espèce", prop={"size": 12, "weight": "bold"})

plt.savefig("pairplot_iris.png", dpi=300, bbox_inches="tight")
plt.show()

# === EXEMPLE 4: TIME SERIES ===

import seaborn as sns
import matplotlib.pyplot as plt

# Charger données
flights = sns.load_dataset("flights")

# Pivot pour heatmap
flights_pivot = flights.pivot("month", "year", "passengers")

# Configuration
fig, axes = plt.subplots(2, 1, figsize=(14, 10))

# Heatmap
sns.heatmap(
    flights_pivot,
    annot=True,
    fmt="d",
    cmap="YlGnBu",
    linewidths=0.5,
    ax=axes[0],
    cbar_kws={"label": "Nombre de Passagers"}
)
axes[0].set_title("Passagers Aériens par Mois et Année", 
                  fontsize=14, fontweight="bold")

# Line plot
sns.lineplot(
    data=flights,
    x="year",
    y="passengers",
    hue="month",
    palette="tab10",
    linewidth=2,
    marker="o",
    ax=axes[1]
)
axes[1].set_title("Évolution du Trafic Aérien", fontsize=14, fontweight="bold")
axes[1].set_xlabel("Année", fontsize=12)
axes[1].set_ylabel("Passagers", fontsize=12)
axes[1].legend(title="Mois", bbox_to_anchor=(1.05, 1), loc="upper left")

plt.tight_layout()
plt.savefig("flights_analysis.png", dpi=300, bbox_inches="tight")
plt.show()

# === EXEMPLE 5: RÉGRESSION MULTIPLE ===

import seaborn as sns
import matplotlib.pyplot as plt

# Charger données
tips = sns.load_dataset("tips")

# FacetGrid avec régressions
g = sns.lmplot(
    data=tips,
    x="total_bill",
    y="tip",
    hue="time",
    col="day",
    col_wrap=2,
    height=4,
    aspect=1.2,
    scatter_kws={"alpha": 0.6, "s": 50},
    line_kws={"linewidth": 2}
)

g.set_axis_labels("Addition Totale ($)", "Pourboire ($)")
g.set_titles("{col_name}")
g.fig.suptitle("Relation Addition-Pourboire par Jour et Moment", 
               y=1.02, fontsize=16, fontweight="bold")

plt.savefig("regression_tips.png", dpi=300, bbox_inches="tight")
plt.show()

# === EXEMPLE 6: DISTRIBUTION JOINTE ===

import seaborn as sns
import matplotlib.pyplot as plt

# Charger données
diamonds = sns.load_dataset("diamonds").sample(1000)

# Joint plot avec hexbin
g = sns.jointplot(
    data=diamonds,
    x="carat",
    y="price",
    kind="hex",
    height=8,
    ratio=5,
    marginal_kws={"bins": 30, "fill": True},
    joint_kws={"gridsize": 30, "cmap": "Blues"}
)

g.set_axis_labels("Poids (Carats)", "Prix ($)", fontsize=12)
g.fig.suptitle("Relation Poids-Prix des Diamants", 
               y=1.02, fontsize=14, fontweight="bold")

# Ajouter ligne de régression
g.plot_joint(sns.regplot, scatter=False, color="red", line_kws={"linewidth": 2})

plt.savefig("jointplot_diamonds.png", dpi=300, bbox_inches="tight")
plt.show()

# === EXEMPLE 7: CATPLOT COMPLEXE ===

import seaborn as sns
import matplotlib.pyplot as plt

# Charger données
tips = sns.load_dataset("tips")

# Catplot avec facettes
g = sns.catplot(
    data=tips,
    x="day",
    y="total_bill",
    hue="sex",
    col="time",
    kind="violin",
    split=True,
    height=5,
    aspect=1.2,
    palette="Set2",
    inner="quartile"
)

g.set_axis_labels("Jour", "Addition ($)")
g.set_titles("{col_name}")
g.fig.suptitle("Distribution des Additions", y=1.02, fontsize=16, fontweight="bold")

plt.savefig("catplot_tips.png", dpi=300, bbox_inches="tight")
plt.show()


[OK] ASTUCES & OPTIMISATIONS

# === PERFORMANCES ===

# Échantillonner gros datasets
df_sample = df.sample(n=10000)  # 10k lignes
df_sample = df.sample(frac=0.1) # 10% des données

# Utiliser hexbin au lieu de scatter
sns.jointplot(data=large_df, x="x", y="y", kind="hex")

# Désactiver KDE pour rapidité
sns.histplot(data=df, x="col", kde=False)

# Utiliser datashader pour très gros datasets
# pip install datashader

# === ÉVITER WARNINGS ===

# Supprimer warnings pandas
import warnings
warnings.filterwarnings('ignore')

# Copier DataFrame avant modification
df_copy = df.copy()

# === GESTION MISSING VALUES ===

# Supprimer NaN avant plot
df_clean = df.dropna(subset=["col1", "col2"])
sns.scatterplot(data=df_clean, x="col1", y="col2")

# Ou dans le plot directement
sns.scatterplot(data=df.dropna(), x="col1", y="col2")

# === ORDRE PERSONNALISÉ ===

# Catégories dans ordre spécifique
order = ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi"]
sns.boxplot(data=df, x="jour", y="valeur", order=order)

# Trier par valeur
order = df.groupby("category")["value"].mean().sort_values().index
sns.barplot(data=df, x="category", y="value", order=order)

# === COMBINER AVEC PANDAS ===

# Pipeline complet
(df
 .query("age > 18")
 .groupby("category")["value"]
 .mean()
 .plot(kind="bar"))

# Avec seaborn
df_agg = df.groupby("category").agg({"value": ["mean", "std"]}).reset_index()
sns.barplot(data=df_agg, x="category", y=("value", "mean"))

# === ANNOTATIONS AUTOMATIQUES ===

# Annoter barplot
ax = sns.barplot(data=df, x="category", y="value")
for container in ax.containers:
    ax.bar_label(container, fmt="%.1f")

# Annoter heatmap avec valeurs
sns.heatmap(data=df, annot=True, fmt=".2f")

# === SOUS-ÉCHANTILLONNAGE INTELLIGENT ===

# Garder outliers + échantillon
def smart_sample(df, col, n=1000, keep_outliers=True):
    if keep_outliers:
        Q1 = df[col].quantile(0.25)
        Q3 = df[col].quantile(0.75)
        IQR = Q3 - Q1
        outliers = df[(df[col] < Q1 - 1.5*IQR) | (df[col] > Q3 + 1.5*IQR)]
        normal = df[(df[col] >= Q1 - 1.5*IQR) & (df[col] <= Q3 + 1.5*IQR)]
        return pd.concat([outliers, normal.sample(n=min(n, len(normal)))])
    return df.sample(n=min(n, len(df)))


[OK] INTÉGRATION AVEC AUTRES OUTILS

# === PLOTLY (INTERACTIF) ===

import plotly.express as px

# Convertir style seaborn vers plotly
df = sns.load_dataset("iris")
fig = px.scatter(df, x="sepal_length", y="sepal_width", 
                 color="species", template="seaborn")
fig.show()

# === ALTAIR ===

import altair as alt

# Style similaire seaborn
chart = alt.Chart(df).mark_point().encode(
    x="x:Q",
    y="y:Q",
    color="category:N"
).properties(
    width=600,
    height=400
).configure_mark(
    opacity=0.6
)

# === PANDAS STYLING ===

# Heatmap dans DataFrame
df.style.background_gradient(cmap="coolwarm")

# === JUPYTER NOTEBOOKS ===

# Affichage inline
%matplotlib inline

# Figures interactives
%matplotlib widget

# Haute résolution
%config InlineBackend.figure_format = 'retina'

# Taille par défaut
plt.rcParams["figure.figsize"] = (12, 8)


[OK] DEBUGGING & TROUBLESHOOTING

# === PROBLÈMES COURANTS ===

# Problème: "No numeric data to plot"
# Solution: Vérifier types de données
print(df.dtypes)
df["col"] = pd.to_numeric(df["col"], errors="coerce")

# Problème: Légende trop grande
# Solution: Réduire ou déplacer
ax.legend(fontsize=8)
ax.legend(bbox_to_anchor=(1.05, 1), loc="upper left")

# Problème: Labels coupés
# Solution: Ajuster layout
plt.tight_layout()
plt.savefig("plot.png", bbox_inches="tight")

# Problème: Trop de catégories
# Solution: Filtrer ou regrouper
top_cats = df["category"].value_counts().head(10).index
df_filtered = df[df["category"].isin(top_cats)]

# Problème: Couleurs pas distinguables
# Solution: Utiliser palette colorblind
sns.set_palette("colorblind")

# Problème: Plot trop lent
# Solution: Échantillonner données
df_sample = df.sample(frac=0.1)

# === VÉRIFICATIONS ===

# Vérifier données avant plot
print(df.info())
print(df.describe())
print(df.isnull().sum())

# Vérifier palette actuelle
print(sns.color_palette())

# Vérifier style actuel
print(plt.rcParams["figure.figsize"])
print(plt.rcParams["font.size"])

# === RESET ===

# Réinitialiser matplotlib
plt.rcdefaults()

# Réinitialiser seaborn
sns.reset_defaults()
sns.reset_orig()

# Fermer toutes les figures
plt.close("all")


[OK] BONNES PRATIQUES

# 1. Toujours définir style au début
sns.set_theme(style="whitegrid", palette="muted")

# 2. Utiliser figsize approprié
fig, ax = plt.subplots(figsize=(10, 6))

# 3. Labels clairs et titres
ax.set_title("Titre Descriptif", fontsize=14, fontweight="bold")
ax.set_xlabel("Variable X", fontsize=12)
ax.set_ylabel("Variable Y", fontsize=12)

# 4. Légendes positionnées correctement
ax.legend(bbox_to_anchor=(1.05, 1), loc="upper left")

# 5. Sauvegarder haute résolution
plt.savefig("plot.png", dpi=300, bbox_inches="tight")

# 6. Couleurs adaptées au contexte
# Publication: palette colorblind
# Présentation: couleurs vives
# Rapport: couleurs professionnelles

# 7. Ne pas surcharger
# Max 5-7 catégories dans hue
# Max 2x2 facettes si possible

# 8. Annotations utiles
# Ajouter moyennes, seuils, références

# 9. Tester sur différents écrans
# Vérifier lisibilité texte
# Vérifier contraste couleurs

# 10. Documenter code
# Commenter choix de visualisation
# Noter packages versions


[OK] RESSOURCES

# Documentation officielle
# https://seaborn.pydata.org/

# Galerie d'exemples
# https://seaborn.pydata.org/examples/index.html

# Tutoriels
# https://seaborn.pydata.org/tutorial.html

# API Reference
# https://seaborn.pydata.org/api.html

# Cheatsheet visuelle
# https://s3.amazonaws.com/assets.datacamp.com/blog_assets/Python_Seaborn_Cheat_Sheet.pdf

# Formation complète
# Real Python - Seaborn Tutorial
# DataCamp - Seaborn Courses

# GitHub
# https://github.com/mwaskom/seaborn

# Stack Overflow
# Tag: [seaborn]


[OK] VERSIONS & COMPATIBILITÉ

# Versions Seaborn
# 0.11.x: Dernière avec anciennes APIs
# 0.12.x+: Nouvelles APIs (recommandé)

# Dépendances
# matplotlib >= 3.1
# pandas >= 0.25
# numpy >= 1.15

# Python
# Python 3.7+

# Vérifier versions
import seaborn as sns
import matplotlib
import pandas as pd
import numpy as np

print(f"Seaborn: {sns.__version__}")
print(f"Matplotlib: {matplotlib.__version__}")
print(f"Pandas: {pd.__version__}")
print(f"NumPy: {np.__version__}")


# FIN DU CHEATSHEET SEABORN