Bloček za brzu pripremu podataka

Často majú ľudia, ktorí sa dostávajú do oblasti Data Science, nerealistické predstavy o tom, čo ich čaká. Mnohí si myslia, že teraz budú skvelo písať neurónové siete, vytvárať hlasového asistenta ako Iron Man alebo porážajú všetkých na finančných trhoch.
Ale práca Data Scientist sa zakladá na údajoch, a jedným z najdôležitejších a časovo náročných momentov je spracovanie údajov pred tým, ako ich dodáme do neurónovej siete alebo analyzujeme určitým spôsobom.

V tomto článku náš tím popíše, ako možno jednoducho a rýchlo spracovať údaje s podrobným návodom a kódom. Snažili sme sa, aby bol kód dosť flexibilný a mohol byť použitý pre rôzne datasety.

Mnohí profesionáli možno nenájdu nič mimoriadne v tomto článku, ale začiatočníci si môžu niečo nové osvojiť, a tiež každý, kto už dlho sníval o vytvorení samostatného notebooku pre rýchle a štruktúrované spracovanie údajov, si môže skopírovať kód a prispôsobiť ho podľa seba, alebo stiahnuť hotový notebook z Githubu.

Získali sme dataset. Čo robiť ďalej?

Takže, štandard: musíme pochopiť, s čím máme dočinenia, celkový prehľad. Na to využijeme pandas, aby sme jednoducho zistili rôzne typy údajov.

import pandas as pd #importujeme pandas
import numpy as np  #importujeme numpy
df = pd.read_csv("AB_NYC_2019.csv") #čítať dataset a uložiť do premennej df

df.head(3) #pozrieme sa na prvé 3 riadky, aby sme pochopili, aké sú hodnoty

Bloček za brzu pripremu podataka

df.info() #Zobrazujeme informácie o stĺpcoch

Bloček za brzu pripremu podataka

Pozrime sa na hodnoty stĺpcov:

  1. Zodpovedá počet riadkov v každom stĺpci celkovému počtu riadkov?
  2. Aká je podstata údajov v každom stĺpci?
  3. Ktorý stĺpec chceme urobiť target, aby sme mohli robiť predpovede preň?

Odpovede na tieto otázky nám umožnia analyzovať dataset a približne nakresliť plán najbližších krokov.

Taktiež, pre hlbší pohľad na hodnoty v každom stĺpci, môžeme použiť funkciu pandas describe(). Avšak nevýhodou tejto funkcie je, že neposkytuje informácie o stĺpcoch s hodnotami typu string. S tými sa vysporiadame neskôr.

df.describe()

Bloček za brzu pripremu podataka

Kúzelná vizualizácia

Pozrime sa na to, kde nám úplne chýbajú hodnoty:

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

Bloček za brzu pripremu podataka

Toto bol malý pohľad zhora, teraz sa pustíme do zaujímavejších vecí.

Pokúsime sa nájsť a pokiaľ je to možné, odstrániť stĺpce, v ktorých sa nachádza len jedna hodnota vo všetkých riadkoch (nebudú mať žiaden vplyv na výsledok):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #Prepisujeme dataset, aby sme si ponechali iba tie stĺpce, kde je viac ako jedna unikátna hodnota

Teraz si chránime seba a úspech nášho projektu pred duplicitnými riadkami (riadkami, ktoré obsahujú rovnaké informácie v rovnakom poradí ako už existujúci riadok):

df.drop_duplicates(inplace=True) #Robíme to, ak to považujeme za potrebné.
                                 #V niektorých projektoch nemá zmysel odstraňovať takéto dáta hneď na začiatku.

Rozdeľujeme dataset na dva: jeden s kvalitnými hodnotami a druhý — s kvantitatívnymi.

Tu je potrebné urobiť malé upresnenie: ak sú riadky s chýbajúcimi dátami u kvalitných a kvantitatívnych údajov veľmi málo prepojené, bude potrebné rozhodnúť, čím obetujeme — všetkými riadkami s chýbajúcimi údajmi, len ich časťou alebo konkrétnymi stĺpcami. Ak sú však riadky prepojené, máme plné právo rozdeliť dataset na dva. Inak by sme sa najprv mali zaoberať riadkami, v ktorých nie sú prepojené chýbajúce údaje v kvalitných a kvantitatívnych, a až potom rozdeliť dataset na dva.

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

Robíme to, aby sme si uľahčili spracovanie týchto dvoch rôznych typov údajov — neskôr zistíme, ako veľmi nám to uľahčuje život.

Pracujeme s kvantitatívnymi údajmi

Prvé, čo by sme mali urobiť — určiť, či neexistujú "špionážne stĺpce" v kvantitatívnych údajoch. Tieto stĺpce nazývame tak, pretože predstierajú, že sú kvantitatívne údaje, zatiaľ čo v skutočnosti fungujú ako kvalitné.

