Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

Az adattudomány területére belépő embereknek gyakran a reálisnál kisebb elvárásaik vannak azzal kapcsolatban, hogy mi vár rájuk. Sokan azt gondolják, hogy most menő neurális hálózatokat fognak írni, létrehoznak egy hangasszisztenst az Iron Man-ből, vagy mindenkit legyőznek a pénzügyi piacokon.
De munka dátum A tudós adatvezérelt, és az egyik legfontosabb és legidőigényesebb szempont az adatok feldolgozása, mielőtt neurális hálózatba betáplálnák, vagy bizonyos módon elemeznék azokat.

Ebben a cikkben csapatunk leírja, hogyan dolgozhat fel gyorsan és egyszerűen adatokat lépésenkénti utasításokkal és kóddal. Megpróbáltuk elég rugalmassá tenni a kódot, és különféle adatkészletekhez használható.

Lehet, hogy sok szakember nem talál ebben a cikkben semmi rendkívülit, de a kezdők megtanulhatnak valami újat, és aki régóta álmodott egy külön notebook készítéséről a gyors és strukturált adatfeldolgozáshoz, az átmásolhatja a kódot és megformázhatja magának, ill. töltse le a kész notebookot a Githubról.

Megkaptuk az adatkészletet. Mi legyen a következő?

Tehát a mérce: meg kell értenünk, hogy mivel is van dolgunk, az összképet. Ehhez pandákat használunk, hogy egyszerűen meghatározzuk a különböző adattípusokat.

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

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

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

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

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

Nézzük az oszlopértékeket:

  1. Az egyes oszlopokban lévő sorok száma megegyezik a sorok teljes számával?
  2. Mi a lényege az egyes oszlopokban lévő adatoknak?
  3. Melyik oszlopot szeretnénk megcélozni, hogy előrejelzéseket készítsünk rá?

Az ezekre a kérdésekre adott válaszok lehetővé teszik az adatkészlet elemzését, és hozzávetőlegesen tervet készíthet a következő műveletekhez.

Ezenkívül az egyes oszlopok értékeinek mélyebb megismeréséhez használhatjuk a pandas description() függvényt. Ennek a függvénynek azonban az a hátránya, hogy nem ad információt a karakterlánc értékű oszlopokról. Később foglalkozunk velük.

df.describe()

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

Varázslatos vizualizáció

Nézzük meg, ahol egyáltalán nincsenek értékeink:

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

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

Ez egy rövid pillantás volt fentről, most érdekesebb dolgokra térünk át

Próbáljuk meg megkeresni és lehetőség szerint eltávolítani azokat az oszlopokat, amelyeknek minden sorban csak egy értéke van (az eredményt semmilyen módon nem befolyásolják):

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

Most megvédjük magunkat és projektünk sikerét az ismétlődő soroktól (olyan sorok, amelyek ugyanazt az információt tartalmazzák, ugyanabban a sorrendben, mint az egyik meglévő sor):

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

Az adatkészletet két részre osztjuk: az egyik minőségi, a másik a mennyiségi értékekkel

Itt egy kis pontosítást kell tennünk: ha a minőségi és mennyiségi adatokban hiányzó adatokat tartalmazó sorok nem nagyon korrelálnak egymással, akkor el kell döntenünk, hogy mit áldozunk fel - az összes hiányzó adatsort, csak egy részét, vagy bizonyos oszlopok. Ha a sorok korrelálnak, akkor jogunk van két részre osztani az adatkészletet. Ellenkező esetben először azokkal a sorokkal kell foglalkoznia, amelyek minőségi és mennyiségi szempontból nem korrelálják a hiányzó adatokat, és csak ezután kell két részre osztani az adatkészletet.

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

Ezt azért tesszük, hogy könnyebben feldolgozzuk ezt a két különböző típusú adatot – később meg fogjuk érteni, hogy ez mennyivel könnyíti meg az életünket.

Mennyiségi adatokkal dolgozunk

Az első dolog, amit meg kell tennünk, hogy meghatározzuk, hogy vannak-e „kémoszlopok” a mennyiségi adatokban. Ezeket az oszlopokat azért hívjuk így, mert mennyiségi adatként jelennek meg, de minőségi adatként működnek.

Hogyan azonosíthatjuk őket? Természetesen minden az elemzett adatok természetétől függ, de általában az ilyen oszlopok kevés egyedi adatot tartalmazhatnak (3-10 egyedi érték tartományban).

print(df_numerical.nunique())

Miután azonosítottuk a kémoszlopokat, áthelyezzük őket a mennyiségi adatokról a minőségi adatokra:

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

