Seaborn

Tutorial Completo di Seaborn con Esempi

Seaborn

Seaborn è una libreria di visualizzazione dati Python basata su Matplotlib. Fornisce un'interfaccia di alto livello per creare visualizzazioni statistiche attraenti e informative.

Indice

  1. Installazione e Importazione

  2. Configurazione e Stili

  3. Tipi di Grafici

    • Relational Plots

    • Categorical Plots

    • Distribution Plots

    • Regression Plots

    • Matrix Plots

  4. Personalizzazione

  5. Temi e Contesti

  6. Esempi Pratici

  7. Integrazione con Pandas

Risorse Utili

  1. Documentazione Ufficiale: https://seaborn.pydata.org/

  2. Galleria Esempi: https://seaborn.pydata.org/examples/index.html

  3. Tutorial: https://seaborn.pydata.org/tutorial.html

  4. Color Palettes: https://seaborn.pydata.org/tutorial/color_palettes.html

1. Installazione e Importazione

Installazione

pip install seaborn
# oppure
conda install seaborn

Importazione

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

# Per i notebook Jupyter
%matplotlib inline

2. Configurazione e Stili

# Impostare lo stile di Seaborn
sns.set_theme(style="whitegrid")  # whitegrid, darkgrid, white, dark, ticks

# Caricare dataset di esempio
tips = sns.load_dataset("tips")
iris = sns.load_dataset("iris")
titanic = sns.load_dataset("titanic")
flights = sns.load_dataset("flights")

# Visualizzare i primi dati
print(tips.head())

3. Tipi di Grafici

Relational Plots (relplot)

# Scatter plot con relplot
sns.relplot(
    data=tips,
    x="total_bill", 
    y="tip", 
    hue="smoker",  # Colore per categoria
    style="time",  # Stile per categoria
    size="size",   # Dimensione punti
    sizes=(40, 200),  # Range dimensioni
    alpha=0.7
)
plt.title("Relazione tra Conto e Mancia")
plt.show()

# Line plot con relplot
sns.relplot(
    data=flights,
    x="year", 
    y="passengers", 
    kind="line",  # Tipo line plot
    hue="month",
    style="month",
    markers=True,
    dashes=False
)
plt.title("Passeggeri per Anno e Mese")
plt.xticks(rotation=45)
plt.show()

Categorical Plots (catplot)

# Box plot
sns.catplot(
    data=tips, 
    x="day", 
    y="total_bill", 
    hue="sex",
    kind="box",
    height=6,
    aspect=1.5
)
plt.title("Distribuzione Conto per Giorno e Sesso")
plt.show()

# Violin plot
sns.catplot(
    data=tips, 
    x="day", 
    y="total_bill", 
    hue="sex",
    kind="violin",
    split=True,  # Dividi i violini
    height=6,
    aspect=1.5
)
plt.title("Distribuzione Conto (Violin Plot)")
plt.show()

# Bar plot
sns.catplot(
    data=tips, 
    x="day", 
    y="total_bill", 
    hue="sex",
    kind="bar",
    ci="sd",  # Deviazione standard invece di intervallo confidenza
    height=6,
    aspect=1.5
)
plt.title("Conto Medio per Giorno e Sesso")
plt.show()

# Count plot
sns.catplot(
    data=tips, 
    x="day", 
    hue="sex",
    kind="count",
    height=6,
    aspect=1.5
)
plt.title("Conteggio Pasti per Giorno e Sesso")
plt.show()

Distribution Plots

# Histogram con KDE
sns.histplot(
    data=tips, 
    x="total_bill", 
    hue="sex", 
    element="step",  # step, bars, poly
    stat="density",  # count, frequency, density, probability
    common_norm=False,  # Normalizza separatamente
    kde=True  # Aggiungi Kernel Density Estimate
)
plt.title("Distribuzione del Conto per Sesso")
plt.show()

