Open In Colab

Seaborn#

Elevare la Visualizzazione dei Dati con Seaborn#

Nel capitolo precedente, abbiamo esaminato Matplotlib, una libreria estremamente versatile per la visualizzazione dei dati in Python. Ora esamineremo le funzionalità di Seabonrn. Seaborn, che si basa su Matplotlib, arricchisce l’esperienza di visualizzazione dei dati offrendo una gamma più ampia e specializzata di opzioni grafiche, particolarmente utili nel campo della data science.

Il vero punto di forza di Seaborn è la sua capacità di migliorare non solo l’aspetto estetico dei grafici ma anche di facilitare la creazione di visualizzazioni più complesse. Questo rende il processo più diretto e intuitivo. La libreria è dotata di un’ampia varietà di strumenti, dalle mappe di calore ai grafici a violino, permettendo agli utenti di esplorare e rappresentare i dati in modi innovativi e informativi.

Per chi vuole approfondire ulteriormente, i tutorial presenti sul sito ufficiale di Seaborn sono una risorsa preziosa e facilmente accessibile.

Preparazione del Notebook#

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
import arviz as az
%config InlineBackend.figure_format = 'retina'
RANDOM_SEED = 42
rng = np.random.default_rng(RANDOM_SEED)
az.style.use("arviz-darkgrid")
sns.set_theme(palette="colorblind")

Visualizzare la distribuzione dei dati#

Vediamo alcuni esempi pratici per scoprire come Seaborn possa trasformare il modo in cui visualizziamo i dati.

Consideriamo nuovamente i dati Palmer penguin.

df = pd.read_csv("../data/penguins.csv")

Una delle forme di visualizzazione più comuni e informative nel campo dell’analisi dei dati è l’istogramma, e la sua variante più sofisticata, l’istogramma lisciato. Vediamo dunque come generare istogrammi che, per il DataFrame df, sono stratificati sia in base alla specie che al genere dei pinguini.

sns.displot(
    df, x="flipper_length_mm", col="species", row="sex",
    binwidth=3, height=3, facet_kws=dict(margin_titles=True),
);
Hide code cell output
/Users/corrado/opt/anaconda3/envs/pymc_env/lib/python3.11/site-packages/seaborn/axisgrid.py:123: UserWarning: The figure layout has changed to tight
  self._figure.tight_layout(*args, **kwargs)
../_images/3501e1ad6969ae755927e8706528f4334684551f9f76dec07197a7be58d71f1c.png

Generiamo la stessa figura usando questa volta gli istogrammi lisciati.

sns.displot(
    df, x="flipper_length_mm", col="species", row="sex",
    height=3, kind="kde", facet_kws=dict(margin_titles=True),
);
/Users/corrado/opt/anaconda3/envs/pymc_env/lib/python3.11/site-packages/seaborn/axisgrid.py:123: UserWarning: The figure layout has changed to tight
  self._figure.tight_layout(*args, **kwargs)
../_images/7009dbb261c71b8f89352de1e11ff79001950ef44f92756494d111bec7d9af3b.png

Visualizzazione di dati categoriali#

Consideriamo ora il caso in cui si vuole rappresentare la relazione tra una variabile numerica e una o più variabili categoriali.

Consideriamo, ad esempio, la massa corporea in relazione alla specie, differenziando le osservazioni per genere. Creiamo il grafico utilizzando i boxplot.

sns.catplot(df, x="species", y="body_mass_g", hue="sex", kind="box")
/Users/corrado/opt/anaconda3/envs/pymc_env/lib/python3.11/site-packages/seaborn/axisgrid.py:123: UserWarning: The figure layout has changed to tight
  self._figure.tight_layout(*args, **kwargs)
<seaborn.axisgrid.FacetGrid at 0x16ea65690>
../_images/dcb843195bbb23c4edd2773720a3bdcccde59327a91f1187d03c45d972e816d5.png

Dai diagrammi risulta evidente che i pinguini maschi hanno un peso maggiore rispetto alle femmine in tutte le specie, e che i pinguini Gentoo hanno un peso superiore rispetto ad Adelie e Chinstrap.

Come alternativa, possiamo utilizzare il violinplot per la rappresentazione grafica dei dati.

sns.catplot(df, x="species", y="body_mass_g", hue="sex", kind="violin")
/Users/corrado/opt/anaconda3/envs/pymc_env/lib/python3.11/site-packages/seaborn/axisgrid.py:123: UserWarning: The figure layout has changed to tight
  self._figure.tight_layout(*args, **kwargs)
<seaborn.axisgrid.FacetGrid at 0x16eac4150>
../_images/eb94f03ec2a8b36092d57b85a302c809ba56cafaf5fc3e13435c7d2fe3ffd7e6.png

Relazioni tra variabili#

Calcoliamo la correlazione tra le variabili.

vars = ["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"]
corr_matrix = df[vars].corr().round(2)
corr_matrix
bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
bill_length_mm 1.00 -0.24 0.66 0.60
bill_depth_mm -0.24 1.00 -0.58 -0.47
flipper_length_mm 0.66 -0.58 1.00 0.87
body_mass_g 0.60 -0.47 0.87 1.00

Queste informazioni possono essere comunicate in forma più diretta se usiamo una rappresentazione grafica.

sns.heatmap(corr_matrix, annot=True, linecolor="white", linewidths=5);
../_images/23a0f308406d00e40e2bf2ea8284876e732d8a9a63d1183625c0f13ab26dc63d.png

La lunghezza della pinna e la massa corporea mostrano un forte legame, con una correlazione di 0.87. Ciò indica che i pinguini con pinne più lunghe tendono a pesare di più.

Di seguito è riportato un esempio di diagramma a dispersione che illustra questa relazione.

sns.scatterplot(df, x="bill_length_mm", y="bill_depth_mm", hue="species");
../_images/0d066af7de6fa890bb176ce7d1aae94f00ec8b9eb0877df5a51632291e7aee33.png

Evidentemente, le osservazioni delle tre specie formano cluster distinti. Per ciascuna specie, la lunghezza e la larghezza del becco presentano un intervallo specifico.

Spesso è vantaggioso creare grafici separati in base a diverse dimensioni dei dati; nell’esempio seguente, suddividiamo i dati in base all’isola di appartenenza.

g = sns.relplot(
    data=df,
    x="bill_length_mm",
    y="bill_depth_mm",
    hue="species",
    row="sex",
    col="island",
    height=3,
    facet_kws=dict(margin_titles=True),
)
g.set_axis_labels(
    "Bill length (mm)",
    "Bill depth (mm)",
);
/Users/corrado/opt/anaconda3/envs/pymc_env/lib/python3.11/site-packages/seaborn/axisgrid.py:123: UserWarning: The figure layout has changed to tight
  self._figure.tight_layout(*args, **kwargs)
../_images/8a0b598ae70f71f1c66d0423b0f9dc7421c1621d4604f5130e6b7baaa8b93072.png
%load_ext watermark
%watermark -n -u -v -iv -w -m
Last updated: Mon Jan 29 2024

Python implementation: CPython
Python version       : 3.11.7
IPython version      : 8.19.0

Compiler    : Clang 16.0.6 
OS          : Darwin
Release     : 23.3.0
Machine     : x86_64
Processor   : i386
CPU cores   : 8
Architecture: 64bit

numpy     : 1.26.2
seaborn   : 0.13.0
matplotlib: 3.8.2
arviz     : 0.17.0
pandas    : 2.1.4

Watermark: 2.4.3