Ako ich určiť? Samozrejme, všetko závisí od povahy údajov, ktoré analyzujete, ale väčšinou také stĺpce môžu mať málo unikátnych údajov (okolo 3-10 unikátnych hodnôt).

print(df_numerical.nunique())

Akonáhle určíme špionážne stĺpce, presunieme ich z kvantitatívnych údajov do kvalitných:

spy_columns = df_numerical[['stĺpec1', 'stĺpec2', 'stĺpec3']]#vyberáme stĺpce-špehov a zapisujeme do samostatného dataframe
df_numerical.drop(labels=['stĺpec1', 'stĺpec2', 'stĺpec3'], axis=1, inplace = True)#vydávame tieto stĺpce z kvantitatívnych dát
df_categorical.insert(1, 'stĺpec1', spy_columns['stĺpec1']) #pridávame prvý stĺpec-špeh do kvalitných dát
df_categorical.insert(1, 'stĺpec2', spy_columns['stĺpec2']) #pridávame druhý stĺpec-špeh do kvalitných dát
df_categorical.insert(1, 'stĺpec3', spy_columns['stĺpec3']) #pridávame tretí stĺpec-špeh do kvalitných dát

Konečne sme úplne oddelili kvantitatívne dáta od kvalitných a teraz s nimi môžeme poriadne pracovať. Prvé — je potrebné pochopiť, kde máme prázdne hodnoty (NaN, a v niektorých prípadoch aj 0 budú akceptované ako prázdne hodnoty).

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

V tomto štádiu je dôležité pochopiť, v ktorých stĺpcoch môžu nuly znamenať chýbajúce hodnoty: súvisí to s tým, ako sa dáta zbierali? Alebo to môže byť spojené s hodnotami dát? Na tieto otázky je potrebné odpovedať v každom jednotlivom prípade.

Takže ak sme sa naozaj rozhodli, že dáta môžu chýbať tam, kde sú nuly, je potrebné nahradiť nuly za NaN, aby sme sa s týmito stratami dalo lepšie pracovať:

df_numerical[["stĺpec 1", "stĺpec 2"]] = df_numerical[["stĺpec 1", "stĺpec 2"]].replace(0, nan)

Teraz sa pozrime, kde máme chýbajúce dáta:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # Môžeme sa tiež pozrieť na df_numerical.info()

Bloček za brzu pripremu podataka

Tu by mali byť označené žltou farbou tie hodnoty vo vnútri stĺpcov, ktoré chýbajú. A to najzaujímavejšie prichádza teraz — ako sa správať k týmto hodnotám? Odstrániť riadky s týmito hodnotami alebo stĺpce? Alebo vyplniť tieto prázdne hodnoty nejakými inými?

Tu je približný návod, ktorý vám môže pomôcť rozhodnúť sa, čo sa s prázdnymi hodnotami dá v zásade robiť:

Bloček za brzu pripremu podataka

0. Odstraňujeme nepotrebné stĺpce

df_numerical.drop(labels=["stĺpec1","stĺpec2"], axis=1, inplace=True)

1. Je počet prázdnych hodnôt v tomto stĺpci vyšší ako 50 %?

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

df_numerical.drop(labels=["stĺpec1","stĺpec2"], axis=1, inplace=True)#Odstráňte, ak má nejaký stĺpec viac ako 50 prázdnych hodnôt

2. Odstraňujeme riadky s prázdnymi hodnotami

df_numerical.dropna(inplace=True) # Odstránime riadky s prázdnymi hodnotami, ak ostane dostatok dát na učenie.

3.1. Vloženie náhodnej hodnoty

import random # importujeme random
df_numerical["stĺpec"].fillna(lambda x: random.choice(df[df[column] != np.nan]["stĺpec"]), inplace=True) # vkladáme náhodné hodnoty do prázdnych buniek tabuľky

3.2. Vloženie konštantnej hodnoty

from sklearn.impute import SimpleImputer # importujeme SimpleImputer, ktorý pomôže vložiť hodnoty
imputer = SimpleImputer(strategy='constant', fill_value="") # vkladáme stanovenú hodnotu pomocou SimpleImputer
df_numerical[["nový_stĺpec1", 'nový_stĺpec2', 'nový_stĺpec3']] = imputer.fit_transform(df_numerical[['stĺpec1', 'stĺpec2', 'stĺpec3']]) # Aplikujeme to na našu tabuľku
df_numerical.drop(labels=["stĺpec1", "stĺpec2", "stĺpec3"], axis=1, inplace=True) # Odstránime stĺpce so starými hodnotami

3.3. Vloženie priemernej alebo najčastejšej hodnoty

