Vai al contenuto principale

Analisi esplorativa delle birre artigianali: Data Profiling

In questo tutorial imparerai l'analisi esplorativa dei dati (EDA) in Python e, più nello specifico, il data profiling con pandas.
Aggiornato 29 set 2026  · 14 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

Nota della redazione: Jean-Nicholas Hould è un data scientist presso Intel Security a Montreal e sul suo blog insegna come iniziare con la data science.

L’analisi esplorativa dei dati (EDA) è un approccio statistico che mira a scoprire e riassumere un dataset. In questa fase del processo di data science, vuoi esplorare la struttura del tuo dataset, le variabili e le loro relazioni.

In questo post ti concentrerai su un aspetto dell’analisi esplorativa dei dati: il data profiling.

Il data profiling consiste nel riassumere il tuo dataset tramite statistiche descrittive. Vuoi usare una pletora di misurazioni per comprendere meglio il tuo dataset. Tipi di dato, valori mancanti, media, mediana e deviazione standard sono solo alcuni dei molti elementi che dovrai raccogliere quando fai il profiling di un dataset. L’obiettivo del data profiling è avere una solida comprensione dei dati per poter poi iniziare a interrogarli e visualizzarli in vari modi.

Sapere da dove provengono i tuoi dati

Prima di lanciarti in qualunque EDA, dovresti sapere il più possibile sulla provenienza dei dati che stai analizzando. Devi capire come sono stati raccolti e come sono stati elaborati. Ci sono trasformazioni pregresse sui dati che potrebbero influenzare la tua analisi?

Dovresti essere in grado di rispondere a queste domande sul tuo dataset:

  • Come è stato raccolto?
  • È un campione?
  • È stato campionato correttamente?
  • Il dataset è stato trasformato in qualche modo?
  • Ci sono problemi noti sul dataset?

Se non capisci da dove provengono i dati, sarà difficile trarre conclusioni significative dal dataset. Inoltre rischi di commettere errori di analisi molto importanti.

Inoltre, dovresti assicurarti che il dataset sia strutturato in modo standardizzato. Il formato consigliato è la terza forma normale, anche chiamata tidy data. Un dataset “tidy” ha le seguenti caratteristiche:

  • Ogni variabile costituisce una colonna e contiene valori
  • Ogni osservazione costituisce una riga
  • Ogni tipo di unità osservazionale costituisce una tabella

Rispettare questo formato standardizzato velocizzerà la tua analisi, poiché è compatibile con molti strumenti e librerie.

Data Profiling

In questo post userai un dataset di birre artigianali dal sito CraftCans. Questo dataset contiene solo dati su birre in lattina provenienti da birrifici degli Stati Uniti. Non è chiaro dal sito se questo dataset riporti ogni singola birra in lattina prodotta negli USA o meno. Per sicurezza, considererai questo dataset come un campione che può contenere bias.

Ecco la struttura dei dataset che userai:

Beers:

  • ID: Identificatore univoco della birra.
  • Name: Nome della birra.
  • ABV: Gradazione alcolica per volume della birra.
  • IBU: International Bittering Units della birra.
  • Style: Stile della birra.
  • Ounces: Once di birra.

Breweries:

  • ID: Identificatore univoco del birrificio.
  • Name: Nome del birrificio.
  • City: Città in cui si trova il birrificio.
  • State: Stato in cui si trova il birrificio.

Tipi di dato

Il primo passo è capire la composizione del tuo dataset.

Con quali variabili hai a che fare?

In genere puoi classificare i dati in una di queste categorie:

  • Numerici
  • Categoriali
  • Testo
  • Data

Per prima cosa importerai i dataset che puoi trovare in questo repository con la funzione from_csv di pandas. Inoltre unirai i dataset beers e breweries per facilitare l’analisi più avanti.

import pandas as pd

beers = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_beers.csv")
breweries = pd.DataFrame.from_csv("https://raw.githubusercontent.com/nickhould/craft-beers-dataset/master/data/craftcans_breweries.csv")

beers_and_breweries = pd.merge(beers, 
                               breweries, 
                               how='inner', 
                               left_on="brewery_id", 
                               right_on="id", 
                               sort=True,
                               suffixes=('_beer', '_brewery'))

Con la libreria pandas puoi eseguire la funzione dtypes per elencare ogni colonna e i rispettivi tipi di dato.

beers.dtypes

Che ti restituisce il seguente risultato:

abv           float64
ibu           float64
id              int64
name           object
style          object
brewery_id      int64
ounces        float64
dtype: object

Come puoi vedere sopra, questa funzione non raggruppa in modo pulito i diversi tipi di dato. I vari tipi numerici (float64 e int64) non sono raggruppati in un’unica categoria come vorremmo. Inoltre, alcune colonne sono indicate come object, il che non è molto utile.

Per aggirare questo problema, puoi costruire una tua funzione che determini la categoria di ciascuna colonna in un DataFrame.

def get_var_category(series):
    unique_count = series.nunique(dropna=False)
    total_count = len(series)
    if pd.api.types.is_numeric_dtype(series):
        return 'Numerical'
    elif pd.api.types.is_datetime64_dtype(series):
        return 'Date'
    elif unique_count==total_count:
        return 'Text (Unique)'
    else:
        return 'Categorical'

def print_categories(df):
    for column_name in df.columns:
        print(column_name, ": ", get_var_category(df[column_name]))

Variabili di Beers

print_categories(beers)

Il comando sopra ti restituisce il seguente risultato:

abv :  Numerical
ibu :  Numerical
id :  Numerical
name :  Categorical
style :  Categorical
brewery_id :  Numerical
ounces :  Numerical

Variabili di Breweries

print_categories(breweries)

Che ti restituisce il seguente risultato:

name :  Categorical
city :  Categorical
state :  Categorical
id :  Numerical

Con queste informazioni puoi già comprendere meglio il nostro dataset. Sai che stai trattando solo dati categoriali e numerici. Le variabili numeriche possono essere usate per estrarre molte misurazioni diverse come media, deviazione standard, ecc. Le variabili categoriali sono in genere un modo interessante per segmentare e raggruppare i dati. Per esempio, potresti voler capire come l’IBU differisce tra i vari stili di birra.

Statistiche descrittive

In questa sezione passerai in rassegna varie statistiche descrittive che possono essere usate per comprendere meglio i nostri dati. Noterai che ciascuna di queste misure, presa isolatamente, non è molto utile. È dalla combinazione di misure diverse che puoi estrarre il maggior valore.

Ti concentrerai sulla variabile IBU perché è una variabile numerica. Questo tipo di variabile offre una gamma più ampia di misurazioni rispetto a quelle categoriali. Puoi comunque calcolare misure anche sulle variabili categoriali, ma sarai molto più limitato.

Lunghezza

La funzione len conta il numero di osservazioni in una Series. La funzione conterà tutte le osservazioni, indipendentemente dalla presenza di valori mancanti o nulli.

length = len(beers["ibu"])
print(length)

In questa Series abbiamo un totale di 2410 osservazioni.

Conteggio

La funzione count restituisce il numero di osservazioni non-NA/non-nulle in una Series.

count = beers["ibu"].count()
print(count)

Come puoi vedere, hai 1405 osservazioni non nulle nella Series.

Valori mancanti

Con la Length e il Count ora possiamo calcolare il numero di valori mancanti. Il numero di valori mancanti è la differenza tra Length e Count.

number_of_missing_values = length - count
pct_of_missing_values = float(number_of_missing_values / length)
pct_of_missing_values = "{0:.1f}%".format(pct_of_missing_values*100)
print(pct_of_missing_values)

Per ottenere i valori mancanti in percentuale, dividi semplicemente il numero di valori mancanti per il numero totale di osservazioni, cioè la lunghezza. La funzione float è usata per assicurarsi che i decimali vengano catturati nella divisione. La funzione format è usata per formattare in modo ordinato il numero come percentuale.

In questo caso, mancano quasi il 42% dei valori della variabile IBU. Questo è importante da sapere perché influenzerà la tua analisi. La maggior parte delle statistiche descrittive ignorerà questi valori mancanti e questo causerà certamente un bias.

Valore minimo/massimo

Il valore minimo e massimo di un dataset si possono ottenere facilmente con le funzioni min e max su una Series.

print("Minimum value: ", beers["ibu"].min())
print("Maximum value: ", beers["ibu"].max())

I valori min/max sono utili per capire l’intervallo di valori di una variabile. In questo caso, l’IBU va da 4 a 138.

Moda

La moda è il valore più frequente in un dataset. Si può ottenere usando la funzione mode su una Series.

print(beers["ibu"].mode())

In una distribuzione normale, la moda è uguale a mean e median.