# KDE plot
sns.kdeplot(
    data=tips, 
    x="total_bill", 
    hue="sex", 
    fill=True,
    alpha=0.5,
    common_norm=False
)
plt.title("Densità del Conto per Sesso")
plt.show()

# Joint plot (scatter + histogram)
g = sns.jointplot(
    data=tips, 
    x="total_bill", 
    y="tip", 
    hue="smoker",
    kind="scatter",  # scatter, reg, resid, kde, hex
    marginal_kws=dict(bins=25, fill=True)
)
g.fig.suptitle("Relazione Conto-Mancia con Distribuzioni Marginali")
plt.tight_layout()
plt.show()

# Pair plot (matrice di scatter plots)
g = sns.pairplot(
    iris, 
    hue="species", 
    palette="viridis",
    diag_kind="hist",  # hist, kde, None
    corner=False  # True per triangolo inferiore
)
g.fig.suptitle("Pair Plot del Dataset Iris")
plt.tight_layout()
plt.show()

Regression Plots (lmplot)

# Linear regression plot
sns.lmplot(
    data=tips, 
    x="total_bill", 
    y="tip", 
    hue="smoker",
    col="time",  # Facet per colonne
    row="sex",   # Facet per righe
    height=4,
    aspect=1.2,
    ci=95  # Intervallo di confidenza
)
plt.suptitle("Regressione Lineare: Conto vs Mancia")
plt.tight_layout()
plt.show()

# Regressione polinomiale
sns.lmplot(
    data=tips, 
    x="total_bill", 
    y="tip", 
    order=2,  # Grado polinomiale
    scatter_kws={"alpha": 0.5},
    line_kws={"color": "red"}
)
plt.title("Regressione Polinomiale (Grado 2)")
plt.show()

# Robust regression (resistente agli outliers)
sns.lmplot(
    data=tips, 
    x="total_bill", 
    y="tip", 
    robust=True,
    ci=None
)
plt.title("Regressione Robusta")
plt.show()

Matrix Plots

# Heatmap
# Preparare i dati
flights_pivot = flights.pivot("month", "year", "passengers")

plt.figure(figsize=(10, 8))
sns.heatmap(
    flights_pivot, 
    annot=True,      # Mostra valori
    fmt="d",         # Formato interi
    cmap="YlOrRd",   # Colormap
    linewidths=0.5,
    cbar_kws={"label": "Passeggeri"}
)
plt.title("Heatmap: Passeggeri per Mese e Anno")
plt.tight_layout()
plt.show()

# Cluster map
iris_numeric = iris.drop("species", axis=1)
g = sns.clustermap(
    iris_numeric, 
    standard_scale=1,  # Normalizza per righe (1) o colonne (0)
    cmap="viridis",
    figsize=(8, 8)
)
plt.suptitle("Cluster Map del Dataset Iris")
plt.show()

# Correlation heatmap
corr = tips.corr(numeric_only=True)
mask = np.triu(np.ones_like(corr, dtype=bool))  # Maschera triangolo superiore

plt.figure(figsize=(8, 6))
sns.heatmap(
    corr, 
    mask=mask,
    annot=True, 
    cmap="coolwarm", 
    center=0,
    square=True,
    linewidths=0.5
)
plt.title("Matrice di Correlazione")
plt.tight_layout()
plt.show()

4. Personalizzazione

# Personalizzazione avanzata
plt.figure(figsize=(10, 6))
ax = sns.barplot(
    data=tips, 
    x="day", 
    y="total_bill", 
    hue="sex",
    palette="Set2",  # Palette colori
    saturation=0.8,  # Saturazione colori
    errcolor=".2",   # Colore error bars
    errwidth=1.5,    # Spessore error bars
    capsize=0.1      # Dimensione caps
)

# Personalizzare ulteriormente con matplotlib
plt.title("Conto Medio per Giorno e Sesso", fontsize=16, fontweight="bold")
plt.xlabel("Giorno", fontsize=12)
plt.ylabel("Conto Medio ($)", fontsize=12)
plt.legend(title="Sesso", title_fontsize=12, fontsize=11)

