Vai al contenuto principale

Preparazione dei dati con pandas

In questo tutorial scoprirai perché è importante pre-processare i dati e come farlo con pandas.
Aggiornato 29 set 2026  · 15 min leggi

Scopri con l'IA

ChatGPTClaudePerplexity

Questo tutorial ti guiderà attraverso alcuni concetti e passaggi di base per la preparazione dei dati. La preparazione dei dati è il primo passo dopo aver messo le mani su qualsiasi tipo di dataset. In questa fase pre-processi i dati grezzi in una forma che possa essere analizzata facilmente e con precisione. Una corretta preparazione dei dati consente un’analisi efficiente: può eliminare errori e imprecisioni che potrebbero essersi verificati durante la raccolta dei dati e aiutare a rimuovere parte dei bias dovuti a una scarsa qualità dei dati. Per questo motivo, gran parte del tempo di un analista è dedicato a questo passaggio cruciale.

Caricare i dati, ripulirli (rimuovere dati non necessari o errati), trasformarne i formati e riordinarli sono le varie fasi coinvolte nella preparazione dei dati. In questo tutorial userai la libreria Pandas di Python per la preparazione dei dati.

Assicurati di conoscere concetti come DataFrame, Series, ecc. di Pandas, perché li incontrerai spesso in questo tutorial. Puoi approfondire pandas nel tutorial su Pandas di DataCamp.

In questo tutorial:

Lungo il percorso troverai suggerimenti, trucchi e riferimenti ad altro materiale di approfondimento, se vuoi esplorare ulteriormente un argomento.

Iniziamo con una breve introduzione a Pandas...

Pandas

Pandas è una libreria software scritta per Python. È molto famosa nella comunità data science perché offre strutture dati potenti, espressive e flessibili che rendono facile la manipolazione e l’analisi dei dati, ed è gratuita. Inoltre, se hai un caso d’uso specifico e nuovo, puoi condividerlo in una delle mailing list di Python o sul repository GitHub di pandas: in effetti, molte funzionalità di pandas sono state guidate proprio da casi d’uso reali.

Per un’ottima introduzione a pandas, dai un’occhiata al corso Pandas Foundation di DataCamp. È molto interattivo e il primo capitolo è gratuito!

Per usare la libreria pandas, devi prima importarla. Digita questo nella tua console Python:

import pandas as pd

Caricamento dei dati

Il primo passo della preparazione dei dati è… ottenere dei dati. Se hai un file .csv, puoi caricarlo facilmente nel tuo sistema usando la funzione .read_csv() di pandas. Puoi quindi digitare:

data = pd.read_csv('path_to_file.csv')

Tuttavia, per questo tutorial lavorerai con DataFrame e Series più piccoli e facili da capire, creati al volo.

Dati mancanti

Gestione dei dati mancanti

Questo è un problema molto diffuso nel mondo dell’analisi dei dati.

diagramma gestione dati mancanti


Fonte

I dati mancanti possono comparire nel dataset per vari motivi: il dato per un determinato campo non è stato inserito dall’utente/dall’applicazione di raccolta, i dati sono andati persi durante un trasferimento manuale, un errore di programmazione, ecc. A volte è fondamentale capirne la causa, perché questo influenzerà il modo in cui li gestirai. Ma ne parleremo più avanti nel tutorial. Per ora, concentriamoci su cosa fare se hai dati mancanti…

Per i dati numerici, pandas usa il valore in virgola mobile NaN (Not a Number) per rappresentare i dati mancanti. È un valore univoco definito nella libreria Numpy, quindi dovremo importarla. NaN è il marcatore predefinito dei valori mancanti per motivi di velocità computazionale e praticità. È un valore sentinella, nel senso che è un valore fittizio o di bandiera che può essere facilmente rilevato e gestito con le funzioni di pandas.

nan vs null

Giochiamo un po’ con i dati…

import numpy as np

# Creating a pandas series
data = pd.Series([0, 1, 2, 3, 4, 5, np.nan, 6, 7, 8])