In questo caso, la moda della variabile IBU è 20. È l’IBU più frequente nel nostro dataset.

Media

La media è una misura di tendenza centrale. Rappresenta la somma dei valori divisa per il numero di osservazioni non mancanti.

Si può ottenere con la funzione mean su una Series.

mean = beers["ibu"].mean()

La media è suscettibile all’influenza degli outlier. Alcuni valori estremi possono modificarla notevolmente, trascinandola verso l’alto o verso il basso.

Mediana

La mediana è anch’essa una misura di tendenza centrale. È il numero esattamente al centro di un elenco ordinato di valori numerici.

median = beers["ibu"].median()

Nel caso di distribuzioni asimmetriche, la mediana è una misura di tendenza centrale molto migliore della media.

Nel caso della distribuzione dell’IBU, media e mediana sono dello stesso ordine di grandezza.

Deviazione standard

La deviazione standard è una misura di dispersione. Un’elevata deviazione standard indica che i punti dati sono distribuiti su un ampio intervallo di valori. La deviazione standard è espressa nella stessa unità dei valori.

standarddev = beers["ibu"].std()

In questo caso, la deviazione standard è ~26. Precisamente 25.954065911259324. Se la distribuzione dell’IBU fosse normale, sapresti che ~68% delle osservazioni è entro una deviazione standard dalla media.

Statistiche di quantile

I quantili sono punti di taglio che dividono una distribuzione in parti di uguale dimensione. Molti quantili hanno un proprio nome. Se dividi una distribuzione in quattro gruppi uguali, il quantile creato si chiama quartile. Puoi creare facilmente quantili usando la funzione quantile su una Series. Puoi passare a quella funzione un array con i diversi quantili da calcolare. Nel caso sotto, vogliamo dividere la nostra distribuzione in quattro gruppi uguali.

quantile = beers["ibu"].quantile([.25, .5, .75])
0.25 21.0
0.50 35.0
0.75 64.0
Name: ibu, dtype: float64

Come puoi vedere sopra, il quantile al 50% è uguale alla mediana. È il valore che divide il dataset a metà. Puoi anche notare che il 75% delle osservazioni è minore o uguale a 64 IBU. Inoltre, il 50% della distribuzione si trova tra 21 e 64 IBU. È importante notare che i valori mancanti non sono considerati in queste metriche.

Grafici di distribuzione

Le visualizzazioni sono molto utili nell’analisi esplorativa dei dati. In questo post non entreremo nel dettaglio delle visualizzazioni. Tuttavia, non si può parlare di data profiling senza menzionare l’importanza di un grafico di distribuzione delle frequenze. È una delle visualizzazioni più semplici ma anche più potenti. Mostra la frequenza di ciascun valore nel nostro dataset.

