Notepad-petuleht andmete kiireks eeltöötluseks

Sageli on andmeteaduse valdkonda tulijatel vähem kui realistlikud ootused selle suhtes, mis neid ees ootab. Paljud inimesed arvavad, et nüüd hakkavad nad kirjutama lahedaid närvivõrke, looma Raudmehest hääleassistendi või lööma kõiki finantsturgudel.
Aga töö kuupäev Teadlane on andmepõhine ning üks olulisemaid ja aeganõudvamaid aspekte on andmete töötlemine enne nende sisestamist närvivõrku või teatud viisil analüüsimist.

Selles artiklis kirjeldab meie meeskond, kuidas saate üksikasjalike juhiste ja koodi abil kiiresti ja lihtsalt andmeid töödelda. Püüdsime muuta koodi üsna paindlikuks ja seda saaks kasutada erinevate andmekogumite jaoks.

Paljud spetsialistid ei pruugi sellest artiklist midagi erakordset leida, kuid algajad saavad õppida midagi uut ja igaüks, kes on juba ammu unistanud eraldi märkmiku valmistamisest kiireks ja struktureeritud andmetöötluseks, saab koodi kopeerida ja enda jaoks vormindada või laadige Githubist alla valmis märkmik.

Saime andmestiku kätte. Mida edasi teha?

Niisiis, standard: me peame mõistma, millega me tegeleme, üldpilti. Selleks kasutame pandasid, et lihtsalt määratleda erinevad andmetüübid.

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

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

Notepad-petuleht andmete kiireks eeltöötluseks

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

Notepad-petuleht andmete kiireks eeltöötluseks

Vaatame veergude väärtusi:

  1. Kas ridade arv igas veerus vastab ridade koguarvule?
  2. Mis on iga veeru andmete olemus?
  3. Millist veergu tahame sihtida, et selle kohta ennustusi teha?

Vastused neile küsimustele võimaldavad teil andmestikku analüüsida ja koostada umbkaudselt plaani oma järgmisteks tegevusteks.

Samuti võime iga veeru väärtuste põhjalikumaks vaatamiseks kasutada funktsiooni pandad description(). Selle funktsiooni puuduseks on aga see, et see ei anna teavet stringiväärtustega veergude kohta. Nendega tegeleme hiljem.

df.describe()

Notepad-petuleht andmete kiireks eeltöötluseks

Maagiline visualiseerimine

Vaatame, kus meil pole üldse väärtusi:

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

Notepad-petuleht andmete kiireks eeltöötluseks

See oli lühike pilk ülalt, nüüd läheme huvitavamate asjade juurde

Proovime leida ja võimalusel eemaldada veerud, millel on kõikides ridades ainult üks väärtus (need ei mõjuta tulemust kuidagi):

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

Nüüd kaitseme ennast ja oma projekti edu dubleerivate ridade eest (read, mis sisaldavad sama teavet samas järjekorras kui üks olemasolevatest ridadest):

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

Jagame andmekogumi kaheks: üks kvalitatiivsete väärtustega ja teine ​​kvantitatiivsete väärtustega

Siin on vaja teha väike täpsustus: kui kvalitatiivsete ja kvantitatiivsete andmete puuduvate andmete read ei ole üksteisega väga korrelatsioonis, siis peame otsustama, mida me ohverdame - kõik read, kus puuduvad andmed, ainult osa neist, või teatud veerud. Kui read on korrelatsioonis, on meil täielik õigus jagada andmestik kaheks. Vastasel juhul peate esmalt tegelema ridadega, mis ei korreleeri puuduvaid andmeid kvalitatiivselt ja kvantitatiivselt, ja alles seejärel jagage andmestik kaheks.

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

Teeme seda selleks, et neid kahte erinevat tüüpi andmeid oleks meil lihtsam töödelda – hiljem saame aru, kui palju see meie elu lihtsamaks teeb.

Töötame kvantitatiivsete andmetega

Esimene asi, mida peaksime tegema, on kindlaks teha, kas kvantitatiivsetes andmetes on spiooniveerge. Nimetame neid veerge nii, kuna need esitavad end kvantitatiivsete andmetena, kuid toimivad kvalitatiivsete andmetena.

Kuidas me neid defineerime? Muidugi oleneb see kõik analüüsitavate andmete olemusest, kuid üldiselt võib sellistes veergudes olla vähe unikaalseid andmeid (3–10 kordumatut väärtust).

print(df_numerical.nunique())

Kui oleme spiooniveerud tuvastanud, teisaldame need kvantitatiivsetelt andmetelt kvalitatiivsetele andmetele:

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

Lõpuks oleme kvantitatiivsed andmed kvalitatiivsetest andmetest täielikult eraldanud ja nüüd saame nendega korralikult töötada. Esimene asi on mõista, kus meil on tühjad väärtused (NaN ja mõnel juhul 0 aktsepteeritakse tühja väärtustena).

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

Siinkohal on oluline mõista, millistes veergudes võivad nullid näidata puuduvaid väärtusi: kas see on tingitud andmete kogumise viisist? Või võib see olla seotud andmeväärtustega? Nendele küsimustele tuleb vastata igal üksikjuhul eraldi.

Seega, kui me siiski otsustame, et meil võivad nullidega andmed puududa, peaksime nullid asendama NaN-ga, et hiljem oleks lihtsam nende kadunud andmetega töötada:

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

Nüüd vaatame, kus meil andmed puuduvad:

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

Notepad-petuleht andmete kiireks eeltöötluseks

Siin tuleks need veergude sees puuduvad väärtused märkida kollasega. Ja nüüd algab lõbu – kuidas nende väärtustega toime tulla? Kas peaksin kustutama nende väärtustega read või veerud? Või täita need tühjad väärtused mõne muuga?

Siin on ligikaudne diagramm, mis aitab teil otsustada, mida saab põhimõtteliselt teha tühjade väärtustega:

Notepad-petuleht andmete kiireks eeltöötluseks

0. Eemaldage mittevajalikud veerud

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

1. Kas tühjade väärtuste arv selles veerus on suurem kui 50%?

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

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

2. Kustutage tühjade väärtustega read

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

3.1. Juhusliku väärtuse sisestamine

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

3.2. Konstantse väärtuse sisestamine

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. Sisestage keskmine või kõige sagedasem väärtus

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. Sisestage teise mudeliga arvutatud väärtus

Mõnikord saab väärtusi arvutada regressioonimudelite abil, kasutades sklearni teegi või muude sarnaste teekide mudeleid. Selle kohta, kuidas seda lähitulevikus teha, pühendab meie meeskond eraldi artikli.

Nii et praeguseks jääb kvantitatiivsete andmete jutustamine katkema, sest siin on palju muid nüansse, kuidas andmete ettevalmistamist ja eeltöötlust erinevate ülesannete jaoks paremini teha ning kvantitatiivsete andmete põhiasjad on selles artiklis arvesse võetud ning nüüd on aeg pöörduda tagasi kvalitatiivsete andmete juurde.mida eraldasime kvantitatiivsetest mitu sammu tagasi. Saate seda märkmikku oma äranägemise järgi muuta, kohandades seda erinevate ülesannete jaoks, et andmete eeltöötlus läheks väga kiiresti!

Kvalitatiivsed andmed

Põhimõtteliselt kasutatakse kvalitatiivsete andmete puhul One-hot-encoding meetodit, et vormindada need stringist (või objektist) numbriks. Enne selle punkti juurde liikumist kasutame tühjade väärtuste käsitlemiseks ülaltoodud diagrammi ja koodi.

df_categorical.nunique()

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

Notepad-petuleht andmete kiireks eeltöötluseks

0. Eemaldage mittevajalikud veerud

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

1. Kas tühjade väärtuste arv selles veerus on suurem kui 50%?

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

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

2. Kustutage tühjade väärtustega read

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

3.1. Juhusliku väärtuse sisestamine

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

3.2. Konstantse väärtuse sisestamine

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)

Niisiis, oleme lõpuks saanud hakkama kvalitatiivsete andmete nullidega. Nüüd on aeg teostada teie andmebaasis olevate väärtuste ühekordne kodeerimine. Seda meetodit kasutatakse väga sageli tagamaks, et teie algoritm saaks kvaliteetsetest andmetest õppida.

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

Niisiis, oleme lõpuks lõpetanud eraldi kvalitatiivsete ja kvantitatiivsete andmete töötlemise – on aeg need uuesti kombineerida

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

Kui oleme andmestikud üheks ühendanud, saame lõpuks kasutada andmete teisendamist sklearni teegist MinMaxScaleri abil. See muudab meie väärtused 0 ja 1 vahele, mis aitab tulevikus mudelit treenida.

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

Need andmed on nüüd valmis kõigeks – närvivõrkudeks, standardseteks ML-algoritmideks jne!

Selles artiklis me ei võtnud arvesse aegridade andmetega töötamist, kuna selliste andmete jaoks peaksite sõltuvalt teie ülesandest kasutama veidi erinevaid töötlemismeetodeid. Tulevikus pühendab meie meeskond sellele teemale eraldi artikli ja loodame, et see suudab teie ellu tuua midagi huvitavat, uut ja kasulikku, nagu seegi.

Allikas: www.habr.com

Lisa kommentaar