# To check if and what index in the dataset contains null value
data.isnull()
0    False
1    False
2    False
3    False
4    False
5    False
6     True
7    False
8    False
9    False
dtype: bool

Sopra abbiamo usato la funzione isnull() che restituisce un valore booleano true o false. True quando il dato in quell’indice è effettivamente mancante o NaN. L’opposto è la funzione notnull().

# To check where the dataset does not contain null value - opposite of isnull()
data.notnull()
0     True
1     True
2     True
3     True
4     True
5     True
6    False
7     True
8     True
9     True
dtype: bool

Inoltre, possiamo usare la funzione dropna() per filtrare i dati mancanti, rimuovere il valore nullo (mancante) e visualizzare solo i valori non nulli. Tuttavia, il valore NaN non viene realmente eliminato e si trova ancora nel dataset originale.

# Will not show the index 6 cause it contains null (NaN) value
data.dropna()
0    0.0
1    1.0
2    2.0
3    3.0
4    4.0
5    5.0
7    6.0
8    7.0
9    8.0
dtype: float64
data
0    0.0
1    1.0
2    2.0
3    3.0
4    4.0
5    5.0
6    NaN
7    6.0
8    7.0
9    8.0
dtype: float64

Per "eliminare" davvero il valore NaN puoi o salvare il nuovo dataset (senza NaN) in modo da non toccare la Series originale, oppure applicare un drop inplace. L’argomento inplace ha valore predefinito false.

not_null_data = data.dropna()
not_null_data
0    0.0
1    1.0
2    2.0
3    3.0
4    4.0
5    5.0
7    6.0
8    7.0
9    8.0
dtype: float64
# Drop the 6th index in the original 'data' since it has a NaN place
data.dropna(inplace = True)
data
0    0.0
1    1.0
2    2.0
3    3.0
4    4.0
5    5.0
7    6.0
8    7.0
9    8.0
dtype: float64

I dataframe però possono essere più complessi e a 2 dimensioni, cioè contenere righe e colonne. Anche in questo caso, pandas ti copre…

# Creating a dataframe with 4 rows and 4 columns (4*4 matrix)
data_dim = pd.DataFrame([[1,2,3,np.nan],[4,5,np.nan,np.nan],[7,np.nan,np.nan,np.nan],[np.nan,np.nan,np.nan,np.nan]])
data_dim
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 NaN NaN
2 7.0 NaN NaN NaN
3 NaN NaN NaN NaN

Ora diciamo che vuoi eliminare solo le righe o le colonne che sono tutte nulle o solo quelle che contengono una certa quantità di valori nulli. Esamina i vari scenari: ricorda che l’eliminazione non avviene inplace, quindi il dataset reale non viene toccato. Fai attenzione agli argomenti passati alla funzione dropna() per determinare come eliminare i dati mancanti.

# Drop all rows and columns containing NaN value
data_dim.dropna()
  0 1 2 3
# Drop all rows and columns containing entirely of NaN value
data_dim.dropna(how = 'all')
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 NaN NaN
2 7.0 NaN NaN NaN
# Drop only columns that contain entirely NaN value
# Default is 0 - which signifies rows
data_dim.dropna(axis = 1, how = 'all')
  0 1 2
0 1.0 2.0 3.0
1 4.0 5.0 NaN
2 7.0 NaN NaN
3 NaN NaN NaN
# Drop all columns that have more than 2 NaN values
data_dim.dropna(axis = 1, thresh = 2)
  0 1
0 1.0 2.0
1 4.0 5.0
2 7.0 NaN
3 NaN NaN
# Drop all rows that have more than 2 NaN values
data_dim.dropna(thresh = 2)
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 NaN NaN

Ora sai come identificare ed eliminare i valori mancanti, sia per visualizzare il dataset risultante sia per una cancellazione inplace. In molti casi, però, eliminare semplicemente i valori nulli non è un’opzione praticabile e potresti voler compilare i dati mancanti con altri valori. Vediamo come farlo…

Compilare i dati mancanti

