Notepad-trompanta folio por rapida datumpretigo

Ofte homoj enirantaj la kampon de Datuma Scienco havas malpli ol realismajn atendojn pri tio, kio atendas ilin. Multaj homoj pensas, ke nun ili skribos bonegajn neŭralajn retojn, kreos voĉan asistanton de Iron Man aŭ venkos ĉiujn en la financaj merkatoj.
Sed laboro datumoj Sciencisto estas datuma movita, kaj unu el la plej gravaj kaj tempopostulaj aspektoj estas prilaborado de la datumoj antaŭ ol enigi ĝin en neŭralan reton aŭ analizi ĝin laŭ certa maniero.

En Δ‰i tiu artikolo, nia teamo priskribos kiel vi povas prilabori datumojn rapide kaj facile per paŝo post paŝo instrukcioj kaj kodo. Ni provis fari la kodon sufiΔ‰e fleksebla kaj povus esti uzata por malsamaj datenoj.

Multaj profesiuloj eble ne trovas ion eksterordinaran en Δ‰i tiu artikolo, sed komencantoj povos lerni ion novan, kaj Δ‰iu, kiu longe revas fari apartan kajeron por rapida kaj strukturita datumtraktado, povas kopii la kodon kaj formati ĝin por si mem, aΕ­ elŝutu la finitan kajeron el Github.

Ni ricevis la datumaron. Kion fari poste?

Do, la normo: ni devas kompreni, kion ni traktas, la ĝeneralan bildon. Por fari tion, ni uzas pandojn por simple difini malsamajn datumtipojn.

import pandas as pd #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ pandas
import numpy as np  #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ numpy
df = pd.read_csv("AB_NYC_2019.csv") #Ρ‡ΠΈΡ‚Π°Π΅ΠΌ датасСт ΠΈ записываСм Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ df

df.head(3) #смотрим Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹Π΅ 3 строчки, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ½ΡΡ‚ΡŒ, ΠΊΠ°ΠΊ выглядят значСния

Notepad-trompanta folio por rapida datumpretigo

df.info() #ДСмонстрируСм ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°Ρ…

Notepad-trompanta folio por rapida datumpretigo

Ni rigardu la kolumnvalorojn:

  1. Ĉu la nombro da linioj en Δ‰iu kolumno respondas al la tuta nombro da linioj?
  2. Kio estas la esenco de la datumoj en Δ‰iu kolumno?
  3. Kiun kolumnon ni volas celi por fari antaŭdirojn pri ĝi?

La respondoj al Δ‰i tiuj demandoj permesos al vi analizi la datumaron kaj proksimume desegni planon por viaj venontaj agoj.

AnkaΕ­, por pli profunde rigardi la valorojn en Δ‰iu kolumno, ni povas uzi la funkcion describe() pandas. Tamen, la malavantaĝo de Δ‰i tiu funkcio estas ke ĝi ne provizas informojn pri kolumnoj kun kordaj valoroj. Ni traktos ilin poste.

df.describe()

Notepad-trompanta folio por rapida datumpretigo

Magia bildigo

Ni rigardu kie ni tute ne havas valorojn:

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

Notepad-trompanta folio por rapida datumpretigo

Ĉi tio estis mallonga rigardo de supre, nun ni transiros al pli interesaj aferoj

Ni provu trovi kaj, se eble, forigi kolumnojn kiuj havas nur unu valoron en Δ‰iuj vicoj (ili neniel influos la rezulton):

df = df[[c for c
        in list(df)
        if len(df[c].unique()) > 1]] #ΠŸΠ΅Ρ€Π΅Π·Π°ΠΏΠΈΡΡ‹Π²Π°Π΅ΠΌ датасСт, оставляя Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Π΅ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠΈ, Π² ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… большС ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния

Nun ni protektas nin kaj la sukceson de nia projekto kontraΕ­ duplikataj linioj (linioj, kiuj enhavas la samajn informojn en la sama ordo kiel unu el la ekzistantaj linioj):

df.drop_duplicates(inplace=True) #Π”Π΅Π»Π°Π΅ΠΌ это, Ссли считаСм Π½ΡƒΠΆΠ½Ρ‹ΠΌ.
                                 #Π’ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π°Ρ… ΡƒΠ΄Π°Π»ΡΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Π΅ с самого Π½Π°Ρ‡Π°Π»Π° Π½Π΅ стоит.

Ni dividas la datumaron en du: unu kun kvalitaj valoroj, kaj la alia kun kvantaj

