Notisblokk-jukseark for rask dataforbehandling

Ofte har folk som går inn i feltet Data Science mindre enn realistiske forventninger til hva som venter dem. Mange tror at nå skal de skrive kule nevrale nettverk, lage en stemmeassistent fra Iron Man, eller slå alle i finansmarkedene.
Men jobb Data Forsker er datadrevet, og en av de viktigste og mest tidkrevende aspektene er å behandle dataene før de mates inn i et nevralt nettverk eller analysere dem på en bestemt måte.

I denne artikkelen vil teamet vårt beskrive hvordan du kan behandle data raskt og enkelt med trinnvise instruksjoner og kode. Vi prøvde å gjøre koden ganske fleksibel og kunne brukes til forskjellige datasett.

Mange fagfolk finner kanskje ikke noe ekstraordinært i denne artikkelen, men nybegynnere vil kunne lære noe nytt, og alle som lenge har drømt om å lage en egen notatbok for rask og strukturert databehandling kan kopiere koden og formatere den for seg selv, eller last ned den ferdige notatboken fra Github.

Vi mottok datasettet. Hva skal jeg gjøre videre?

Så, standarden: vi må forstå hva vi har å gjøre med, helhetsbildet. For å gjøre dette bruker vi pandaer for ganske enkelt å definere forskjellige datatyper.

import pandas as pd #импортируем pandas
import numpy as np  #импортируем numpy
df = pd.read_csv("AB_NYC_2019.csv") #читаем датасет и записываем в переменную df

df.head(3) #смотрим на первые 3 строчки, чтобы понять, как выглядят значения

Notisblokk-jukseark for rask dataforbehandling

df.info() #Демонстрируем информацию о колонках

Notisblokk-jukseark for rask dataforbehandling

La oss se på kolonneverdiene:

  1. Tilsvarer antall linjer i hver kolonne det totale antallet linjer?
  2. Какова суть данных в каждой колонке?
  3. Hvilken kolonne ønsker vi å målrette mot for å komme med spådommer for den?

Svarene på disse spørsmålene lar deg analysere datasettet og grovt tegne en plan for dine neste handlinger.

For en dypere titt på verdiene i hver kolonne kan vi også bruke funksjonen pandas describe(). Ulempen med denne funksjonen er imidlertid at den ikke gir informasjon om kolonner med strengverdier. Vi skal håndtere dem senere.

df.describe()

Notisblokk-jukseark for rask dataforbehandling

Magisk visualisering

La oss se på hvor vi ikke har noen verdier i det hele tatt:

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

Notisblokk-jukseark for rask dataforbehandling

Dette var en kort titt ovenfra, nå skal vi gå videre til mer interessante ting

La oss prøve å finne og, hvis mulig, fjerne kolonner som bare har én verdi i alle rader (de vil ikke påvirke resultatet på noen måte):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #Перезаписываем датасет, оставляя только те колонки, в которых больше одного уникального значения

Nå beskytter vi oss selv og suksessen til prosjektet vårt fra dupliserte linjer (linjer som inneholder samme informasjon i samme rekkefølge som en av de eksisterende linjene):

df.drop_duplicates(inplace=True) #Делаем это, если считаем нужным.
                                 #В некоторых проектах удалять такие данные с самого начала не стоит.

Vi deler datasettet i to: en med kvalitative verdier, og den andre med kvantitative

Her må vi gjøre en liten avklaring: hvis linjene med manglende data i kvalitative og kvantitative data ikke er veldig korrelerte med hverandre, må vi bestemme hva vi ofrer - alle linjene med manglende data, bare en del av dem, eller visse kolonner. Hvis linjene er korrelerte, har vi full rett til å dele datasettet i to. Ellers må du først forholde deg til linjene som ikke korrelerer de manglende dataene i kvalitativ og kvantitativ, og først deretter dele datasettet i to.

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

Vi gjør dette for å gjøre det lettere for oss å behandle disse to forskjellige datatypene – senere vil vi forstå hvor mye enklere dette gjør livet vårt.

Vi jobber med kvantitative data

Det første vi bør gjøre er å finne ut om det er "spionkolonner" i de kvantitative dataene. Vi kaller disse kolonnene det fordi de presenterer seg selv som kvantitative data, men fungerer som kvalitative data.

Hvordan kan vi identifisere dem? Alt avhenger selvfølgelig av arten av dataene du analyserer, men generelt kan slike kolonner ha lite unike data (i området 3-10 unike verdier).

print(df_numerical.nunique())

Når vi har identifisert spionkolonnene, vil vi flytte dem fra kvantitative data til kvalitative data:

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']) #добавляем третью колонку-шпион в качественные данные

Til slutt har vi fullstendig skilt kvantitative data fra kvalitative data og nå kan vi jobbe skikkelig med det. Det første er å forstå hvor vi har tomme verdier (NaN, og i noen tilfeller vil 0 bli akseptert som tomme verdier).

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