from sklearn.impute import SimpleImputer # importujeme SimpleImputer, ktorý pomôže vložiť hodnoty
imputer = SimpleImputer(strategy='mean', missing_values=np.nan) # namiesto mean môžeme tiež použiť most_frequent
df_numerical[["nový_stĺpec1", 'nový_stĺpec2', 'nový_stĺpec3']] = imputer.fit_transform(df_numerical[['stĺpec1', 'stĺpec2', 'stĺpec3']]) # Aplikujeme to na našu tabuľku
df_numerical.drop(labels=["stĺpec1", "stĺpec2", "stĺpec3"], axis=1, inplace=True) # Odstránime stĺpce so starými hodnotami

3.4. Vloženie hodnoty vypočítanej iným modelom

Niekedy je možné vypočítať hodnoty pomocou regresných modelov, využívajúc modely z knižnice sklearn alebo iných podobných knižníc. Naša tím sa plánuje venovať samostatnému článku o tom, ako to možné urobiť v blízkej budúcnosti.

Takže, zatiaľ sa príbeh o kvantitatívnych datoach preruší, pretože existencia mnohých iných aspektov, ako lepšie vykonávať prípravu a predspracovanie dát pre rôzne úlohy, a základné veci pre kvantitatívne dáta boli uvedené v tomto článku; a teraz je čas vrátiť sa k kvalitatívnym dátam, ktoré sme pred niekoľkými krokmi oddelili od kvantitatívnych. Môžete upraviť tento notebook podľa svojich predstáv a prispôsobovať ho rôznym úlohám, aby predspracovanie dát prebiehalo veľmi rýchlo!

Kvalitatívne dáta

Hlavne na kvalitné dáta sa používa metóda One-hot-encoding na ich formátovanie zo string (alebo object) na číslo. Predtým, ako prejdeme k tejto téme, využijeme schému a kód vyššie, aby sme sa vysporiadali s prázdnymi hodnotami.

df_categorical.nunique()

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

Bloček za brzu pripremu podataka

0. Odstraňujeme nepotrebné stĺpce

df_categorical.drop(labels=["stĺpec1","stĺpec2"], axis=1, inplace=True)

1. Je počet prázdnych hodnôt v tomto stĺpci vyšší ako 50 %?

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

df_categorical.drop(labels=["stĺpec1","stĺpec2"], axis=1, inplace=True) #Odstraňujeme, ak nejaký stĺpec 
                                                                          #má viac ako 50% prázdnych hodnôt

2. Odstraňujeme riadky s prázdnymi hodnotami

df_categorical.dropna(inplace=True)#Odstraňujeme riadky s prázdnymi hodnotami, 
                                   #ak potom zostane dosť dát na učenie

3.1. Vloženie náhodnej hodnoty

import random
df_categorical["stĺpec"].fillna(lambda x: random.choice(df[df[column] != np.nan]["stĺpec"]), inplace=True)

3.2. Vloženie konštantnej hodnoty

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='constant', fill_value="")
df_categorical[["nový_stĺpec1",'nový_stĺpec2','nový_stĺpec3']] = imputer.fit_transform(df_categorical[['stĺpec1', 'stĺpec2', 'stĺpec3']])
df_categorical.drop(labels = ["stĺpec1","stĺpec2","stĺpec3"], axis = 1, inplace = True)

Takže sme sa konečne vysporiadali s prázdnymi hodnotami v kvalitných dátach. Teraz je čas vykonať one-hot-encoding pre hodnoty, ktoré máte vo svojej databáze. Táto metóda sa veľmi často používa, aby váš algoritmus mohol učiť s ohľadom na kvalitatívne dáta.

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 = ["stĺpec1","stĺpec2","stĺpec3"]
for feature in features_to_encode:
    df_categorical = encode_and_bind(df_categorical, feature))

Tak sme konečne dokončili spracovanie kvalitných a kvantitatívnych dát oddelene — teraz je čas ich znova spojiť

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

Po tom, čo sme spojili datasety do jedného, môžeme na konci využiť transformáciu dát pomocou MinMaxScaler z knižnice sklearn. To nastaví naše hodnoty v rozmedzí od 0 do 1, čo pomôže pri učení modelu v budúcnosti.

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

Tieto dáta sú teraz pripravené na všetko — na neurónové siete, štandardné ML algoritmy atď!

V tomto článku sme sa nezamerali na prácu s údajmi týkajúcimi sa časových radov, pretože na takéto údaje by sa mali používať trochu iné techniky spracovania, v závislosti od vašej úlohy. Naša tím sa v budúcnosti tejto téme venuje samostatný článok a dúfame, že prinesie do vášho života niečo zaujímavé, nové a užitočné, ako aj tento.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster