Bilježnica za brzu pretprocesiranje podataka

Često ljudi koji ulaze u područje znanosti o podacima imaju manje od realnih očekivanja o tome što ih čeka. Mnogi ljudi misle da će sada napisati cool neuronske mreže, stvoriti glasovnog asistenta iz Iron Mana ili pobijediti sve na financijskim tržištima.
Ali raditi Datum Znanstvenik je vođen podacima, a jedan od najvažnijih aspekata koji oduzima mnogo vremena je obrada podataka prije nego što se unesu u neuronsku mrežu ili analiziraju na određeni način.

U ovom će članku naš tim opisati kako možete brzo i jednostavno obraditi podatke pomoću detaljnih uputa i koda. Pokušali smo kod učiniti prilično fleksibilnim i da se može koristiti za različite skupove podataka.

Mnogi profesionalci možda neće pronaći ništa neobično u ovom članku, ali početnici će moći naučiti nešto novo, a svatko tko je dugo sanjao napraviti zasebnu bilježnicu za brzu i strukturiranu obradu podataka može kopirati kod i formatirati ga za sebe, ili preuzmite gotovu bilježnicu s Githuba.

Dobili smo skup podataka. Što učiniti sljedeće?

Dakle, standard: moramo razumjeti s čime imamo posla, cjelokupnu sliku. Da bismo to učinili, koristimo pande za jednostavno definiranje različitih tipova podataka.

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

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

Bilježnica za brzu pretprocesiranje podataka

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

Bilježnica za brzu pretprocesiranje podataka

Pogledajmo vrijednosti stupaca:

  1. Odgovara li broj redaka u svakom stupcu ukupnom broju redaka?
  2. Što je suština podataka u svakom stupcu?
  3. Koji stupac želimo ciljati kako bismo za njega napravili predviđanja?

Odgovori na ova pitanja omogućit će vam da analizirate skup podataka i grubo nacrtate plan za svoje sljedeće radnje.

Također, za dublji uvid u vrijednosti u svakom stupcu, možemo koristiti funkciju pandas describe(). Međutim, nedostatak ove funkcije je što ne pruža informacije o stupcima s vrijednostima niza. Kasnije ćemo se pozabaviti njima.

df.describe()

Bilježnica za brzu pretprocesiranje podataka

Čarobna vizualizacija

Pogledajmo gdje uopće nemamo vrijednosti:

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

Bilježnica za brzu pretprocesiranje podataka

Ovo je bio kratak pogled odozgo, sad ćemo prijeći na zanimljivije stvari

Pokušajmo pronaći i, ako je moguće, ukloniti stupce koji imaju samo jednu vrijednost u svim recima (ni na koji način neće utjecati na rezultat):

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

Sada štitimo sebe i uspjeh našeg projekta od dupliciranih redaka (redaka koji sadrže iste informacije istim redoslijedom kao neki od postojećih redaka):

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

Skup podataka dijelimo na dva dijela: jedan s kvalitativnim vrijednostima, a drugi s kvantitativnim

Ovdje trebamo napraviti malo pojašnjenje: ako reci s nedostajućim podacima u kvalitativnim i kvantitativnim podacima nisu baš međusobno povezani, tada ćemo morati odlučiti što ćemo žrtvovati - svi reci s nedostajućim podacima, samo dio njih, ili određene stupce. Ako su linije povezane, tada imamo puno pravo podijeliti skup podataka na dva dijela. U suprotnom, prvo ćete se morati pozabaviti retcima koji ne povezuju podatke koji nedostaju u kvalitativnom i kvantitativnom smislu, a tek onda podijeliti skup podataka na dva dijela.

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

To činimo kako bismo lakše obrađivali te dvije različite vrste podataka - kasnije ćemo shvatiti koliko nam to olakšava život.

Radimo s kvantitativnim podacima

Prvo što bismo trebali učiniti jest utvrditi postoje li u kvantitativnim podacima “špijunski stupci”. Ove stupce tako nazivamo jer se predstavljaju kao kvantitativni podaci, ali djeluju kao kvalitativni podaci.

Kako ih možemo identificirati? Naravno, sve ovisi o prirodi podataka koje analizirate, ali općenito takvi stupci mogu imati malo jedinstvenih podataka (u području od 3-10 jedinstvenih vrijednosti).

print(df_numerical.nunique())

Nakon što smo identificirali špijunske stupce, premjestit ćemo ih iz kvantitativnih podataka u kvalitativne podatke:

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