Ĉi tie ni devas fari malgrandan klarigon: se la linioj kun mankantaj datumoj en kvalitaj kaj kvantaj datumoj ne tre korelacias unu kun la alia, tiam ni devos decidi kion ni oferas - Δ‰iujn liniojn kun mankantaj datumoj, nur parton de ili, aΕ­ certaj kolumnoj. Se la linioj estas korelaciitaj, tiam ni rajtas dividi la datumaron en du. Alie, vi unue devos trakti la liniojn, kiuj ne korelacias la mankantajn datumojn en kvalita kaj kvanta, kaj nur tiam dividi la datumaron en du.

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

Ni faras tion por faciligi al ni prilabori Δ‰i tiujn du malsamajn specojn de datumoj - poste ni komprenos kiom pli facilas Δ‰i tio faciligas nian vivon.

Ni laboras kun kvantaj datumoj

La unua afero, kiun ni devas fari, estas determini Δ‰u estas "spionaj kolumnoj" en la kvantaj datumoj. Ni nomas Δ‰i tiujn kolumnojn tiel Δ‰ar ili prezentas sin kiel kvantajn datumojn, sed agas kiel kvalitaj datumoj.

Kiel ni povas identigi ilin? Kompreneble, Δ‰io dependas de la naturo de la datumoj, kiujn vi analizas, sed ĝenerale tiaj kolumnoj povas havi malmulte da unikaj datumoj (en la regiono de 3-10 unikaj valoroj).

print(df_numerical.nunique())

Post kiam ni identigis la spionkolumnojn, ni movos ilin de kvantaj datumoj al kvalitaj datumoj:

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']) #добавляСм Ρ‚Ρ€Π΅Ρ‚ΡŒΡŽ ΠΊΠΎΠ»ΠΎΠ½ΠΊΡƒ-шпион Π² качСствСнныС Π΄Π°Π½Π½Ρ‹Π΅

Fine, ni tute apartigis kvantajn datumojn de kvalitaj datumoj kaj nun ni povas labori kun ĝi ĝuste. La unua afero estas kompreni, kie ni havas malplenajn valorojn (NaN, kaj en iuj kazoj 0 estos akceptita kiel malplenaj valoroj).

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

Je Δ‰i tiu punkto, estas grave kompreni en kiuj kolumnoj nuloj povas indiki mankantajn valorojn: Δ‰u tio estas pro kiel la datumoj estis kolektitaj? AΕ­ Δ‰u ĝi povus rilati al la datumvaloroj? Ĉi tiuj demandoj devas esti responditaj laΕ­kaze.

Do, se ni ankoraΕ­ decidas, ke eble mankas al ni datumoj kie estas nuloj, ni devus anstataΕ­igi la nulojn per NaN por plifaciligi labori kun Δ‰i tiuj perditaj datumoj poste:

df_numerical[["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 1", "ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 2"]] = df_numerical[["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 1", "ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 2"]].replace(0, nan)

Nun ni vidu, kie ni mankas datumoj:

sns.heatmap(df_numerical.isnull(),yticklabels=False,cbar=False,cmap='viridis') # МоТно Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ df_numerical.info()

Notepad-trompanta folio por rapida datumpretigo

Ĉi tie tiuj valoroj ene de la mankantaj kolumnoj devus esti markitaj flava. Kaj nun komenciĝas la amuzo - kiel trakti Δ‰i tiujn valorojn? Ĉu mi forigu vicojn kun Δ‰i tiuj valoroj aΕ­ kolumnoj? AΕ­ plenigu Δ‰i tiujn malplenajn valorojn per iuj aliaj?

Jen proksimuma diagramo, kiu povas helpi vin decidi, kion oni principe povas fari kun malplenaj valoroj:

Notepad-trompanta folio por rapida datumpretigo

0. Forigu nenecesajn kolumnojn

df_numerical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True)

1. Ĉu la nombro da malplenaj valoroj en Δ‰i tiu kolumno estas pli granda ol 50%?

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

df_numerical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True)#УдаляСм, Ссли какая-Ρ‚ΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° ΠΈΠΌΠ΅Π΅Ρ‚ большС 50 пустых Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ

2. Forigu liniojn kun malplenaj valoroj

df_numerical.dropna(inplace=True)#УдаляСм строчки с пустыми значСниями, Ссли ΠΏΠΎΡ‚ΠΎΠΌ останСтся достаточно Π΄Π°Π½Π½Ρ‹Ρ… для обучСния

