Tihti inimesed, kes siseneb andmete teaduse valdkonda, omavad ebatavalisi ootusi selle kohta, mis neid ees ootab. Paljud arvavad, et nad hakkavad kohe kirjutama keerulisi nÀrvivÔrke, looma raudmehe hÀÀlabilisi vÔi vÔidavad kÔiki finantsturgudel.
Kuid töö Andmed teadlasena on seotud andmetega, ning ĂŒks olulisemaid ja kĂ”ige ajakulukamaid hetki on andmete töötlemine enne nende sisestamist nĂ€rvivĂ”rku vĂ”i enne kindlal viisil analĂŒĂŒsimist.
Selles artiklis kirjeldab meie meeskond, kuidas andmeid lihtsalt ja kiiresti töödelda, et jĂ€lgida samm-sammult juhiseid ja koode. Oleme pĂŒĂŒdnud, et kood oleks piisavalt paindlik ja seda saaks kasutada erinevate andmekogumite jaoks.
Paljud spetsialistid ei pruugi selle artikli sisu leida midagi erakordset, kuid algajad saavad kindlasti midagi uut ja igaĂŒks, kes on pikka aega soovinud luua enda jaoks eraldi mĂ€rkmiku kiireks ja struktureeritud andmete töötlemiseks, saab koode kopeerida ja kohandada endale sobivaks, vĂ”i
Olete saanud andmekogumi. Mida edasi teha?
Seega, standart: tuleb mĂ”ista, millega meil tegu on, ĂŒldpilti. Selleks kasutame pandas't, et lihtsalt mÀÀrata erinevaid andmetĂŒĂŒpe.
import pandas as pd #impordime pandas
import numpy as np #impordime numpy
df = pd.read_csv("AB_NYC_2019.csv") #loeme andmestiku ja salvestame muutuja df
df.head(3) #vaatame kolme esimese rida, et mÔista, kuidas vÀÀrtused vÀlja nÀevad 
df.info() #Kuvame teavet veergude kohta 
Vaatame veergude vÀÀrtuseid:
- Kas iga veeru ridade arv vastab koguarvule ridadele?
- Mis on iga veeru andmete olemus?
- Millist veergu soovime teha sihiks, et teha ennustusi selle kohta?
Nendele kĂŒsimustele vastamine vĂ”imaldab analĂŒĂŒsida andmestikku ning koostada lĂŒhiajaline tegevuskava.
Samuti, et sĂŒgavamalt vaadata iga veeru vÀÀrtusi, saame kasutada pandas'i funktsiooni describe(). Kahjuks ei paku see funktsioon teavet string-vÀÀrtustega veergude kohta. Nendega tegeleme hiljem.
df.describe() 
Mugav visualiseerimine
Vaatame, kus meil puuduvad vÀÀrtused tÀielikult:
import seaborn as sns
sns.heatmap(df.isnull(), yticklabels=False, cbar=False, cmap='viridis') 
See oli vĂ€ike ĂŒlevaade, nĂŒĂŒd liikume huvitavamate asjade juurde
PĂŒĂŒame leida ja vĂ”imalusel eemaldada veerud, milles on ainult ĂŒks vÀÀrtus kĂ”igis ridades (need ei mĂ”juta tulemust):
df = df[[c for c
in list(df)
if len(df[c].unique()) > 1]] #Uuendame andmestikku, jĂ€ttes alles vaid need veerud, kus on rohkem kui ĂŒks unikaalne vÀÀrtusKaitseme end ja meie projekti edu duplikaatridade eest (ridade ees, mis sisaldavad sama teavet samas jĂ€rjekorras nagu juba olemasolevad read):
df.drop_duplicates(inplace=True) #Teeme seda, kui peame seda vajalikuks.
#MĂ”nes projektis ei ole otstarbekas selliseid andmeid alguses eemaldada.Jagame andmestiku kaheks: ĂŒks kvaliteetsete vÀÀrtuste jaoks ja teine kvantitatiivsete vÀÀrtuste jaoks
Siin on vajalik vĂ€ike tĂ€psustus: kui ridade vahel, kus on puudu andmeid kvalitatiivsete ja kvantitatiivsete andmete osas, ei ole tugev seos, siis tuleb otsustada, millest loobume â kas kĂ”igist puuduvate andmetega ridadest, ainult osast neist vĂ”i teatud veergudest. Kui read omavahel seonduvad, siis on meil tĂ€ielik Ă”igus jagada andmestiku kahte osa. Vastasel juhul tuleb esmalt lahendada read, kus kvalitatiivsetes ja kvantitatiivsetes andmetes puuduvad andmed ei seondu, ja alles seejĂ€rel jagada andmestik kahte osa.
df_numerical = df.select_dtypes(include = [np.number])
df_categorical = df.select_dtypes(exclude = [np.number])Teeme seda, et oleks kergem töötada nende kahe erineva andmeliigiga â hiljem mĂ”istame, kui palju see meie elu lihtsustab.
Töötame kvantitatiivsete andmetega
Esimene asi, mida peaksime teema, on mÀÀrata, kas kvantitatiivsetes andmetes on ânuhi-veergeâ. Me nimetame neid veerge nii, kuna nad annavad end vĂ€lja kvantitatiivsete andmetena, kuid töötavad tegelikult nagu kvaliteedilised.
Kuidas me need mÀÀratleme? Loomulikult sĂ”ltub kĂ”ik analĂŒĂŒsitavate andmete iseloomust, kuid peamiselt vĂ”ivad sellised veerud omada vĂ€he unikaalseid andmeid (umbes 3-10 unikaalset vÀÀrtust).
print(df_numerical.nunique())PÀrast seda, kui oleme mÀÀratlenud nuhkveerud, liigutame need kvantitatiivsetest andmetest kvalitatiivsetesse:
spy_columns = df_numerical[['veeru1', 'veeru2', 'veeru3']]#valime nuhkveerud ja salvestame need eraldi dataframe'iks
df_numerical.drop(labels=['veeru1', 'veeru2', 'veeru3'], axis=1, inplace=True)#kustutame need veerud kvantitatiivsetest andmetest
df_categorical.insert(1, 'veeru1', spy_columns['veeru1']) #lisame esimese nuhkveeru kvalitatiivsetesse andmetesse
df_categorical.insert(1, 'veeru2', spy_columns['veeru2']) #lisame teise nuhkveeru kvalitatiivsetesse andmetesse
df_categorical.insert(1, 'veeru3', spy_columns['veeru3']) #lisame kolmanda nuhkveeru kvalitatiivsetesse andmetesseSaime lĂ”puks tĂ€ielikult eraldada kvantitatiivsed andmed kvalitatiivsetest ning nĂŒĂŒd saame nendega korralikult töötada. Esiteks â tuleb mĂ”ista, kus meil on tĂŒhjad vÀÀrtused (NaN, ja mĂ”nel juhul tunneme 0 tĂŒhjade vÀÀrtustena).
for i in df_numerical.columns:
print(i, df[i][df[i]==0].count())Selles etapis on oluline mĂ”ista, millistes veergudes nullid vĂ”ivad tĂ€hendada puuduvaid vÀÀrtusi: kas see on seotud andmete kogumisega? VĂ”i vĂ”ivad need olla seotud andmete vÀÀrtustega? Neile kĂŒsimustele tuleb vastata igas eraldi juhus.
Nii et kui me oleme ikka jÔudnud jÀreldusele, et andmed vÔivad puududa seal, kus on nullid, tuleks nullid asendada NaN-iga, et oleks hiljem lihtsam töötada nende kadunud andmetega:
df_numerical[["veerg 1", "veerg 2"]] = df_numerical[["veerg 1", "veerg 2"]].replace(0, nan)NĂŒĂŒd vaatame, kus meil on puuduvad andmed:
sns.heatmap(df_numerical.isnull(), yticklabels=False, cbar=False, cmap='viridis') # Samuti saab kasutada df_numerical.info() 
Siin peaksid kollase vĂ€rviga olema mĂ€rgitud need vÀÀrtused veergudes, mis puuduvad. Ja nĂŒĂŒd algab kĂ”ige huvitavam osa â kuidas nende vÀÀrtustega kĂ€ituda? Kustutada need ridadega vĂ”i veergudega? VĂ”i tĂ€ita need tĂŒhjad vÀÀrtused millegagi?
Siin on ligikaudne skeem, mis vĂ”ib aidata teil otsustada, mida pĂ”himĂ”tteliselt teha tĂŒhjade vÀÀrtustega:

0. Kustutame mittevajalikud veerud
df_numerical.drop(labels=["veerg1", "veerg2"], axis=1, inplace=True)1. Kas selle veeru tĂŒhjade vÀÀrtuste arv ĂŒletab 50%?
print(df_numerical.isnull().sum() / df_numerical.shape[0] * 100)df_numerical.drop(labels=["veerg1", "veerg2"], axis=1, inplace=True) # Eemaldame, kui mĂ”nes veerus on rohkem kui 50 tĂŒhja vÀÀrtust2. Eemaldame tĂŒhjad vÀÀrtused ridadest
df_numerical.dropna(inplace=True) # Eemaldame tĂŒhjad vÀÀrtused ridadest, kui jÀÀb piisavalt andmeid koolituseks3.1. Sisestame juhusliku vÀÀrtuse
import random # impordime random
df_numerical["veerg"].fillna(lambda x: random.choice(df[df[column] != np.nan]["veerg"]), inplace=True) # sisestame juhuslikud vÀÀrtused tĂŒhjadesse lahtritesse3.2. Sisestame konstantsed vÀÀrtused
from sklearn.impute import SimpleImputer # impordime SimpleImputeri, mis aitab sisestada vÀÀrtusi
imputer = SimpleImputer(strategy='constant', fill_value="") # sisestame kindla vÀÀrtuse SimpleImputeriga
df_numerical[["uus_veerg1", 'uus_veerg2', 'uus_veerg3']] = imputer.fit_transform(df_numerical[['veerg1', 'veerg2', 'veerg3']]) # Rakendame seda meie tabelisse
df_numerical.drop(labels=["veerg1", "veerg2", "veerg3"], axis=1, inplace=True) # Eemaldame veerud vanade vÀÀrtustega3.3. Sisestame keskmise vÔi kÔige sagedasema vÀÀrtuse
from sklearn.impute import SimpleImputer # teiste vÀÀrtuste tÀitmiseks vajalik SimpleImputer imporditakse
imputer = SimpleImputer(strategy='mean', missing_values = np.nan) # mean'i asemel vÔib kasutada ka most_frequent
df_numerical[["uus_kategooria1", 'uus_kategooria2', 'uus_kategooria3']] = imputer.fit_transform(df_numerical[['kategooria1', 'kategooria2', 'kategooria3']]) # rakendame seda meie tabelis
df_numerical.drop(labels = ["kategooria1", "kategooria2", "kategooria3"], axis = 1, inplace = True) # eemaldame vanad vÀÀrtused3.4. Sisestame vÀÀrtuse, mille teine mudel on arvutanud
MĂ”nikord saab vÀÀrtusi arvutada regressioonimudelite abil, kasutades sklearn'i vĂ”i teiste sarnaste teekide mudeleid. Meie meeskond pĂŒhendab sellele teemale eraldi artikli lĂ€hitulevikus.
Nii et, kuigi kvantitatiivsete andmete jutustus katkeb, kuna on palju muid nĂŒansse, kuidas andmete ettevalmistamist ja eeltöötlemist erinevate ĂŒlesannete jaoks paremini teha, ja baasasjad kvantitatiivsete andmete jaoks on selles artiklis arvesse vĂ”etud, on nĂŒĂŒd Ă”ige aeg naasta kvalitatiivsete andmete juurde, mille me mĂ”ni samm tagasi kvantitatiivsetest eraldasime. Te saate seda notebook'i muuta nii, nagu soovite, kohandades seda erinevate ĂŒlesannete jaoks, et andmete eeltöötlemine toimuks vĂ€ga kiiresti!
Kvalitatiivsed andmed
Kvalitatiivsete andmete puhul kasutatakse peamiselt meetodit One-hot-encoding, et vormindada need string'idest (vĂ”i objektidest) numbriteks. Enne selle punkti juurde liikumist kasuta ĂŒleval olevat skeemi ja koodi, et tegeleda puuduva vÀÀrtusega.
df_categorical.nunique()sns.heatmap(df_categorical.isnull(), yticklabels=False, cbar=False, cmap='viridis') 
0. Kustutame mittevajalikud veerud
df_categorical.drop(labels=["ĐșĐŸĐ»ĐŸĐœĐșа1", "ĐșĐŸĐ»ĐŸĐœĐșа2"], axis=1, inplace=True)1. Kas selle veeru tĂŒhjade vÀÀrtuste arv ĂŒletab 50%?
print(df_categorical.isnull().sum() / df_numerical.shape[0] * 100)df_categorical.drop(labels=["ĐșĐŸĐ»ĐŸĐœĐșа1", "ĐșĐŸĐ»ĐŸĐœĐșа2"], axis=1, inplace=True) # Eemaldame, kui mĂ”nes tulbas on rohkem kui 50% tĂŒhje vÀÀrtusi2. Eemaldame tĂŒhjad vÀÀrtused ridadest
df_categorical.dropna(inplace=True)#Eemame tĂŒhjad read,
#kui jÀÀb piisavalt andmeid Ôppimiseks3.1. Sisestame juhusliku vÀÀrtuse
import random
df_categorical["veerg"].fillna(lambda x: random.choice(df[df[column] != np.nan]["veerg"]), inplace=True)3.2. Sisestame konstantsed vÀÀrtused
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='constant', fill_value="")
df_categorical[["uus_veerg1", 'uus_veerg2', 'uus_veerg3']] = imputer.fit_transform(df_categorical[['veerg1', 'veerg2', 'veerg3']])
df_categorical.drop(labels=["veerg1", "veerg2", "veerg3"], axis=1, inplace=True)Nii, lĂ”puks oleme saanud aru, kuidas tegeleda tĂŒhjade vÀÀrtustega kvalitatiivsetes andmetes. NĂŒĂŒd on aeg teostada one-hot-encoding vÀÀrtuste jaoks, mis teie andmebaasis on. See meetod on ÀÀrmisel sagedasel kasutusel, et teie algoritm saaks Ă”ppida kvalitatiivsete andmete arvestamisel.
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 = ["veerg1", "veerg2", "veerg3"]
for feature in features_to_encode:
df_categorical = encode_and_bind(df_categorical, feature)Nii, lĂ”puks oleme lĂ”petanud kvalitatiivsete ja kvantitatiivsete andmete töötlemise â aeg on need jĂ€lle kokku viia.
new_df = pd.concat([df_numerical,df_categorical], axis=1)PĂ€rast andmestike ĂŒhendamist ĂŒhte saab me kasutada andmete teisendamist MinMaxScaler abil, mis on saadaval sklearn raamatukogus. See aitab hoida meie vÀÀrtusi vahemikus 0 kuni 1, mis on kasulik mudeli koolitamiseks tulevikus.
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Ă”ikideks â nĂ€rvivĂ”rkude, standardsete ML algoritmide jne jaoks!
Selles artiklis ei ole me arvesse vĂ”tnud ajaseeriatega seotud andmete töötlemist, kuna selliste andmete korral tuleks kasutada veidi teisi töötlustehnikaid, sĂ”ltuvalt teie ĂŒlesandest. Tulevikus pĂŒhendab meie meeskond sellele teemale eraldi artikli, lootes, et see toob teie ellu midagi huvitavat, uut ja kasulikku, just nagu see.
Allikas: habr.com