Per sostituire o meglio "riempire" i dati nulli, puoi usare la funzione fillna(). Ad esempio, proviamo a usare lo stesso dataset di prima e riempire i valori NaN con 0.

# Check what the dataset looks like again
data_dim
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 NaN NaN
2 7.0 NaN NaN NaN
3 NaN NaN NaN NaN
# Fill the NaN values with 0
data_dim_fill = data_dim.fillna(0)
data_dim_fill
  0 1 2 3
0 1.0 2.0 3.0 0.0
1 4.0 5.0 0.0 0.0
2 7.0 0.0 0.0 0.0
3 0.0 0.0 0.0 0.0

E, come con dropna(), puoi fare molte altre cose a seconda dell’argomento che passi. Ricorda anche che passando l’argomento inplace = True apporterai la modifica al dataset originale.

# Pass a dictionary to use differnt values for each column
data_dim_fill = data_dim.fillna({0: 0, 1: 8, 2: 9, 3: 10})
data_dim_fill
  0 1 2 3
0 1.0 2.0 3.0 10.0
1 4.0 5.0 9.0 10.0
2 7.0 8.0 9.0 10.0
3 0.0 8.0 9.0 10.0

Puoi passare un argomento method alla funzione fillna() che propaga automaticamente i valori non nulli in avanti (ffill o pad) o all’indietro (bfill o backfill).

# Pass method to determine how to fill-up the column - forward here
data_dim_fill = data_dim.fillna(method='ffill')
data_dim_fill
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 3.0 NaN
2 7.0 5.0 3.0 NaN
3 7.0 5.0 3.0 NaN

Puoi anche limitare il numero di riempimenti. Per esempio, riempi solo due posizioni nelle colonne… Inoltre, se passi axis = 1 il riempimento verrà fatto sulle righe.

# Pass method to determine how to fill-up the column - forward here
data_dim_fill = data_dim.fillna(method='ffill', limit = 2)
data_dim_fill
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 3.0 NaN
2 7.0 5.0 3.0 NaN
3 7.0 5.0 NaN NaN
# Pass method to determine how to fill-up the row - forward here
data_dim_fill = data_dim.fillna(axis = 1, method='ffill')
data_dim_fill
  0 1 2 3
0 1.0 2.0 3.0 3.0
1 4.0 5.0 5.0 5.0
2 7.0 7.0 7.0 7.0
3 NaN NaN NaN NaN

Con un po’ di comprensione dei dati e del tuo caso d’uso, puoi usare la funzione fillna() in molti altri modi oltre al semplice riempimento con numeri. Potresti riempire usando la media con mean() o il valore mediano con median()…

# Check the data_dim dataset
data_dim
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 NaN NaN
2 7.0 NaN NaN NaN
3 NaN NaN NaN NaN
# Fill the NaN value with mean values in the corresponding column
data_dim_fill = data_dim.fillna(data_dim.mean())
data_dim_fill
  0 1 2 3
0 1.0 2.0 3.0 NaN
1 4.0 5.0 3.0 NaN
2 7.0 3.5 3.0 NaN
3 4.0 3.5 3.0 NaN

Trasformazione dei dati

Sostituzione dei valori

Finora hai lavorato solo con dati mancanti (NaN), ma potrebbero esserci situazioni in cui vuoi sostituire un valore non nullo con un valore diverso. Oppure un valore nullo è registrato come un numero casuale e quindi deve essere trattato come NaN piuttosto che come numero. È qui che la funzione replace() torna utile…

Creiamo questa volta un dataset diverso.

data = pd.Series([1,2,-99,4,5,-99,7,8,-99])
data
0     1
1     2
2   -99
3     4
4     5
5   -99
6     7
7     8
8   -99
dtype: int64
# Replace the placeholder -99 as NaN
data.replace(-99, np.nan)
0    0.0
1    1.0
2    2.0
3    3.0
4    4.0
5    5.0
7    6.0
8    7.0
9    8.0
dtype: float64