Konačno smo u potpunosti odvojili kvantitativne podatke od kvalitativnih podataka i sada s njima možemo ispravno raditi. Prva stvar je razumjeti gdje imamo prazne vrijednosti (NaN, au nekim slučajevima 0 će biti prihvaćene kao prazne vrijednosti).

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

U ovom trenutku važno je razumjeti u kojim stupcima nule mogu označavati nedostajuće vrijednosti: je li to zbog načina na koji su podaci prikupljeni? Ili bi to moglo biti povezano s vrijednostima podataka? Na ova se pitanja mora odgovoriti od slučaja do slučaja.

Dakle, ako ipak odlučimo da nam možda nedostaju podaci tamo gdje postoje nule, trebali bismo zamijeniti nule s NaN kako bismo kasnije olakšali rad s tim izgubljenim podacima:

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

Sada da vidimo gdje nam nedostaju podaci:

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

Bilježnica za brzu pretprocesiranje podataka

Ovdje one vrijednosti unutar stupaca koje nedostaju trebaju biti označene žutom bojom. I sad počinje zabava – kako se nositi s tim vrijednostima? Trebam li izbrisati retke s ovim vrijednostima ili stupce? Ili ispuniti ove prazne vrijednosti nekim drugim?

Ovdje je približni dijagram koji vam može pomoći da odlučite što se u načelu može učiniti s praznim vrijednostima:

Bilježnica za brzu pretprocesiranje podataka

0. Uklonite nepotrebne stupce

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

1. Je li broj praznih vrijednosti u ovom stupcu veći od 50%?

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

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

2. Izbrišite retke s praznim vrijednostima

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

3.1. Umetanje slučajne vrijednosti

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

3.2. Umetanje konstantne vrijednosti

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. Unesite prosječnu ili najčešću vrijednost

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. Unesite vrijednost izračunatu drugim modelom

Ponekad se vrijednosti mogu izračunati pomoću regresijskih modela pomoću modela iz knjižnice sklearn ili drugih sličnih biblioteka. Naš će tim u bliskoj budućnosti posvetiti poseban članak o tome kako se to može učiniti.

Dakle, za sada ćemo prekinuti narativ o kvantitativnim podacima, jer postoji mnogo drugih nijansi o tome kako bolje napraviti pripremu i pretprocesiranje podataka za različite zadatke, a osnovne stvari za kvantitativne podatke uzete su u obzir u ovom članku, i sada je vrijeme da se vratimo kvalitativnim podacima koje smo odvojili nekoliko koraka unatrag od kvantitativnih. Ovu bilježnicu možete mijenjati kako želite, prilagođavajući je različitim zadacima, tako da predobrada podataka ide vrlo brzo!

Kvalitativni podaci

U osnovi, za kvalitativne podatke koristi se metoda One-hot-encoding kako bi se formatirali iz niza (ili objekta) u broj. Prije nego prijeđemo na ovu točku, upotrijebimo gornji dijagram i kôd za rješavanje praznih vrijednosti.

df_categorical.nunique()

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

Bilježnica za brzu pretprocesiranje podataka

0. Uklonite nepotrebne stupce

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

1. Je li broj praznih vrijednosti u ovom stupcu veći od 50%?

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

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

2. Izbrišite retke s praznim vrijednostima

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

3.1. Umetanje slučajne vrijednosti

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

3.2. Umetanje konstantne vrijednosti

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)

Dakle, konačno smo se uhvatili u koštac s nulama u kvalitativnim podacima. Sada je vrijeme da izvršite one-hot-enkodiranje na vrijednostima koje se nalaze u vašoj bazi podataka. Ova se metoda vrlo često koristi kako bi se osiguralo da vaš algoritam može učiti iz podataka visoke kvalitete.

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

Dakle, konačno smo završili s obradom zasebnih kvalitativnih i kvantitativnih podataka - vrijeme je da ih ponovno kombiniramo

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

Nakon što smo spojili skupove podataka u jedan, konačno možemo koristiti transformaciju podataka koristeći MinMaxScaler iz knjižnice sklearn. Time će naše vrijednosti biti između 0 i 1, što će pomoći pri obučavanju modela u budućnosti.

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

Ovi su podaci sada spremni za sve - neuronske mreže, standardne ML algoritme itd.!

U ovom članku nismo uzeli u obzir rad s vremenskim serijama podataka, jer za takve podatke trebate koristiti malo drugačije tehnike obrade, ovisno o vašem zadatku. U budućnosti će naš tim ovoj temi posvetiti poseban članak i nadamo se da će moći unijeti nešto zanimljivo, novo i korisno u vaš život, baš kao što je ovaj.

Izvor: www.habr.com

Dodajte komentar