Foglio informativo del blocco note per una rapida preelaborazione dei dati

Spesso le persone che entrano nel campo della scienza dei dati hanno aspettative tutt’altro che realistiche su ciΓ² che li attende. Molte persone pensano che ora scriveranno fantastiche reti neurali, creeranno un assistente vocale di Iron Man o batteranno tutti nei mercati finanziari.
Ma lavora Dati Lo scienziato Γ¨ guidato dai dati e uno degli aspetti piΓΉ importanti e dispendiosi in termini di tempo Γ¨ l'elaborazione dei dati prima di inserirli in una rete neurale o analizzarli in un certo modo.

In questo articolo, il nostro team descriverΓ  come elaborare i dati in modo rapido e semplice con istruzioni e codice passo passo. Abbiamo cercato di rendere il codice abbastanza flessibile e che potesse essere utilizzato per diversi set di dati.

Molti professionisti potrebbero non trovare nulla di straordinario in questo articolo, ma i principianti potranno imparare qualcosa di nuovo e chiunque sogni da tempo di creare un notebook separato per l'elaborazione rapida e strutturata dei dati puΓ² copiare il codice e formattarlo da solo, oppure scarica il notebook finito da Github.

Abbiamo ricevuto il set di dati. Cosa fare dopo?

Quindi, la norma: bisogna capire con cosa abbiamo a che fare, il quadro complessivo. Per fare ciΓ², utilizziamo i panda per definire semplicemente diversi tipi di dati.

import pandas as pd #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ pandas
import numpy as np  #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ numpy
df = pd.read_csv("AB_NYC_2019.csv") #Ρ‡ΠΈΡ‚Π°Π΅ΠΌ датасСт ΠΈ записываСм Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ df

df.head(3) #смотрим Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹Π΅ 3 строчки, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ½ΡΡ‚ΡŒ, ΠΊΠ°ΠΊ выглядят значСния

Foglio informativo del blocco note per una rapida preelaborazione dei dati

df.info() #ДСмонстрируСм ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°Ρ…

Foglio informativo del blocco note per una rapida preelaborazione dei dati

Diamo un'occhiata ai valori delle colonne:

  1. Il numero di righe in ciascuna colonna corrisponde al numero totale di righe?
  2. Qual Γ¨ l'essenza dei dati in ciascuna colonna?
  3. Quale colonna vogliamo prendere di mira per fare previsioni al riguardo?

Le risposte a queste domande ti permetteranno di analizzare il set di dati e tracciare approssimativamente un piano per le tue prossime azioni.

Inoltre, per uno sguardo piΓΉ approfondito ai valori in ciascuna colonna, possiamo utilizzare la funzione pandas description(). Tuttavia, lo svantaggio di questa funzione Γ¨ che non fornisce informazioni sulle colonne con valori stringa. Ci occuperemo di loro piΓΉ tardi.

df.describe()

Foglio informativo del blocco note per una rapida preelaborazione dei dati

Visualizzazione magica

Diamo un'occhiata a dove non abbiamo alcun valore:

