Dopo aver letto un’articolo molto curioso su Forbes ho deciso di scrivere qualche riga sul data preprocessing e su come manovrare dati prima ancora di implementare tutte le possibili tecniche di machine learning. Secondo l’articolo in questione, questa fase occupa circa il 60% del tempo di chi lavora in questo settore.

 

Fonte: articolo forbes

Con il termine data preprocessing ci si riferisce ad una serie di tecniche di data mining che consistono nel trasformare i dati in un formato comprensibile e adatto alle nostre necessità. Nella “vita reale” i dati sono spesso incompleti, inconsistenti, oppure alcuni trend non sono visibili e quindi, vanno fatti affiorare; inoltre durante questa fase possono emergere nuovi patterns e/o ipotesi da eventualmente validare impiegando diversi modelli.

Dati mancanti (missing data)

Una situazione classica della “vita di tutti i giorni” sono i dati mancanti, pensiamo a quando compiliamo un modulo: non sempre rispondiamo a tutte le domande che ci vengono poste, oppure semplicemente non vogliamo condividere determinate informazioni.

 

Un esempio di una time-series dove mancano delle osservazioni.

Normalmente, nel momento nel quale ci si trova di fronte a osservazioni mancanti due strategie possono essere usate:

  • eliminare le osservazioni contenenti i dati mancanti: questa tecnica è valida nei casi dove, ad esempio, le osservazioni ad essere parziali o incomplete sono poche in proporzione alla grandezza del dataset, oppure dove le osservazioni mancanti non sono rilevanti nello studio.
  • completare le osservazioni contenenti dati mancanti utlizzando tools come la media, la moda o altri strumenti: questa tecnica viene utilizzata soprattutto dove i modelli che si vogliono implementare non ammettono osservazioni mancanti (time-series, analisi di sopravvivenza, KNN…)

Utilizzando un piccolo dataset puramente creato per dimostrare questi esempi, affiancato dalle librerie Pandas e sklearn ecco come si può procedere:

# Importo le librerie
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importo il dataset
dataset = pd.read_csv('Data.csv')

# Divido il dataset in variabili indipendenti e dipendenti
# il metodo .values ritorna una rappresentazione del dataset come array di arrays
X = dataset.iloc[:, :-1].values
y = dataset.iloc[:, 3].values

# La classe Imputer è un'ottimo strumento per prendersi cura dei dati mancanti
from sklearn.preprocessing import Imputer
imputer = Imputer(missing_values = 'NaN', strategy = 'median', axis=0)
imputer = imputer.fit(X[:, 1:3])
X[:, 1:3] = imputer.transform(X[:, 1:3])

Prima e dopo, i valori mancanti sono stati sostituiti con la mediana della colonna, mentre la variabile dipendente “Purchased” è stata rimossa dal dataset.

Encoding di variabili categoriche

Nel dataset utilizzato in questo esempio sono presenti delle variabili categoriche che rappresentano nomi di Stati, per poter utilizzare queste variabili in un modello è necessario trasformarle in variabili numeriche, allo stesso tempo però non si può assegnare direttamente uno scalare, altrimenti quando il dataset verrà utilizzato in qualche modello, la categoria rappresentata dallo scalare con il valore assoluto più alto avrà la prevalenza sulle altre. Per ovviare a questo problema è necessario utilizzare un piccolo stratagemma: ovvero aggiungere colonne di zeri, dove è il numero di categorie presenti; e per ogni osservazione dove ricade un determinata categoria lo zero verrà sostituito con un uno.

Sempre dalla libreria sklearn vengono in aiuto due classi create apposta per questo: LabelEncoder OneHotEncoder :

# Encoding
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X = LabelEncoder()
X[:, 0] = labelencoder_X.fit_transform(X[:, 0])
onehotencoder = OneHotEncoder(categorical_features = [0])
X = onehotencoder.fit_transform(X).toarray()
# Encoding the Dependent Variable
labelencoder_y = LabelEncoder()
y = labelencoder_y.fit_transform(y)

Divisione del dataset in test set e training set

Un’operazione fondamentale del supervised learning è la divisione del dataset in test set e training set, questo può essere fatto in letteralmente due righe di codice grazie alla classe train_test_split .

# Splitting
from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)

Il dataset viene diviso con proporzione 80–20, tenendo il 20% per i test sets.

Tips & tricks

Spesso, durante il preprocessing, possono tornare utili una serie di comandi per filtrare, cercare e raggruppare i dati, di seguito ne elencherò alcuni tra quelli più usati.

Spesso può capitare di dover ricercare una stringa o una porzione di stringa all’interno di un dataset, questo si può ottenere utlizzando un metodo di numpywhere() che ritorna un array contenente True False in base al risultato della ricerca.

array([ 1., nan, nan, nan, nan, 1., nan, 1., nan, 1.])

nel caso si voglia fare una ricerca di più stringe è sufficiente passare come argomento la lista contenente le stringe preceduta dal metodo join() :

array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

Filtrare le colonne

Filtrare le colonne in base a determinate condizioni è un operazione basilare ma largamente utilizzata, è possibile filtrare le colonne in base a condizioni semplicemente separando ogni condizione con un &:

Raggruppare e contare

Spesso può tornare molto utile raggruppare dati per categorie e contarli:

Pivot tables

Raggruppare i dati in pivot tables è un’operazione estremamente efficace per creare report, in questo esempio viene creata una tabella contenente la somma dei salari per paese:

Da una tabella pivot, senza utilizzare nessun’altra libreria è possibile creare un grafico semplicemente chiamando il metodo plot(), in questo esempio un’istogramma: table.plot(kind=’bar’)

 

Probabilmente più veloce di Excel.

Rimovere duplicati aggregando una colonna

In alcuni casi può capitare di voler aggregare righe contenenti lo stesso valore per evitare duplicati senza però perdere il contenuto, ad esempio in questo dataset ci sono diverse ripetizioni nella colonna Country :

Aggregare la colonna Country, evitando ripetizioni può tornare utile:

Questo si può ottenere combinando due metodi molto potenti di Pandasgroupby() e agg() utilizzando un funzione lambda per aggiungere la virgola dopo ogni nome di città:

In questo articolo ho voluto condividere diverse strategie utilizzabili sia nel data preprocessing che semplicemente in tutte quelle situazioni nelle quali c’è la necessita di manovrare e/o modificare dati. Alcuni di questi metodi sono fattibilissimi con qualunque foglio di calcolo, ma non sempre è possibile aprire un dataset in un foglio di calcolo; nei casi nei quali si lavora tramite database, connessioni ssh, Jupyter Notebooks e via dicendo raramente si ha a disposizione programmi come OpenOffice oppure Excel.

Se sei arrivato fin qui ed il tema ti interessa ti consiglio vivamente il mio secondo articolo su data preprocessing ed analisi time-serie.


 

About Roberto Sannazzaro

Studente di Advanced Analytics e Big Data alla Warsaw School of Economics, mi occupo di sviluppo di sistemi di machine learning e analisi di big data.