Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

Dažnai žmonės, žengiantys į duomenų mokslo sritį, turi mažiau nei realūs lūkesčiai, kas jų laukia. Daugelis žmonių mano, kad dabar jie rašys šaunius neuroninius tinklus, sukurs balso asistentą iš Geležinio žmogaus arba įveiks visus finansų rinkose.
Bet dirbti Duomenys Mokslininkas yra pagrįstas duomenimis, o vienas iš svarbiausių ir daug laiko reikalaujančių aspektų yra duomenų apdorojimas prieš įvedant juos į neuroninį tinklą arba tam tikru būdu analizuojant.

Šiame straipsnyje mūsų komanda aprašys, kaip galite greitai ir lengvai apdoroti duomenis naudodami nuoseklias instrukcijas ir kodą. Mes stengėmės, kad kodas būtų gana lankstus ir galėtų būti naudojamas įvairiems duomenų rinkiniams.

Daugelis specialistų šiame straipsnyje gal ir neras nieko nepaprasto, tačiau pradedantieji galės išmokti ko nors naujo, o kiekvienas, seniai svajojęs pasidaryti atskirą sąsiuvinį greitam ir struktūrizuotam duomenų apdorojimui, gali nukopijuoti kodą ir suformatuoti jį sau, arba atsisiųskite gatavą užrašų knygelę iš „Github“.

Gavome duomenų rinkinį. Ką daryti toliau?

Taigi, standartas: turime suprasti, su kuo turime reikalą, bendrą vaizdą. Norėdami tai padaryti, mes naudojame pandas, kad paprasčiausiai apibrėžtume skirtingus duomenų tipus.

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

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

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

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

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

Pažvelkime į stulpelių reikšmes:

  1. Ar eilučių skaičius kiekviename stulpelyje atitinka bendrą eilučių skaičių?
  2. Kokia kiekvieno stulpelio duomenų esmė?
  3. Į kurį stulpelį norime taikyti, kad galėtume numatyti?

Atsakymai į šiuos klausimus leis jums išanalizuoti duomenų rinkinį ir apytiksliai sudaryti tolesnių veiksmų planą.

Be to, norėdami giliau pažvelgti į kiekvieno stulpelio reikšmes, galime naudoti funkciją pandos description(). Tačiau šios funkcijos trūkumas yra tas, kad ji nepateikia informacijos apie stulpelius su eilutės reikšmėmis. Su jais susitvarkysime vėliau.

df.describe()

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

Magiška vizualizacija

Pažiūrėkime, kur mes visai neturime vertybių:

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

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

Tai buvo trumpas žvilgsnis iš viršaus, dabar pereisime prie įdomesnių dalykų

Pabandykime surasti ir, jei įmanoma, pašalinti stulpelius, kurių visose eilutėse yra tik viena reikšmė (jie niekaip neturės įtakos rezultatui):

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

Dabar apsaugome save ir savo projekto sėkmę nuo pasikartojančių eilučių (eilučių, kuriose yra ta pati informacija ta pačia tvarka kaip ir vienoje iš esamų eilučių):

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

Duomenų rinkinį padalijame į du: vieną su kokybinėmis reikšmėmis, o kitą su kiekybinėmis.

Čia reikia šiek tiek patikslinti: jei kokybinių ir kiekybinių duomenų eilutės su trūkstamais duomenimis nėra labai koreliuojamos viena su kita, tada turėsime nuspręsti, ką aukojame - visas eilutes su trūkstamais duomenimis, tik dalį jų, arba tam tikrus stulpelius. Jei linijos yra koreliuojamos, mes turime visas teises padalyti duomenų rinkinį į dvi dalis. Priešingu atveju pirmiausia turėsite susidoroti su eilutėmis, kurios nekoreliuoja trūkstamų duomenų kokybiniu ir kiekybiniu požiūriu, ir tik tada padalinti duomenų rinkinį į dvi dalis.

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

Tai darome tam, kad mums būtų lengviau apdoroti šių dviejų skirtingų tipų duomenis – vėliau suprasime, kiek tai palengvina mūsų gyvenimą.

Dirbame su kiekybiniais duomenimis

Pirmas dalykas, kurį turėtume padaryti, yra nustatyti, ar kiekybiniuose duomenyse yra „šnipų stulpelių“. Šiuos stulpelius taip vadiname, nes jie pateikiami kaip kiekybiniai, bet veikia kaip kokybiniai duomenys.

Kaip galime juos atpažinti? Žinoma, viskas priklauso nuo jūsų analizuojamų duomenų pobūdžio, tačiau apskritai tokiuose stulpeliuose gali būti mažai unikalių duomenų (3–10 unikalių reikšmių).

print(df_numerical.nunique())

Kai nustatysime šnipų stulpelius, juos iš kiekybinių duomenų perkelsime į kokybinius:

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