Non vedrai più -99, perché è stato sostituito con NaN e quindi non viene mostrato. Allo stesso modo puoi passare più valori da sostituire. Per farlo, creeremo un’altra series e poi concateneremo la series originale con la nuova per poi applicare la sostituzione multipla.

Concatenare Series di pandas

Per farlo, possiamo usare la funzione concat() di pandas. Per far proseguire l’indicizzazione dopo la concatenazione, puoi passare l’argomento ignore_index = True.

# Create a new Series
new_data = pd.Series([-100, 11, 12, 13])
combined_series = pd.concat([data, new_data], ignore_index = True)
combined_series
0       1
1       2
2     -99
3       4
4       5
5     -99
6       7
7       8
8     -99
9    -100
10     11
11     12
12     13
dtype: int64
# Let's replace -99 and -100 as NaN in the new combined_series
data_replaced = combined_series.replace([-99, -100], np.nan)
data_replaced
0      1.0
1      2.0
2      NaN
3      4.0
4      5.0
5      NaN
6      7.0
7      8.0
8      NaN
9      NaN
10    11.0
11    12.0
12    13.0
dtype: float64
# Argument passed can also be a dictionary with separate values
data_replaced = combined_series.replace({-99: np.nan, -100: 0})

# Same as: new_data.replace([-99, -100], [np.nan, 0])
data_replaced
0      1.0
1      2.0
2      NaN
3      4.0
4      5.0
5      NaN
6      7.0
7      8.0
8      NaN
9      0.0
10    11.0
11    12.0
12    13.0
dtype: float64

Aggiungere conoscenza - funzione map

In alcune situazioni potresti voler aggiungere maggiore insight a ciò che hai già, in base a una logica. È qui che puoi usare map e una combinazione di funzioni per ottenere ciò che vuoi. La logica può diventare più complicata, ma prova a capirla con questo esempio.

Supponiamo di avere un dataframe di numeri mappati alla loro corrispondente conta in inglese.

data_number = pd.DataFrame({'english': ['zero','one','two','three','four','five'],
'digits': [0,1,2,3,4,5]})
data_number
  english digits
0 zero 0
1 one 1
2 two 2
3 three 3
4 four 4
5 five 5

Ora diciamo che vuoi aggiungere un’altra colonna che indichi i multipli di due come "Yes" e il resto come "No". Puoi scrivere una mappatura di ciascun termine inglese distinto alla sua corrispondente etichetta "Yes" o "No".

english_to_multiple = {
    'two': 'yes',
    'four': 'yes'
}

Quindi puoi chiamare la funzione map per aggiungere la colonna quando il valore nella colonna English è un multiplo di 2. Cosa viene inserito nelle altre colonne non multiple? Scopriamolo…

data_number['multiple'] = data_number['english'].map(english_to_multiple)
data_number
  english digits multiple
0 zero 0 NaN
1 one 1 NaN
2 two 2 yes
3 three 3 NaN
4 four 4 yes
5 five 5 NaN

Le altre colonne sono riempite con valori NaN, e sai già come lavorare ulteriormente con i valori mancanti. Questo era un esempio semplice. Ma speriamo tu possa trarne ispirazione per usare la funzione map in casi d’uso più specifici.

Discretizzazione - funzione cut

A volte potresti voler categorizzare in base a una logica e mettere tutti i dati in insiemi o "bin" discreti per l’analisi. Puoi usare la funzione cut() per questo. Per esempio, creiamo prima un dataset contenente 30 numeri casuali tra 1 e 100.

import random

data = random.sample(range(1, 101), 30)
# data
[45,
 39,
 25,
 83,
 27,
 6,
 73,
 43,
 36,
 93,
 97,
 17,
 15,
 99,
 37,
 5,
 31,
 22,
 65,
 30,
 3,
 26,
 91,
 12,
 52,
 76,
 63,
 84,
 59,
 53]

Diciamo di volerli categorizzare in base a dei bucket definiti da noi: numeri tra 1 - 25, poi 25 - 35, 40 - 60, poi 60 - 80 e infine il resto. Quindi definiamo un bucket…

Poi useremo la funzione cut.