# Aggiungere valori sulle barre
for container in ax.containers:
    ax.bar_label(container, fmt='%.1f', padding=3)

plt.tight_layout()
plt.show()

5. Temi e Contesti

# Cambiare tema e contesto
themes = ["whitegrid", "darkgrid", "white", "dark", "ticks"]
contexts = ["paper", "notebook", "talk", "poster"]

for i, theme in enumerate(themes, 1):
    plt.figure(figsize=(6, 4))
    sns.set_theme(style=theme)
    sns.histplot(data=tips, x="total_bill", kde=True)
    plt.title(f"Tema: {theme}")
    plt.tight_layout()
    plt.show()

# Ripristinare tema predefinito
sns.set_theme(style="whitegrid")

# Cambiare contesto (dimensione elementi)
sns.set_context("paper")  # Elementi più piccoli
sns.histplot(data=tips, x="total_bill", kde=True)
plt.title("Contesto: Paper")
plt.show()

sns.set_context("poster")  # Elementi più grandi
sns.histplot(data=tips, x="total_bill", kde=True)
plt.title("Contesto: Poster")
plt.show()

# Ripristinare contesto predefinito
sns.set_context("notebook")

6. Esempi Pratici

Analisi Dataset Titanic

# Analisi esplorativa Titanic
plt.figure(figsize=(12, 10))

# Sopravvivenza per classe e sesso
plt.subplot(2, 2, 1)
sns.barplot(data=titanic, x="class", y="survived", hue="sex", ci=None)
plt.title("Tasso di Sopravvivenza per Classe e Sesso")
plt.ylabel("Tasso di Sopravvivenza")

# Distribuzione età per sopravvivenza e sesso
plt.subplot(2, 2, 2)
sns.histplot(data=titanic, x="age", hue="survived", element="step", 
             stat="density", common_norm=False, kde=True)
plt.title("Distribuzione Età per Sopravvivenza")
plt.xlabel("Età")

# Sopravvivenza per porto di imbarco
plt.subplot(2, 2, 3)
sns.countplot(data=titanic, x="embarked", hue="survived")
plt.title("Sopravvivenza per Porto di Imbarco")
plt.xlabel("Porto di Imbarco")

# Distribuzione tariffe per classe
plt.subplot(2, 2, 4)
sns.boxplot(data=titanic, x="class", y="fare")
plt.title("Distribuzione Tariffe per Classe")
plt.yscale("log")  # Scala logaritmica per meglio visualizzare outliers

plt.tight_layout()
plt.show()

Multiplot con FacetGrid

# Creare una griglia di subplots
g = sns.FacetGrid(tips, col="time", row="smoker", height=4, aspect=1.2)
g.map_dataframe(sns.scatterplot, x="total_bill", y="tip", hue="sex", alpha=0.7)
g.add_legend()
g.fig.suptitle("Relazione Conto-Mancia per Time e Smoker", y=1.02)
plt.tight_layout()
plt.show()

# Usare PairGrid per personalizzazione avanzata
g = sns.PairGrid(iris, hue="species", palette="viridis")
g.map_upper(sns.scatterplot, alpha=0.8)  # Triangolo superiore: scatter
g.map_lower(sns.kdeplot, fill=True)     # Triangolo inferiore: KDE
g.map_diag(sns.histplot, kde=True)      # Diagonale: histogram con KDE
g.add_legend()
g.fig.suptitle("PairGrid Personalizzato per Dataset Iris", y=1.02)
plt.tight_layout()
plt.show()

7. Integrazione con Pandas

# Creare dataset di esempio
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2023-12-31', freq='D')
df = pd.DataFrame({
    'date': dates,
    'sales': np.random.normal(1000, 200, len(dates)),
    'temperature': np.random.normal(20, 5, len(dates)),
    'region': np.random.choice(['North', 'South', 'East', 'West'], len(dates)),
    'product': np.random.choice(['A', 'B', 'C'], len(dates))
})