3.1. Enmetante hazardan valoron

import random #ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠ΅ΠΌ random
df_numerical["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"].fillna(lambda x: random.choice(df[df[column] != np.nan]["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"]), inplace=True) #вставляСм Ρ€Π°Π½Π΄ΠΎΠΌΠ½Ρ‹Π΅ значСния Π² пустыС ΠΊΠ»Π΅Ρ‚ΠΊΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹

3.2. Enmetante konstantan valoron

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. Enmetu la mezan aΕ­ plej oftan valoron

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. Enigu la valoron kalkulitan de alia modelo

Kelkfoje valoroj povas esti kalkulitaj per regresaj modeloj uzante modelojn de la sklearn-biblioteko aŭ aliaj similaj bibliotekoj. Nia teamo dediĉos apartan artikolon pri kiel tio povas esti farita baldaŭ.

Do, nuntempe, la rakonto pri kvantaj datumoj estos interrompita, Δ‰ar ekzistas multaj aliaj nuancoj pri kiel pli bone fari datumpreparon kaj antaΕ­traktadon por malsamaj taskoj, kaj la bazaj aferoj por kvantaj datumoj estis konsiderataj en Δ‰i tiu artikolo, kaj nun estas la tempo reveni al kvalitaj datumoj.kiujn ni apartigis plurajn paŝojn malantaΕ­en de la kvantaj. Vi povas ŝanĝi Δ‰i tiun kajeron laΕ­plaΔ‰e, adaptante ĝin al malsamaj taskoj, por ke datumpretigo iru tre rapide!

Kvalitaj datumoj

Esence, por kvalitaj datenoj, la Unu-varma-kodiga metodo estas uzata por formati ĝin de Δ‰eno (aΕ­ objekto) al nombro. AntaΕ­ ol pluiri al Δ‰i tiu punkto, ni uzu la diagramon kaj kodon supre por trakti malplenajn valorojn.

df_categorical.nunique()

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

Notepad-trompanta folio por rapida datumpretigo

0. Forigu nenecesajn kolumnojn

df_categorical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True)

1. Ĉu la nombro da malplenaj valoroj en Δ‰i tiu kolumno estas pli granda ol 50%?

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

df_categorical.drop(labels=["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°1","ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°2"], axis=1, inplace=True) #УдаляСм, Ссли какая-Ρ‚ΠΎ ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ° 
                                                                          #ΠΈΠΌΠ΅Π΅Ρ‚ большС 50% пустых Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ

2. Forigu liniojn kun malplenaj valoroj

df_categorical.dropna(inplace=True)#УдаляСм строчки с пустыми значСниями, 
                                   #Ссли ΠΏΠΎΡ‚ΠΎΠΌ останСтся достаточно Π΄Π°Π½Π½Ρ‹Ρ… для обучСния

3.1. Enmetante hazardan valoron

import random
df_categorical["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"].fillna(lambda x: random.choice(df[df[column] != np.nan]["ΠΊΠΎΠ»ΠΎΠ½ΠΊΠ°"]), inplace=True)

3.2. Enmetante konstantan valoron

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)

Do, ni finfine ektraktis nulojn en kvalitaj datumoj. Nun estas tempo fari unu-varman kodigon sur la valoroj, kiuj estas en via datumbazo. Ĉi tiu metodo estas tre ofte uzata por certigi, ke via algoritmo povas lerni de altkvalitaj datumoj.

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

Do, ni finfine finis prilabori apartajn kvalitajn kaj kvantajn datumojn - tempo por kombini ilin reen

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

Post kiam ni kombinis la datumarojn kune en unu, ni povas finfine uzi datuman transformon uzante MinMaxScaler de la sklearn-biblioteko. Ĉi tio faros niajn valorojn inter 0 kaj 1, kio helpos dum trejnado de la modelo estonte.

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

Ĉi tiuj datumoj nun estas pretaj por io ajn - neŭralaj retoj, normaj ML-algoritmoj, ktp.!

En Δ‰i tiu artikolo, ni ne konsideris labori kun temposerio-datumoj, Δ‰ar por tiaj datumoj vi devus uzi iomete malsamajn prilaborajn teknikojn, depende de via tasko. Estonte nia teamo dediΔ‰os apartan artikolon al Δ‰i tiu temo, kaj ni esperas, ke ĝi povos alporti ion interesan, novan kaj utilan en vian vivon, same kiel Δ‰i tiu.

fonto: www.habr.com

Aldoni komenton