Végül teljesen elválasztottuk a kvantitatív adatokat a minőségi adatoktól, és most már megfelelően dolgozhatunk velük. Az első dolog az, hogy megértsük, hol vannak üres értékeink (NaN, és bizonyos esetekben a 0 üres értékként fogadható el).

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

Ezen a ponton fontos megérteni, hogy mely oszlopokban jelezhetik a nullák a hiányzó értékeket: ez az adatgyűjtés módjának köszönhető? Vagy az adatértékekkel lehet összefüggésben? Ezeket a kérdéseket eseti alapon kell megválaszolni.

Tehát, ha mégis úgy döntünk, hogy esetleg hiányoznak az adatok, ahol nullák vannak, akkor a nullákat NaN-re kell cserélnünk, hogy később könnyebben dolgozhassunk ezekkel az elveszett adatokkal:

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

Most nézzük meg, hol hiányoznak az adatok:

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

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

Itt az oszlopokon belüli hiányzó értékeket sárgával kell jelölni. És most kezdődik a móka – hogyan kezeljük ezeket az értékeket? Töröljem az ilyen értékekkel rendelkező sorokat vagy oszlopokat? Vagy töltse ki ezeket az üres értékeket másokkal?

Íme egy hozzávetőleges diagram, amely segíthet eldönteni, hogy elvileg mit lehet tenni üres értékekkel:

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

0. Távolítsa el a szükségtelen oszlopokat

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

1. Az üres értékek száma ebben az oszlopban nagyobb, mint 50%?

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

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

2. Törölje az üres értékekkel rendelkező sorokat

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

3.1. Véletlenszerű érték beszúrása

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

3.2. Állandó érték beillesztése

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. Írja be az átlagos vagy a leggyakoribb értéket

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. Írja be a másik modell által számított értéket

Néha az értékeket regressziós modellekkel lehet kiszámítani a sklearn könyvtárból vagy más hasonló könyvtárakból származó modellek segítségével. Ennek mikéntjéről csapatunk a közeljövőben külön cikket fog szentelni.

Egyelőre tehát megszakad a kvantitatív adatokról szóló narratíva, mert sok más árnyalat is van arról, hogyan lehetne jobban elvégezni a különböző feladatokhoz szükséges adat-előkészítést és előfeldolgozást, illetve a mennyiségi adatokkal kapcsolatos alapvető dolgokat ebben a cikkben figyelembe vettük, ill. itt az ideje visszatérni a minőségi adatokhoz.amelyeket több lépéssel hátrább választottunk a kvantitatívaktól. Ezt a notebookot tetszés szerint cserélheti, különféle feladatokhoz igazítva, így az adatok előfeldolgozása nagyon gyorsan megy!

Minőségi adatok

Alapvetően a minőségi adatokhoz a One-hot-encoding módszert használják annak érdekében, hogy karakterláncból (vagy objektumból) számmá formázzák azokat. Mielőtt továbbmennénk erre a pontra, használjuk a fenti diagramot és kódot az üres értékek kezelésére.

df_categorical.nunique()

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

Jegyzettömb-csalólap a gyors adat-előfeldolgozáshoz

0. Távolítsa el a szükségtelen oszlopokat

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

1. Az üres értékek száma ebben az oszlopban nagyobb, mint 50%?

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

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

2. Törölje az üres értékekkel rendelkező sorokat

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

3.1. Véletlenszerű érték beszúrása

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

3.2. Állandó érték beillesztése

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)

Tehát végre megbirkóztunk a minőségi adatok nullpontjaival. Most itt az ideje, hogy egyszeri kódolást hajtson végre az adatbázisában lévő értékeken. Ezt a módszert gyakran használják annak biztosítására, hogy az algoritmus tudjon tanulni a jó minőségű adatokból.

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

Tehát végre befejeztük a minőségi és mennyiségi adatok külön feldolgozását – ideje összevonni őket

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

Miután egyesítettük az adatkészleteket egybe, végre használhatjuk az adatátalakítást a MinMaxScaler segítségével a sklearn könyvtárból. Ez 0 és 1 közé teszi az értékeinket, ami segít a modell jövőbeni betanításában.

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

Ezek az adatok most már mindenre készen állnak - neurális hálózatokra, szabványos ML algoritmusokra stb.!

Ebben a cikkben nem vettük figyelembe az idősoros adatokkal való munkát, mivel az ilyen adatokhoz a feladattól függően kissé eltérő feldolgozási technikákat kell alkalmazni. A jövőben csapatunk külön cikket fog szentelni ennek a témának, és reméljük, hogy valami érdekeset, újat és hasznosat tud majd vinni az életébe, akárcsak ez.

Forrás: will.com

Hozzászólás