Galiausiai, mes visiškai atskyrėme kiekybinius duomenis nuo kokybinių duomenų ir dabar galime tinkamai su jais dirbti. Pirmas dalykas yra suprasti, kur turime tuščias reikšmes (NaN, o kai kuriais atvejais 0 bus priimtos kaip tuščios reikšmės).

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

Šiuo metu svarbu suprasti, kuriuose stulpeliuose nuliai gali nurodyti trūkstamas reikšmes: ar taip yra dėl to, kaip buvo renkami duomenys? O gal tai gali būti susiję su duomenų reikšmėmis? Į šiuos klausimus reikia atsakyti kiekvienu konkrečiu atveju.

Taigi, jei vis tiek nuspręstume, kad mums gali trūkti duomenų ten, kur yra nuliai, turėtume pakeisti nulius NaN, kad vėliau būtų lengviau dirbti su šiais prarastais duomenimis:

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

Dabar pažiūrėkime, kur trūksta duomenų:

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

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

Čia trūkstamos reikšmės stulpeliuose turi būti pažymėtos geltona spalva. O dabar prasideda linksmybės – kaip elgtis su šiomis vertybėmis? Ar turėčiau ištrinti eilutes su šiomis reikšmėmis ar stulpelius? Arba užpildyti šias tuščias reikšmes kitomis?

Čia yra apytikslė diagrama, kuri gali padėti nuspręsti, ką iš esmės galima padaryti su tuščiomis reikšmėmis:

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

0. Pašalinkite nereikalingus stulpelius

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

1. Ar tuščių verčių skaičius šiame stulpelyje yra didesnis nei 50%?

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

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

2. Ištrinkite eilutes su tuščiomis reikšmėmis

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

3.1. Atsitiktinės reikšmės įterpimas

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

3.2. Pastovios vertės įvedimas

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. Įveskite vidutinę arba dažniausiai pasitaikančią vertę

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. Įveskite vertę, apskaičiuotą pagal kitą modelį

Kartais vertes galima apskaičiuoti naudojant regresijos modelius, naudojant modelius iš sklearn bibliotekos ar kitų panašių bibliotekų. Mūsų komanda artimiausiu metu skirs atskirą straipsnį apie tai, kaip tai padaryti.

Taigi kol kas pasakojimas apie kiekybinius duomenis bus nutrauktas, nes yra daug kitų niuansų, kaip geriau paruošti duomenis ir atlikti išankstinį apdorojimą įvairioms užduotims atlikti, o šiame straipsnyje buvo atsižvelgta į pagrindinius dalykus, susijusius su kiekybiniais duomenimis. dabar laikas grįžti prie kokybinių duomenų, kuriuos skyrėme keliais žingsniais atgal nuo kiekybinių. Šį bloknotą galite keisti kaip norite, pritaikydami įvairioms užduotims, kad išankstinis duomenų apdorojimas vyktų labai greitai!

Kokybiniai duomenys

Iš esmės kokybiniams duomenims naudojamas „One-hot“ kodavimo metodas, siekiant suformatuoti juos iš eilutės (arba objekto) į skaičių. Prieš pereidami prie šio taško, naudokime aukščiau pateiktą diagramą ir kodą, kad galėtume tvarkyti tuščias reikšmes.

df_categorical.nunique()

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

Užrašų knygelė, skirta greitam išankstiniam duomenų apdorojimui

0. Pašalinkite nereikalingus stulpelius

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

1. Ar tuščių verčių skaičius šiame stulpelyje yra didesnis nei 50%?

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

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

2. Ištrinkite eilutes su tuščiomis reikšmėmis

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

3.1. Atsitiktinės reikšmės įterpimas

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

3.2. Pastovios vertės įvedimas

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)

Taigi, mes pagaliau susitvarkėme su kokybinių duomenų nuliais. Dabar atėjo laikas atlikti vienkartinį duomenų, esančių duomenų bazėje, kodavimą. Šis metodas labai dažnai naudojamas siekiant užtikrinti, kad jūsų algoritmas galėtų mokytis iš aukštos kokybės duomenų.

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

Taigi, pagaliau baigėme apdoroti atskirus kokybinius ir kiekybinius duomenis – laikas juos sujungti atgal

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

Sujungę duomenų rinkinius į vieną, pagaliau galime naudoti duomenų transformavimą naudodami MinMaxScaler iš sklearn bibliotekos. Dėl to mūsų reikšmės bus nuo 0 iki 1, o tai padės treniruoti modelį ateityje.

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

Šie duomenys dabar yra paruošti viskam – neuroniniams tinklams, standartiniams ML algoritmams ir pan.!

Šiame straipsnyje mes neatsižvelgėme į darbą su laiko eilučių duomenimis, nes tokiems duomenims turėtumėte naudoti šiek tiek skirtingus apdorojimo būdus, atsižvelgiant į jūsų užduotį. Ateityje mūsų komanda šiai temai skirs atskirą straipsnį ir tikimės, kad jis galės įnešti į jūsų gyvenimą kažką įdomaus, naujo ir naudingo, kaip ir šis.

Šaltinis: www.habr.com

Добавить комментарий