# Defining the starting value for each bucket
bucket = [1, 25, 35, 60, 80, 100]

cut_data = pd.cut(data, bucket)
cut_data
[(35, 60], (35, 60], (1, 25], (80, 100], (25, 35], ..., (60, 80], (60, 80], (80, 100], (35, 60], (35, 60]]
Length: 30
Categories (5, interval[int64]): [(1, 25] < (25, 35] < (35, 60] < (60, 80] < (80, 100]]

cut() è una funzione molto utile, e ci puoi fare molto di più. Ti consigliamo vivamente di consultare la documentazione di Pandas per saperne di più.

Variabili dummy e One-Hot Encoding

Questo argomento è particolarmente utile quando vuoi convertire dei dati categoriali in valori numerici per poterli usare nel tuo modello di analisi. È particolarmente comodo, soprattutto nel machine learning, dove il concetto di one-hot encoding è diffuso. In termini più tecnici: il one-hot encoding è il processo di conversione di valori categoriali in un vettore numerico monodimensionale.

Un modo per farlo con pandas è usare la funzione get_dummies(). Se una colonna del tuo dataframe ha 'n' valori distinti, la funzione ricaverà una matrice con 'n' colonne contenenti solo 1 e 0. Vediamolo con un esempio per afferrare meglio il concetto…

# Creating a DataFrame consiting individual characters in the list
data = pd.Series(list('abcdababcdabcd'))
data
0     a
1     b
2     c
3     d
4     a
5     b
6     a
7     b
8     c
9     d
10    a
11    b
12    c
13    d
dtype: object

Ora diciamo che vuoi avere vettori separati che indichino la presenza di ciascun carattere per passarli a una funzione.

Qualcosa tipo: per 'a' = [1,0,0,0,1,0,1,0,0,0,1,0,0,0], dove 1 è nelle posizioni in cui 'a' è presente e 0 dove non lo è. Usare la funzione get_dummies() renderà il compito più semplice.

pd.get_dummies(data)
  a b c d
0 1 0 0 0
1 0 1 0 0
2 0 0 1 0
3 0 0 0 1
4 1 0 0 0
5 0 1 0 0
6 1 0 0 0
7 0 1 0 0
8 0 0 1 0
9 0 0 0 1
10 1 0 0 0
11 0 1 0 0
12 0 0 1 0
13 0 0 0 1

Tuttavia, questo è un semplice esempio per iniziare. Nelle applicazioni reali, l’appartenenza di un carattere può riferirsi a più categorie allo stesso tempo, quindi dovrai imparare metodi più sofisticati. Inoltre, per dataset molto più grandi, questa funzione potrebbe non essere molto efficiente in termini di velocità. L’articolo di DataCamp Handling Categorical Data in Python discute questi casi e l’argomento in modo più approfondito.

E adesso?

Sei arrivato alla fine del tutorial e hai imparato alcuni strumenti di base per iniziare il primo passo nel tuo percorso di analisi dei dati. Altre competenze utili nella fase di preparazione dei dati includono imparare a rilevare e filtrare gli outlier nel tuo dataset e, se il dataset è molto grande, magari iniziare con un campionamento casuale. Ma sono di nuovo temi ampi e difficili da generalizzare.

I casi d’uso reali possono essere spesso più complessi e richiedere soluzioni ad hoc, ma l’idea è di partire in piccolo, imparare strada facendo, esplorare e sporcarti le mani con dataset diversi! Assicurati di dare un’occhiata al corso Cleaning Data in Python di DataCamp per imparare altri strumenti e trucchi e, alla fine, lavorerai su un vero dataset disordinato ottenuto dalla Gapminder Foundation. Inizia subito!

Argomenti
Python
Data Science

Corsi di Python

Corso

Introduzione a Python

4 ore
7.1M
Impara le basi dell’analisi dei dati con Python in sole 4 ore. Questo corso online ti introduce all’interfaccia di Python e ai pacchetti più usati.
Vedi i dettagliRight Arrow
Inizia Il Corso
Mostra altroRight Arrow
Correlato

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

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

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