Per creare questa visualizzazione usiamo la libreria seaborn`` con ladisplotfunction. Questa funzione si aspetta unaSeries` senza valori mancanti.

import seaborn as sns
sns.set(color_codes=True)
sns.set_palette(sns.color_palette("muted"))

sns.distplot(beers["ibu"].dropna());

distribution plot

In questo grafico di distribuzione puoi vedere chiaramente alcuni dei valori calcolati in precedenza. Il valore minimo è vicino a 0 IBU e il valore massimo è vicino a 140 IBU. Vedi chiaramente che il valore più frequente è vicino a 20 IBU. In aggiunta a queste informazioni, ora vediamo un picco vicino a 60 IBU.

Perché ci sono due picchi in questa distribuzione?

Cosa può spiegarlo? Questo è un aspetto che possiamo esplorare nella seconda fase dell’analisi esplorativa dei dati.

Correlazioni

Le correlazioni sono un ottimo modo per scoprire relazioni tra variabili numeriche. Esistono vari modi per calcolare la correlazione. Il coefficiente di correlazione di Pearson è un approccio ampiamente usato che misura la dipendenza lineare tra due variabili. Il coefficiente di correlazione varia da -1 a 1. Una correlazione di 1 è una correlazione positiva totale, -1 è una correlazione negativa totale e 0 indica assenza di correlazione lineare. Possiamo eseguire quel calcolo usando la funzione corr su una Series. Per impostazione predefinita, questa funzione usa il coefficiente di Pearson. È possibile usare metodi di calcolo diversi con questa funzione.

beers[["abv", "ibu", "ounces"]].corr()
  abv ibu ounces
abv 1 0.670621 0.172529
ibu 0.670621 1 0.054691
ounces 0.172529 0.054691 1

Come puoi vedere sopra, la correlazione tra l’IBU e se stessa è 1. Ovviamente, le variabili numeriche sono perfettamente correlate con se stesse. Più interessante, puoi vedere che la correlazione tra ABV e IBU è pari a 0.670621. Pur non essendo una correlazione positiva totale, è comunque elevata. Questo è un aspetto interessante che possiamo esplorare più avanti.

Qualche nota sulle variabili non numeriche

Le metriche estratte in precedenza sono applicabili principalmente ai valori numerici. Se stai lavorando con altri tipi di dati, come quelli categoriali, puoi comunque ricavare alcune misure interessanti. Potresti calcolare la frequenza di ciascun valore nel dataset.

I DataFrame hanno una funzione chiamata describe che riassume il dataset. Se il tuo DataFrame contiene solo valori categoriali o di testo, il riepilogo sarà adattato specificamente a questo tipo di dati.

beers[["name", "style"]].describe()
  name style
count 2410 2405
unique 2305 99
top Nonstop Hef Hop American IPA
freq 12 424

Librerie per il profiling

Come hai visto sopra, raccogliere statistiche descrittive può essere un processo noioso. Per fortuna esistono librerie che fanno tutto il lavoro pesante per te. Producono un profilo molto chiaro dei tuoi dati. pandas-profiling è una di queste. Questa libreria offre un profiling statistico pronto all’uso del tuo dataset. Poiché il dataset che stiamo usando è tidy e standardizzato, possiamo usare la libreria subito sul nostro dataset.

import pandas_profiling 

pandas_profiling.ProfileReport(beers_and_breweries)

Altre domande

In genere, una volta profilato il tuo dataset, hai molte più domande rispetto all’inizio. Questo è ottimo perché queste nuove domande alimenteranno la tua analisi esplorativa dei dati.

Ecco alcune domande che abbiamo raccolto durante questo profiling:

  • Il 41,7% dei valori di IBU è mancante. Perché? Come può influenzare la nostra analisi?
  • Ci sono due picchi nella distribuzione dell’IBU. Cosa lo spiega?
  • Cosa spiega la correlazione tra IBU e ABV? Qual è l’influenza dello stile di birra in questa correlazione?
  • Ci sono differenze in IBU, ABV o Style tra regioni geografiche? E tra East Coast e West Coast?

Il data profiling non è un processo lineare. Man mano che filtri e segmenti il tuo dataset, tornerai a raccogliere statistiche descrittive su sottogruppi dei tuoi dati.

Prossimi passi

In questo post hai visto come profilare un dataset. Ora sai come attribuire le variabili a specifici gruppi di tipi di dato. Hai anche calcolato diverse statistiche descrittive sul dataset e capisci come interpretare queste misure. Infine, hai visto che esistono librerie che possono aiutarti nel lavoro di calcolo per profilare il tuo dataset. Ancora più importante, hai generato più domande che mai per alimentare la tua analisi esplorativa dei dati.

Dai un’occhiata al Tutorial di Analisi Esplorativa dei Dati in Python di DataCamp.

Argomenti
Analisi dei dati
Data Science
Python

Scopri di più su Python

Corso

Analisi dei dati bayesiana in Python

4 ore
16.2K
Scopri tutti i vantaggi dell'analisi bayesiana dei dati e usala in un sacco di casi reali!
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

blog

Che cos'è Snowflake? Guida per principianti alla piattaforma dati cloud

Esplora le basi di Snowflake, la piattaforma dati cloud. Scopri la sua architettura, le sue funzionalità e come integrarla nelle tue pipeline di dati.
Tim Lu's photo

Tim Lu

12 min

blog

Tokenizzazione nel NLP: come funziona, sfide e casi d'uso

Guida al preprocessing NLP nel machine learning. Copriamo spaCy, i transformer di Hugging Face e come funziona la tokenizzazione in casi d'uso reali.
Abid Ali Awan's photo

Abid Ali Awan

10 min

blog

I 15 migliori server MCP remoti che ogni AI builder dovrebbe conoscere nel 2026

Scopri i 15 migliori server MCP remoti che stanno trasformando lo sviluppo AI nel 2026. Scopri come migliorano automazione, ragionamento, sicurezza e velocità dei workflow.
Abid Ali Awan's photo

Abid Ali Awan

15 min

Mostra AltroMostra Altro