# Aggiungere stagionalità
df['sales'] = df['sales'] + 100 * np.sin(2 * np.pi * df.date.dt.dayofyear / 365)

# Aggiungere giorno della settimana e mese
df['day_of_week'] = df['date'].dt.day_name()
df['month'] = df['date'].dt.month_name()

# Analisi vendite con Seaborn e Pandas
plt.figure(figsize=(15, 10))

# Andamento vendite nel tempo
plt.subplot(2, 2, 1)
df_weekly = df.resample('W', on='date')['sales'].mean().reset_index()
sns.lineplot(data=df_weekly, x='date', y='sales')
plt.title('Vendite Medie Settimanali')
plt.xticks(rotation=45)

# Vendite per regione e prodotto
plt.subplot(2, 2, 2)
sns.barplot(data=df, x='region', y='sales', hue='product', ci=None)
plt.title('Vendite per Regione e Prodotto')

# Distribuzione vendite per giorno della settimana
plt.subplot(2, 2, 3)
day_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
sns.boxplot(data=df, x='day_of_week', y='sales', order=day_order)
plt.title('Distribuzione Vendite per Giorno della Settimana')
plt.xticks(rotation=45)

# Correlazione tra temperatura e vendite
plt.subplot(2, 2, 4)
sns.scatterplot(data=df, x='temperature', y='sales', hue='region', alpha=0.6)
plt.title('Correlazione: Temperatura vs Vendite')

plt.tight_layout()
plt.show()

Dashboard Completa

# Creare una dashboard completa
fig = plt.figure(figsize=(18, 12))

# Definire la griglia
gs = fig.add_gridspec(3, 3)

# Heatmap correlazione
ax1 = fig.add_subplot(gs[0, 0])
numeric_df = df[['sales', 'temperature']].corr(numeric_only=True)
sns.heatmap(numeric_df, annot=True, cmap='coolwarm', center=0, ax=ax1)
ax1.set_title('Matrice di Correlazione')

# Distribuzione vendite
ax2 = fig.add_subplot(gs[0, 1])
sns.histplot(data=df, x='sales', kde=True, ax=ax2)
ax2.set_title('Distribuzione Vendite')

# Vendite per mese
ax3 = fig.add_subplot(gs[0, 2])
month_order = ['January', 'February', 'March', 'April', 'May', 'June', 
               'July', 'August', 'September', 'October', 'November', 'December']
monthly_sales = df.groupby('month')['sales'].mean().reindex(month_order)
sns.barplot(x=monthly_sales.index, y=monthly_sales.values, ax=ax3)
ax3.set_title('Vendite Medie per Mese')
ax3.tick_params(axis='x', rotation=45)

# Andamento temporale
ax4 = fig.add_subplot(gs[1, :])
df_daily = df.resample('D', on='date')['sales'].mean().reset_index()
sns.lineplot(data=df_daily, x='date', y='sales', ax=ax4)
ax4.set_title('Andamento Vendite Giornaliere')
ax4.tick_params(axis='x', rotation=45)

# Violin plot per regione
ax5 = fig.add_subplot(gs[2, 0])
sns.violinplot(data=df, x='region', y='sales', ax=ax5)
ax5.set_title('Distribuzione Vendite per Regione')

# Box plot per prodotto
ax6 = fig.add_subplot(gs[2, 1])
sns.boxplot(data=df, x='product', y='sales', ax=ax6)
ax6.set_title('Distribuzione Vendite per Prodotto')

# Scatter plot temperatura vs vendite
ax7 = fig.add_subplot(gs[2, 2])
sns.scatterplot(data=df, x='temperature', y='sales', hue='region', alpha=0.6, ax=ax7)
ax7.set_title('Temperatura vs Vendite')

plt.tight_layout()
plt.suptitle('Dashboard Analisi Vendite Completa', fontsize=16, fontweight='bold', y=0.98)
plt.show()


Last updated