På dette tidspunktet er det viktig å forstå i hvilke kolonner nuller kan indikere manglende verdier: skyldes dette hvordan dataene ble samlet inn? Eller kan det ha sammenheng med dataverdiene? Disse spørsmålene må besvares fra sak til sak.

Så hvis vi fortsatt bestemmer oss for at vi kanskje mangler data der det er nuller, bør vi erstatte nullene med NaN for å gjøre det lettere å jobbe med disse tapte dataene senere:

df_numerical[["колонка 1", "колонка 2"]] = df_numerical[["колонка 1", "колонка 2"]].replace(0, nan)

La oss nå se hvor vi mangler data:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # Можно также воспользоваться df_numerical.info()

Notisblokk-jukseark for rask dataforbehandling

Her skal de verdiene inne i kolonnene som mangler være merket med gult. Og nå begynner moroa - hvordan håndtere disse verdiene? Bør jeg slette rader med disse verdiene eller kolonnene? Eller fylle disse tomme verdiene med noen andre?

Her er et omtrentlig diagram som kan hjelpe deg med å bestemme hva som i prinsippet kan gjøres med tomme verdier:

Notisblokk-jukseark for rask dataforbehandling

0. Fjern unødvendige kolonner

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. Er antallet tomme verdier i denne kolonnen større enn 50 %?

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

df_numerical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)#Удаляем, если какая-то колонка имеет больше 50 пустых значений

2. Slett linjer med tomme verdier

df_numerical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, если потом останется достаточно данных для обучения

3.1. Setter inn en tilfeldig verdi

import random #импортируем random
df_numerical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True) #вставляем рандомные значения в пустые клетки таблицы

3.2. Sette inn en konstant verdi

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. Sett inn den gjennomsnittlige eller hyppigste verdien

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. Sett inn verdien beregnet av en annen modell

Noen ganger kan verdier beregnes ved hjelp av regresjonsmodeller ved bruk av modeller fra sklearn-biblioteket eller andre lignende biblioteker. Teamet vårt vil vie en egen artikkel om hvordan dette kan gjøres i nær fremtid.

Så foreløpig vil narrativet om kvantitative data bli avbrutt, fordi det er mange andre nyanser om hvordan man bedre kan gjøre dataforberedelse og forbehandling for forskjellige oppgaver, og de grunnleggende tingene for kvantitative data er tatt i betraktning i denne artikkelen, og nå er tiden inne for å gå tilbake til kvalitative data, som vi skilte flere skritt tilbake fra de kvantitative. Du kan endre denne notatboken som du vil, tilpasse den til forskjellige oppgaver, slik at dataforbehandlingen går veldig raskt!

Kvalitative data

I utgangspunktet, for kvalitative data, brukes One-hot-encoding-metoden for å formatere dem fra en streng (eller objekt) til et tall. Før vi går videre til dette punktet, la oss bruke diagrammet og koden ovenfor for å håndtere tomme verdier.

df_categorical.nunique()

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

Notisblokk-jukseark for rask dataforbehandling

0. Fjern unødvendige kolonner

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True)

1. Er antallet tomme verdier i denne kolonnen større enn 50 %?

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

df_categorical.drop(labels=["колонка1","колонка2"], axis=1, inplace=True) #Удаляем, если какая-то колонка 
                                                                          #имеет больше 50% пустых значений

2. Slett linjer med tomme verdier

df_categorical.dropna(inplace=True)#Удаляем строчки с пустыми значениями, 
                                   #если потом останется достаточно данных для обучения

3.1. Setter inn en tilfeldig verdi

import random
df_categorical["колонка"].fillna(lambda x: random.choice(df[df[column] != np.nan]["колонка"]), inplace=True)

3.2. Sette inn en konstant verdi

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)

Så vi har endelig fått tak i nullverdier i kvalitative data. Nå er det på tide å utføre én hot-encoding på verdiene som er i databasen din. Denne metoden brukes veldig ofte for å sikre at algoritmen din kan lære av data av høy kvalitet.

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))

Så, vi er endelig ferdige med å behandle separate kvalitative og kvantitative data - på tide å kombinere dem tilbake

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

Etter at vi har slått sammen datasettene til ett, kan vi endelig bruke datatransformasjon ved hjelp av MinMaxScaler fra sklearn-biblioteket. Dette vil gjøre verdiene våre mellom 0 og 1, noe som vil hjelpe når du trener modellen i fremtiden.

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

Disse dataene er nå klare for alt - nevrale nettverk, standard ML-algoritmer, etc.!

I denne artikkelen tok vi ikke hensyn til å jobbe med tidsseriedata, siden du for slike data bør bruke litt forskjellige behandlingsteknikker, avhengig av oppgaven din. I fremtiden vil teamet vårt vie en egen artikkel til dette emnet, og vi håper at det vil kunne bringe noe interessant, nytt og nyttig inn i livet ditt, akkurat som dette.

Kilde: www.habr.com

Legg til en kommentar