# Рад са подацима: Припрема података |![ Скетч од [(@sketchthedocs)](https://sketchthedocs.dev) ](../../sketchnotes/08-DataPreparation.png)| |:---:| |Припрема података - _Скетч од [@nitya](https://twitter.com/nitya)_ | ## [Квиз пре предавања](https://ff-quizzes.netlify.app/en/ds/quiz/14) У зависности од извора, необрађени подаци могу садржати неке недоследности које ће изазвати проблеме у анализи и моделирању. Другим речима, ови подаци могу бити категорисани као „нечисти“ и потребно их је очистити. Ова лекција се фокусира на технике чишћења и трансформације података како би се решили проблеми са недостајућим, нетачним или непотпуним подацима. Теме обухваћене у овој лекцији користе Python и библиотеку Pandas и биће [приказане у нотебуку](../../../../2-Working-With-Data/08-data-preparation/notebook.ipynb) унутар овог директоријума. ## Значај чишћења података - **Лакше коришћење и поновна употреба**: Када су подаци правилно организовани и нормализовани, лакше их је претраживати, користити и делити са другима. - **Конзистентност**: Наука о подацима често захтева рад са више скупова података, где скупови података из различитих извора треба да се споје. Осигурање да сваки појединачни скуп података има заједничку стандардизацију обезбедиће да подаци остану корисни када се сви споје у један скуп података. - **Тачност модела**: Очишћени подаци побољшавају тачност модела који се на њима заснивају. ## Уобичајени циљеви и стратегије чишћења - **Истраживање скупа података**: Истраживање података, које је обухваћено у [каснијој лекцији](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/4-Data-Science-Lifecycle/15-analyzing), може вам помоћи да откријете податке које треба очистити. Визуелно посматрање вредности унутар скупа података може поставити очекивања о томе како ће остатак изгледати или пружити идеју о проблемима који се могу решити. Истраживање може укључивати основно упитивање, визуализације и узорковање. - **Форматирање**: У зависности од извора, подаци могу имати недоследности у начину на који су представљени. Ово може изазвати проблеме у претраживању и представљању вредности, где се она види унутар скупа података, али није правилно представљена у визуализацијама или резултатима упита. Уобичајени проблеми са форматирањем укључују решавање празног простора, датума и типова података. Решавање проблема са форматирањем обично је на људима који користе податке. На пример, стандарди о томе како се датуми и бројеви представљају могу се разликовати од земље до земље. - **Дупликати**: Подаци који имају више од једне појаве могу произвести нетачне резултате и обично их треба уклонити. Ово може бити уобичајена појава када се спајају два или више скупа података. Међутим, постоје случајеви када дупликати у спојеним скуповима података садрже делове који могу пружити додатне информације и можда их треба сачувати. - **Недостајући подаци**: Недостајући подаци могу изазвати нетачности као и слабе или пристрасне резултате. Понекад се ово може решити „поновним учитавањем“ података, попуњавањем недостајућих вредности рачунским методама и кодом као што је Python, или једноставно уклањањем вредности и одговарајућих података. Постоји много разлога зашто подаци могу недостајати, а радње које се предузимају да се реше ове недостајуће вредности могу зависити од тога како и зашто су нестали. ## Истраживање информација о DataFrame-у > **Циљ учења:** На крају овог пододељка, требало би да будете у могућности да пронађете опште информације о подацима који се чувају у pandas DataFrame-овима. Када учитате своје податке у pandas, они ће највероватније бити у DataFrame-у (погледајте претходну [лекцију](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python#dataframe) за детаљан преглед). Међутим, ако скуп података у вашем DataFrame-у има 60.000 редова и 400 колона, како уопште почети да разумете са чиме радите? Срећом, [pandas](https://pandas.pydata.org/) пружа неке погодне алате за брз преглед општих информација о DataFrame-у, као и првих и последњих неколико редова. Да бисмо истражили ову функционалност, увешћемо Python библиотеку scikit-learn и користити један познати скуп података: **Iris скуп података**. ```python import pandas as pd from sklearn.datasets import load_iris iris = load_iris() iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names']) ``` | |дужина чашичног листа (cm)|ширина чашичног листа (cm)|дужина латице (cm)|ширина латице (cm)| |----------------------------------------|--------------------------|--------------------------|------------------|------------------| |0 |5.1 |3.5 |1.4 |0.2 | |1 |4.9 |3.0 |1.4 |0.2 | |2 |4.7 |3.2 |1.3 |0.2 | |3 |4.6 |3.1 |1.5 |0.2 | |4 |5.0 |3.6 |1.4 |0.2 | - **DataFrame.info**: За почетак, `info()` метода се користи за испис резимеа садржаја присутног у `DataFrame-у`. Погледајмо овај скуп података да видимо шта имамо: ```python iris_df.info() ``` ``` RangeIndex: 150 entries, 0 to 149 Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 sepal length (cm) 150 non-null float64 1 sepal width (cm) 150 non-null float64 2 petal length (cm) 150 non-null float64 3 petal width (cm) 150 non-null float64 dtypes: float64(4) memory usage: 4.8 KB ``` Из овога знамо да *Iris* скуп података има 150 уноса у четири колоне без недостајућих уноса. Сви подаци су сачувани као 64-битни бројеви са покретним зарезом. - **DataFrame.head()**: Затим, да бисмо проверили стварни садржај `DataFrame-а`, користимо `head()` методу. Погледајмо првих неколико редова нашег `iris_df`: ```python iris_df.head() ``` ``` sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) 0 5.1 3.5 1.4 0.2 1 4.9 3.0 1.4 0.2 2 4.7 3.2 1.3 0.2 3 4.6 3.1 1.5 0.2 4 5.0 3.6 1.4 0.2 ``` - **DataFrame.tail()**: Супротно томе, да бисмо проверили последњих неколико редова `DataFrame-а`, користимо `tail()` методу: ```python iris_df.tail() ``` ``` sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) 145 6.7 3.0 5.2 2.3 146 6.3 2.5 5.0 1.9 147 6.5 3.0 5.2 2.0 148 6.2 3.4 5.4 2.3 149 5.9 3.0 5.1 1.8 ``` > **Закључак:** Чак и само гледањем метаподатака о информацијама у DataFrame-у или првих и последњих неколико вредности у њему, можете добити тренутну идеју о величини, облику и садржају података са којима радите. ## Рад са недостајућим подацима > **Циљ учења:** На крају овог пододељка, требало би да знате како да замените или уклоните null вредности из DataFrame-ова. Већину времена скупови података које желите да користите (или морате да користите) имају недостајуће вредности. Начин на који се недостајући подаци обрађују носи са собом суптилне компромисе који могу утицати на вашу коначну анализу и исходе у стварном свету. Pandas обрађује недостајуће вредности на два начина. Први сте већ видели у претходним одељцима: `NaN`, или Not a Number. Ово је заправо посебна вредност која је део IEEE спецификације за бројеве са покретним зарезом и користи се само за означавање недостајућих вредности са покретним зарезом. За недостајуће вредности осим бројева са покретним зарезом, pandas користи Python објекат `None`. Иако може изгледати збуњујуће да ћете наићи на две различите врсте вредности које суштински говоре исту ствар, постоје добри програмски разлози за овај избор дизајна и, у пракси, овај приступ омогућава pandas-у да пружи добар компромис за велику већину случајева. Упркос томе, и `None` и `NaN` носе ограничења која треба да имате на уму у погледу начина на који се могу користити. Погледајте више о `NaN` и `None` у [нотебуку](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/4-Data-Science-Lifecycle/15-analyzing/notebook.ipynb)! - **Детектовање null вредности**: У `pandas`, методе `isnull()` и `notnull()` су ваши примарни алати за детектовање null података. Обе враћају Булове маске преко ваших података. Користићемо `numpy` за `NaN` вредности: ```python import numpy as np example1 = pd.Series([0, np.nan, '', None]) example1.isnull() ``` ``` 0 False 1 True 2 False 3 True dtype: bool ``` Пажљиво погледајте излаз. Да ли вас нешто изненађује? Иако је `0` аритметички null, он је ипак савршено добар целобројни број и pandas га тако третира. `''` је мало суптилнији. Иако смо га користили у Одељку 1 да представимо празну стринг вредност, он је ипак стринг објекат и није представљање null вредности у смислу pandas-а. Сада, хајде да ово окренемо и користимо ове методе на начин који је ближи ономе како ћете их користити у пракси. Можете користити Булове маске директно као индекс ``Series`` или ``DataFrame``, што може бити корисно када покушавате да радите са изолованим недостајућим (или присутним) вредностима. > **Закључак**: И `isnull()` и `notnull()` методе производе сличне резултате када их користите у `DataFrame-овима`: показују резултате и индекс тих резултата, што ће вам изузетно помоћи док се борите са својим подацима. - **Уклањање null вредности**: Поред идентификовања недостајућих вредности, pandas пружа погодан начин за уклањање null вредности из `Series` и `DataFrame-ова`. (Посебно код великих скупа података, често је препоручљивије једноставно уклонити недостајуће [NA] вредности из ваше анализе него се бавити њима на друге начине.) Да бисмо видели ово у пракси, вратићемо се на `example1`: ```python example1 = example1.dropna() example1 ``` ``` 0 0 2 dtype: object ``` Приметите да ово треба да изгледа као ваш излаз из `example3[example3.notnull()]`. Разлика овде је у томе што је, уместо да само индексира маскиране вредности, `dropna` уклонио те недостајуће вредности из `Series` `example1`. Пошто `DataFrame-ови` имају две димензије, они пружају више опција за уклањање података. ```python example2 = pd.DataFrame([[1, np.nan, 7], [2, 5, 8], [np.nan, 6, 9]]) example2 ``` | | 0 | 1 | 2 | |------|---|---|---| |0 |1.0|NaN|7 | |1 |2.0|5.0|8 | |2 |NaN|6.0|9 | (Да ли сте приметили да је pandas променио тип две колоне у бројеве са покретним зарезом како би се прилагодио `NaN` вредностима?) Не можете уклонити једну вредност из `DataFrame-а`, тако да морате уклонити целе редове или колоне. У зависности од онога што радите, можда ћете желети да урадите једно или друго, па pandas пружа опције за оба. Пошто у науци о подацима колоне генерално представљају променљиве, а редови представљају опсервације, вероватније је да ћете уклонити редове података; подразумевана поставка за `dropna()` је да уклони све редове који садрже било које null вредности: ```python example2.dropna() ``` ``` 0 1 2 1 2.0 5.0 8 ``` Ако је потребно, можете уклонити NA вредности из колона. Користите `axis=1` да то урадите: ```python example2.dropna(axis='columns') ``` ``` 2 0 7 1 8 2 9 ``` Приметите да ово може уклонити много података које можда желите да задржите, посебно у мањим скуповима података. Шта ако желите да уклоните само редове или колоне који садрже неколико или чак све null вредности? Те поставке можете одредити у `dropna` помоћу параметара `how` и `thresh`. Подразумевано, `how='any'` (ако желите да проверите сами или видите које друге параметре метода има, покрените `example4.dropna?` у код ћелији). Можете алтернативно одредити `how='all'` како бисте уклонили само редове или колоне који садрже све null вредности. Хајде да проширимо наш пример `DataFrame-а` да видимо ово у пракси. ```python example2[3] = np.nan example2 ``` | |0 |1 |2 |3 | |------|---|---|---|---| |0 |1.0|NaN|7 |NaN| |1 |2.0|5.0|8 |NaN| |2 |NaN|6.0|9 |NaN| Параметар `thresh` вам даје прецизнију контролу: постављате број *не-null* вредности које ред или колона треба да имају да би били задржани: ```python example2.dropna(axis='rows', thresh=3) ``` ``` 0 1 2 3 1 2.0 5.0 8 NaN ``` Овде су први и последњи ред уклоњени, јер садрже само две не-null вредности. - **Попуњавање null вредности**: У зависности од вашег скупа података, понекад може имати више смисла да попуните null вредности валидним него да их уклоните. Могли бисте користити `isnull` да то урадите на месту, али то може бити напорно, посебно ако имате много вредности за попуњавање. Пошто је ово тако уобичајен задатак у науци о подацима, pandas пружа `fillna`, који враћа копију `Series` или `DataFrame-а` са недостајућим вредностима замењеним оним које изаберете. Хајде да направимо још један пример `Series` да видимо како ово функционише у пракси. ```python example3 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde')) example3 ``` ``` a 1.0 b NaN c 2.0 d NaN e 3.0 dtype: float64 ``` Можете попунити све недостајуће уносе једном вредношћу, као што је `0`: ```python example3.fillna(0) ``` ``` a 1.0 b 0.0 c 2.0 d 0.0 e 3.0 dtype: float64 ``` Можете **попунити унапред** null вредности, што значи да користите последњу валидну вредност за попуњавање null: ```python example3.fillna(method='ffill') ``` ``` a 1.0 b 1.0 c 2.0 d 2.0 e 3.0 dtype: float64 ``` Такође можете **попунити уназад** да бисте пренели следећу валидну вредност уназад за попуњавање null: ```python example3.fillna(method='bfill') ``` ``` a 1.0 b 2.0 c 2.0 d 3.0 e 3.0 dtype: float64 ``` Као што можете претпоставити, ово функционише исто са `DataFrame-овима`, али можете такође одредити > **Закључак:** Постоји више начина за решавање недостајућих вредности у вашим скуповима података. Конкретна стратегија коју користите (уклањање, замена или начин на који их замењујете) треба да буде диктирана специфичностима тих података. Развићете бољи осећај за решавање недостајућих вредности што више радите и интерагујете са скуповима података. ## Уклањање дупликатних података > **Циљ учења:** На крају овог пододељка, требало би да будете спремни да идентификујете и уклоните дупликатне вредности из DataFrame-ова. Поред недостајућих података, често ћете наићи на дупликатне податке у стварним скуповима података. Срећом, `pandas` пружа једноставан начин за откривање и уклањање дупликатних уноса. - **Идентификовање дупликата: `duplicated`**: Лако можете уочити дупликатне вредности користећи метод `duplicated` у pandas-у, који враћа Булову маску која показује да ли је унос у `DataFrame`-у дупликат неког претходног. Хајде да направимо још један пример `DataFrame`-а да видимо како то функционише. ```python example4 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'], 'numbers': [1, 2, 1, 3, 3]}) example4 ``` | |слова |бројеви| |------|-------|-------| |0 |A |1 | |1 |B |2 | |2 |A |1 | |3 |B |3 | |4 |B |3 | ```python example4.duplicated() ``` ``` 0 False 1 False 2 True 3 False 4 True dtype: bool ``` - **Уклањање дупликата: `drop_duplicates`:** једноставно враћа копију података за које су све `duplicated` вредности `False`: ```python example4.drop_duplicates() ``` ``` letters numbers 0 A 1 1 B 2 3 B 3 ``` И `duplicated` и `drop_duplicates` подразумевано узимају у обзир све колоне, али можете одредити да испитују само подскуп колона у вашем `DataFrame`-у: ```python example4.drop_duplicates(['letters']) ``` ``` letters numbers 0 A 1 1 B 2 ``` > **Закључак:** Уклањање дупликатних података је суштински део готово сваког пројекта у области науке о подацима. Дупликатни подаци могу променити резултате ваших анализа и довести до нетачних закључака! ## 🚀 Изазов Сви материјали који су обрађени доступни су као [Jupyter Notebook](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/2-Working-With-Data/08-data-preparation/notebook.ipynb). Поред тога, постоје вежбе након сваког одељка, пробајте их! ## [Квиз након предавања](https://ff-quizzes.netlify.app/en/ds/quiz/15) ## Преглед и самостално учење Постоји много начина да откријете и приступите припреми ваших података за анализу и моделирање, а чишћење података је важан корак који захтева практично искуство. Испробајте ове изазове са Kaggle-а да истражите технике које ова лекција није покрила. - [Изазов чишћења података: Парсирање датума](https://www.kaggle.com/rtatman/data-cleaning-challenge-parsing-dates/) - [Изазов чишћења података: Скалирање и нормализација података](https://www.kaggle.com/rtatman/data-cleaning-challenge-scale-and-normalize-data) ## Задатак [Процена података из формулара](assignment.md) --- **Одрицање од одговорности**: Овај документ је преведен коришћењем услуге за превођење помоћу вештачке интелигенције [Co-op Translator](https://github.com/Azure/co-op-translator). Иако се трудимо да обезбедимо тачност, молимо вас да имате у виду да аутоматски преводи могу садржати грешке или нетачности. Оригинални документ на његовом изворном језику треба сматрати меродавним извором. За критичне информације препоручује се професионални превод од стране људи. Не преузимамо одговорност за било каква погрешна тумачења или неспоразуме који могу настати услед коришћења овог превода.