import seaborn as sns
sns.heatmap(df.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Foglio informativo del blocco note per una rapida preelaborazione dei dati

Questo era un breve sguardo dall'alto, ora passeremo a cose piΓΉ interessanti

Proviamo a trovare e, se possibile, rimuovere le colonne che hanno un solo valore in tutte le righe (non influenzeranno in alcun modo il risultato):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #ΠŸΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°Π΅ΠΌ датасСт, оставляя Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… большС ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния

Ora proteggiamo noi stessi e il successo del nostro progetto dalle righe duplicate (righe che contengono le stesse informazioni nello stesso ordine di una delle righe esistenti):

df.drop_duplicates(inplace=True) #Π”Π΅Π»Π°Π΅ΠΌ это, Ссли считаСм Π½ΡƒΠΆΠ½Ρ‹ΠΌ.
                                 #Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ… ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Π΅ с самого Π½Π°Ρ‡Π°Π»Π° Π½Π΅ стоит.

Dividiamo il dataset in due: uno con valori qualitativi e l'altro con valori quantitativi

Qui dobbiamo fare una piccola precisazione: se le righe con dati mancanti nei dati qualitativi e quantitativi non sono molto correlate tra loro, allora dovremo decidere cosa sacrificare: tutte le righe con dati mancanti, solo una parte di esse, o determinate colonne. Se le linee sono correlate, abbiamo tutto il diritto di dividere il set di dati in due. Altrimenti bisognerΓ  prima occuparsi delle linee che non correlano i dati mancanti in termini qualitativi e quantitativi, e solo successivamente dividere il dataset in due.

df_numerical = df.select_dtypes(include = [np.number])
df_categorical = df.select_dtypes(exclude = [np.number])

Lo facciamo per facilitarci l'elaborazione di questi due diversi tipi di dati: in seguito capiremo quanto questo ci semplifichi la vita.

Lavoriamo con dati quantitativi

La prima cosa da fare Γ¨ determinare se ci sono β€œcolonne spia” nei dati quantitativi. Chiamiamo queste colonne cosΓ¬ perchΓ© si presentano come dati quantitativi, ma agiscono come dati qualitativi.

Come li definiamo? Naturalmente, tutto dipende dalla natura dei dati che stai analizzando, ma in generale tali colonne potrebbero contenere pochi dati univoci (nell'ordine di 3-10 valori univoci).

print(df_numerical.nunique())

Una volta individuate le colonne spia, le sposteremo dai dati quantitativi ai dati qualitativi:

spy_columns = df_numerical[['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1', 'ΠΊΠΎΠ»ΠΎΠΊΠ°2', 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3']]#выдСляСм ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ-ΡˆΠΏΠΈΠΎΠ½Ρ‹ ΠΈ записываСм Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΡƒΡŽ dataframe
df_numerical.drop(labels=['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1', 'ΠΊΠΎΠ»ΠΎΠΊΠ°2', 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3'], axis=1, inplace = True)#Π²Ρ‹Ρ€Π΅Π·Π°Π΅ΠΌ эти ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ ΠΈΠ· количСствСнных Π΄Π°Π½Π½Ρ‹Ρ…
df_categorical.insert(1, 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1', spy_columns['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1']) #добавляСм ΠΏΠ΅Ρ€Π²ΡƒΡŽ ΠΊΠΎΠ»ΠΎΠ½ΠΊΡƒ-шпион Π² качСствСнныС Π΄Π°Π½Π½Ρ‹Π΅
df_categorical.insert(1, 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2', spy_columns['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2']) #добавляСм Π²Ρ‚ΠΎΡ€ΡƒΡŽ ΠΊΠΎΠ»ΠΎΠ½ΠΊΡƒ-шпион Π² качСствСнныС Π΄Π°Π½Π½Ρ‹Π΅
df_categorical.insert(1, 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3', spy_columns['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3']) #добавляСм Ρ‚Ρ€Π΅Ρ‚ΡŒΡŽ ΠΊΠΎΠ»ΠΎΠ½ΠΊΡƒ-шпион Π² качСствСнныС Π΄Π°Π½Π½Ρ‹Π΅

Infine, abbiamo completamente separato i dati quantitativi da quelli qualitativi e ora possiamo lavorarci correttamente. La prima cosa Γ¨ capire dove abbiamo valori vuoti (NaN, e in alcuni casi 0 saranno accettati come valori vuoti).

for i in df_numerical.columns:
    print(i, df[i][df[i]==0].count())

A questo punto Γ¨ importante capire in quali colonne gli zeri possono indicare valori mancanti: Γ¨ dovuto a come sono stati raccolti i dati? O potrebbe essere correlato ai valori dei dati? A queste domande bisogna rispondere caso per caso.

Quindi, se decidiamo ancora che potrebbero mancare dati dove sono presenti zeri, dovremmo sostituire gli zeri con NaN per rendere piΓΉ semplice lavorare con questi dati persi in seguito:

df_numerical[["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 1", "ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 2"]] = df_numerical[["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 1", "ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 2"]].replace(0, nan)

Ora vediamo dove mancano i dati:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # МоТно Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ df_numerical.info()

Foglio informativo del blocco note per una rapida preelaborazione dei dati

Qui quei valori all'interno delle colonne che mancano dovrebbero essere contrassegnati in giallo. E ora inizia il divertimento: come affrontare questi valori? Devo eliminare righe con questi valori o colonne? O riempire questi valori vuoti con altri?

Ecco un diagramma approssimativo che puΓ² aiutarti a decidere cosa si puΓ² fare, in linea di principio, con valori vuoti:

Foglio informativo del blocco note per una rapida preelaborazione dei dati

0. Rimuovere le colonne non necessarie

df_numerical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True)

1. Il numero di valori vuoti in questa colonna Γ¨ superiore al 50%?

print(df_numerical.isnull().sum() / df_numerical.shape[0] * 100)

df_numerical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True)#УдаляСм, Ссли какая-Ρ‚ΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° ΠΈΠΌΠ΅Π΅Ρ‚ большС 50 пустых Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ

2. Elimina le righe con valori vuoti

df_numerical.dropna(inplace=True)#УдаляСм строчки с пустыми значСниями, Ссли ΠΏΠΎΡ‚ΠΎΠΌ останСтся достаточно Π΄Π°Π½Π½Ρ‹Ρ… для обучСния

3.1. Inserimento di un valore casuale

import random #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ random
df_numerical["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"].fillna(lambda x: random.choice(df[df[column] != np.nan]["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"]), inplace=True) #вставляСм Ρ€Π°Π½Π΄ΠΎΠΌΠ½Ρ‹Π΅ значСния Π² пустыС ΠΊΠ»Π΅Ρ‚ΠΊΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹

3.2. Inserimento di un valore costante

from sklearn.impute import SimpleImputer #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ SimpleImputer, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π²ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ значСния
imputer = SimpleImputer(strategy='constant', fill_value="<Π’Π°ΡˆΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ здСсь>") #вставляСм ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ SimpleImputer
df_numerical[["новая_ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1",'новая_ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2','новая_ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3']] = imputer.fit_transform(df_numerical[['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1', 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2', 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3']]) #ΠŸΡ€ΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ это для нашСй Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹
df_numerical.drop(labels = ["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3"], axis = 1, inplace = True) #Π£Π±ΠΈΡ€Π°Π΅ΠΌ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ со старыми значСниями

3.3. Inserisci il valore medio o piΓΉ frequente

from sklearn.impute import SimpleImputer #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ SimpleImputer, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π²ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ значСния
imputer = SimpleImputer(strategy='mean', missing_values = np.nan) #вмСсто mean ΠΌΠΎΠΆΠ½ΠΎ Ρ‚Π°ΠΊΠΆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ most_frequent
df_numerical[["новая_ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1",'новая_ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2','новая_ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3']] = imputer.fit_transform(df_numerical[['ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1', 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2', 'ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3']]) #ΠŸΡ€ΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ это для нашСй Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹
df_numerical.drop(labels = ["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3"], axis = 1, inplace = True) #Π£Π±ΠΈΡ€Π°Π΅ΠΌ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ со старыми значСниями

3.4. Inserire il valore calcolato da un altro modello

A volte i valori possono essere calcolati utilizzando modelli di regressione utilizzando modelli della libreria sklearn o altre librerie simili. Il nostro team dedicherΓ  un articolo separato su come ciΓ² possa essere fatto nel prossimo futuro.

Quindi, per ora, la narrazione sui dati quantitativi verrΓ  interrotta, perchΓ© ci sono molte altre sfumature su come eseguire al meglio la preparazione e la preelaborazione dei dati per compiti diversi, e gli aspetti fondamentali per i dati quantitativi sono stati presi in considerazione in questo articolo, e ora Γ¨ il momento di ritornare ai dati qualitativi, che abbiamo separato parecchi passi indietro da quelli quantitativi. Puoi modificare questo taccuino come preferisci, adattandolo a compiti diversi, in modo che la preelaborazione dei dati avvenga molto rapidamente!

Dati qualitativi

Fondamentalmente, per i dati qualitativi, viene utilizzato il metodo One-hot-encoding per formattarli da una stringa (o oggetto) a un numero. Prima di passare a questo punto, utilizziamo il diagramma e il codice sopra per gestire i valori vuoti.

df_categorical.nunique()

sns.heatmap(df_categorical.isnull(),yticklabels=False,cbar=False,cmap='viridis')

Foglio informativo del blocco note per una rapida preelaborazione dei dati

0. Rimuovere le colonne non necessarie

df_categorical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True)

1. Il numero di valori vuoti in questa colonna Γ¨ superiore al 50%?

print(df_categorical.isnull().sum() / df_numerical.shape[0] * 100)

df_categorical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True) #УдаляСм, Ссли какая-Ρ‚ΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 
                                                                          #ΠΈΠΌΠ΅Π΅Ρ‚ большС 50% пустых Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ

2. Elimina le righe con valori vuoti

df_categorical.dropna(inplace=True)#УдаляСм строчки с пустыми значСниями, 
                                   #Ссли ΠΏΠΎΡ‚ΠΎΠΌ останСтся достаточно Π΄Π°Π½Π½Ρ‹Ρ… для обучСния

3.1. Inserimento di un valore casuale

import random
df_categorical["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"].fillna(lambda x: random.choice(df[df[column] != np.nan]["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"]), inplace=True)

3.2. Inserimento di un valore costante

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='constant', fill_value="<Π’Π°ΡˆΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ здСсь>")
df_categorical[["новая_колонка1",'новая_колонка2','новая_колонка3']] = imputer.fit_transform(df_categorical[['колонка1', 'колонка2', 'колонка3']])
df_categorical.drop(labels = ["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3"], axis = 1, inplace = True)

Quindi, finalmente siamo riusciti a gestire i valori nulli nei dati qualitativi. Ora Γ¨ il momento di eseguire la codifica a caldo sui valori presenti nel tuo database. Questo metodo viene utilizzato molto spesso per garantire che il tuo algoritmo possa apprendere da dati di alta qualitΓ .

def encode_and_bind(original_dataframe, feature_to_encode):
    dummies = pd.get_dummies(original_dataframe[[feature_to_encode]])
    res = pd.concat([original_dataframe, dummies], axis=1)
    res = res.drop([feature_to_encode], axis=1)
    return(res)

features_to_encode = ["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°3"]
for feature in features_to_encode:
    df_categorical = encode_and_bind(df_categorical, feature))

Quindi, abbiamo finalmente finito di elaborare dati qualitativi e quantitativi separati: Γ¨ ora di combinarli di nuovo

new_df = pd.concat([df_numerical,df_categorical], axis=1)

Dopo aver combinato i set di dati in uno solo, possiamo finalmente utilizzare la trasformazione dei dati utilizzando MinMaxScaler dalla libreria sklearn. CiΓ² renderΓ  i nostri valori compresi tra 0 e 1, il che aiuterΓ  durante l'addestramento del modello in futuro.

from sklearn.preprocessing import MinMaxScaler
min_max_scaler = MinMaxScaler()
new_df = min_max_scaler.fit_transform(new_df)

Questi dati sono ora pronti per tutto: reti neurali, algoritmi ML standard, ecc.!

In questo articolo non abbiamo preso in considerazione il lavoro con dati di serie temporali, poichΓ© per tali dati Γ¨ necessario utilizzare tecniche di elaborazione leggermente diverse, a seconda dell'attivitΓ . In futuro, il nostro team dedicherΓ  un articolo separato a questo argomento e speriamo che possa portare qualcosa di interessante, nuovo e utile nella tua vita, proprio come questo.

Fonte: habr.com

Aggiungi un commento