# Práca s dátami: Príprava dát |![ Sketchnote od [(@sketchthedocs)](https://sketchthedocs.dev) ](../../sketchnotes/08-DataPreparation.png)| |:---:| |Príprava dát - _Sketchnote od [@nitya](https://twitter.com/nitya)_ | ## [Kvíz pred prednáškou](https://ff-quizzes.netlify.app/en/ds/quiz/14) V závislosti od zdroja môžu surové dáta obsahovať nekonzistencie, ktoré spôsobujú problémy pri analýze a modelovaní. Inými slovami, tieto dáta môžu byť označené ako „špinavé“ a bude ich potrebné vyčistiť. Táto lekcia sa zameriava na techniky čistenia a transformácie dát na riešenie problémov s chýbajúcimi, nepresnými alebo neúplnými dátami. Témy pokryté v tejto lekcii využívajú Python a knižnicu Pandas a budú [predvedené v notebooku](../../../../2-Working-With-Data/08-data-preparation/notebook.ipynb) v tomto adresári. ## Dôležitosť čistenia dát - **Jednoduchosť použitia a opätovného použitia**: Keď sú dáta správne organizované a normalizované, je jednoduchšie ich vyhľadávať, používať a zdieľať s ostatnými. - **Konzistentnosť**: Dátová veda často vyžaduje prácu s viacerými datasetmi, kde datasety z rôznych zdrojov musia byť spojené. Zabezpečenie, že každý jednotlivý dataset má spoločnú štandardizáciu, zaručí, že dáta budú stále užitočné, keď sa spoja do jedného datasetu. - **Presnosť modelov**: Vyčistené dáta zlepšujú presnosť modelov, ktoré na nich závisia. ## Bežné ciele a stratégie čistenia - **Preskúmanie datasetu**: Preskúmanie dát, ktoré je pokryté v [neskoršej lekcii](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/4-Data-Science-Lifecycle/15-analyzing), vám môže pomôcť identifikovať dáta, ktoré je potrebné vyčistiť. Vizualizácia hodnôt v datasete môže nastaviť očakávania, ako bude vyzerať zvyšok datasetu, alebo poskytnúť predstavu o problémoch, ktoré je možné vyriešiť. Preskúmanie môže zahŕňať základné dotazovanie, vizualizácie a vzorkovanie. - **Formátovanie**: V závislosti od zdroja môžu dáta obsahovať nekonzistencie v tom, ako sú prezentované. To môže spôsobiť problémy pri vyhľadávaní a reprezentácii hodnôt, kde sú viditeľné v datasete, ale nie sú správne reprezentované vo vizualizáciách alebo výsledkoch dotazov. Bežné problémy s formátovaním zahŕňajú riešenie medzier, dátumov a typov dát. Riešenie problémov s formátovaním je zvyčajne na ľuďoch, ktorí dáta používajú. Napríklad štandardy, ako sú prezentované dátumy a čísla, sa môžu líšiť podľa krajiny. - **Duplikácie**: Dáta, ktoré sa vyskytujú viac ako raz, môžu produkovať nepresné výsledky a zvyčajne by mali byť odstránené. Toto je bežný jav pri spájaní dvoch alebo viacerých datasetov. Avšak existujú prípady, keď duplikácie v spojených datasetoch obsahujú časti, ktoré môžu poskytnúť dodatočné informácie a môžu byť potrebné zachovať. - **Chýbajúce dáta**: Chýbajúce dáta môžu spôsobiť nepresnosti, ako aj slabé alebo zaujaté výsledky. Niekedy je možné tieto problémy vyriešiť „znovunačítaním“ dát, doplnením chýbajúcich hodnôt výpočtom a kódom, ako je Python, alebo jednoducho odstránením hodnoty a zodpovedajúcich dát. Existuje mnoho dôvodov, prečo môžu dáta chýbať, a kroky, ktoré sa podniknú na vyriešenie týchto chýbajúcich hodnôt, môžu závisieť od toho, ako a prečo zmizli. ## Preskúmanie informácií o DataFrame > **Cieľ učenia:** Na konci tejto podsekcie by ste mali byť schopní nájsť všeobecné informácie o dátach uložených v pandas DataFrames. Keď načítate svoje dáta do pandas, pravdepodobne budú vo forme DataFrame (pozrite si predchádzajúcu [lekciu](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python#dataframe) pre podrobný prehľad). Ak však dataset vo vašom DataFrame obsahuje 60 000 riadkov a 400 stĺpcov, ako vôbec začať chápať, s čím pracujete? Našťastie, [pandas](https://pandas.pydata.org/) poskytuje niekoľko praktických nástrojov na rýchle získanie celkových informácií o DataFrame, ako aj o prvých a posledných riadkoch. Aby sme preskúmali túto funkcionalitu, importujeme knižnicu Python scikit-learn a použijeme ikonický dataset: **Iris dataset**. ```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']) ``` | |dĺžka sepalu (cm)|šírka sepalu (cm)|dĺžka petalu (cm)|šírka petalu (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**: Na začiatok sa používa metóda `info()`, ktorá vytlačí súhrn obsahu prítomného v `DataFrame`. Pozrime sa na tento dataset, aby sme zistili, čo máme: ```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 ``` Z toho vieme, že dataset *Iris* má 150 záznamov v štyroch stĺpcoch bez nulových záznamov. Všetky dáta sú uložené ako 64-bitové čísla s pohyblivou desatinnou čiarkou. - **DataFrame.head()**: Ďalej, na kontrolu skutočného obsahu `DataFrame`, používame metódu `head()`. Pozrime sa, ako vyzerajú prvé riadky nášho `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()**: Naopak, na kontrolu posledných riadkov `DataFrame` používame metódu `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 ``` > **Záver:** Už len pohľad na metadáta o informáciách v DataFrame alebo na prvé a posledné hodnoty v ňom vám môže okamžite poskytnúť predstavu o veľkosti, tvare a obsahu dát, s ktorými pracujete. ## Riešenie chýbajúcich dát > **Cieľ učenia:** Na konci tejto podsekcie by ste mali vedieť, ako nahradiť alebo odstrániť nulové hodnoty z DataFrames. Väčšinou dataset, ktorý chcete použiť (alebo musíte použiť), obsahuje chýbajúce hodnoty. Spôsob, akým sa chýbajúce dáta riešia, nesie jemné kompromisy, ktoré môžu ovplyvniť vašu konečnú analýzu a výsledky v reálnom svete. Pandas rieši chýbajúce hodnoty dvoma spôsobmi. Prvý ste už videli v predchádzajúcich sekciách: `NaN`, alebo Not a Number. Toto je špeciálna hodnota, ktorá je súčasťou špecifikácie IEEE pre čísla s pohyblivou desatinnou čiarkou a používa sa iba na označenie chýbajúcich hodnôt s pohyblivou desatinnou čiarkou. Pre chýbajúce hodnoty okrem čísel s pohyblivou desatinnou čiarkou používa pandas objekt Python `None`. Aj keď sa môže zdať mätúce, že sa stretnete s dvoma rôznymi typmi hodnôt, ktoré v podstate hovoria to isté, existujú rozumné programové dôvody pre tento dizajn a v praxi tento prístup umožňuje pandas dosiahnuť dobrý kompromis pre drvivú väčšinu prípadov. Napriek tomu majú `None` a `NaN` obmedzenia, ktoré musíte mať na pamäti, pokiaľ ide o ich použitie. Viac o `NaN` a `None` si môžete prečítať v [notebooku](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/4-Data-Science-Lifecycle/15-analyzing/notebook.ipynb)! - **Detekcia nulových hodnôt**: V `pandas` sú vaše primárne metódy na detekciu nulových dát `isnull()` a `notnull()`. Obe vracajú Booleovské masky nad vašimi dátami. Budeme používať `numpy` pre hodnoty `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 ``` Pozorne si prezrite výstup. Prekvapilo vás niečo? Zatiaľ čo `0` je aritmetická nula, je to stále úplne dobré celé číslo a pandas ho tak aj považuje. `''` je trochu jemnejšie. Zatiaľ čo sme ho v sekcii 1 použili na reprezentáciu prázdnej hodnoty reťazca, je to stále objekt reťazca a nie reprezentácia nuly z pohľadu pandas. Teraz to otočme a použime tieto metódy spôsobom, akým ich budete používať v praxi. Booleovské masky môžete použiť priamo ako index pre ``Series`` alebo ``DataFrame``, čo môže byť užitočné pri práci s izolovanými chýbajúcimi (alebo prítomnými) hodnotami. > **Záver:** Metódy `isnull()` a `notnull()` produkujú podobné výsledky, keď ich použijete v `DataFrame`: zobrazujú výsledky a index týchto výsledkov, čo vám veľmi pomôže pri práci s vašimi dátami. - **Odstraňovanie nulových hodnôt**: Okrem identifikácie chýbajúcich hodnôt poskytuje pandas pohodlný spôsob, ako odstrániť nulové hodnoty zo `Series` a `DataFrame`. (Najmä pri veľkých datasetoch je často rozumnejšie jednoducho odstrániť chýbajúce [NA] hodnoty z vašej analýzy, než sa s nimi zaoberať inými spôsobmi.) Aby sme to videli v praxi, vráťme sa k `example1`: ```python example1 = example1.dropna() example1 ``` ``` 0 0 2 dtype: object ``` Všimnite si, že toto by malo vyzerať ako váš výstup z `example3[example3.notnull()]`. Rozdiel je v tom, že namiesto indexovania na maskované hodnoty `dropna` odstránil tieto chýbajúce hodnoty zo `Series` `example1`. Keďže `DataFrame` má dve dimenzie, poskytuje viac možností na odstraňovanie dát. ```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 | (Všimli ste si, že pandas pretypoval dva stĺpce na čísla s pohyblivou desatinnou čiarkou, aby vyhoveli hodnotám `NaN`?) Nemôžete odstrániť jednu hodnotu z `DataFrame`, takže musíte odstrániť celé riadky alebo stĺpce. V závislosti od toho, čo robíte, môžete chcieť urobiť jedno alebo druhé, a pandas vám dáva možnosti pre obe. Keďže v dátovej vede stĺpce zvyčajne reprezentujú premenné a riadky reprezentujú pozorovania, pravdepodobnejšie je, že odstránite riadky dát; predvolené nastavenie pre `dropna()` je odstrániť všetky riadky, ktoré obsahujú akékoľvek nulové hodnoty: ```python example2.dropna() ``` ``` 0 1 2 1 2.0 5.0 8 ``` Ak je to potrebné, môžete odstrániť hodnoty NA zo stĺpcov. Použite `axis=1` na to: ```python example2.dropna(axis='columns') ``` ``` 2 0 7 1 8 2 9 ``` Všimnite si, že to môže odstrániť veľa dát, ktoré by ste mohli chcieť zachovať, najmä v menších datasetoch. Čo ak chcete odstrániť iba riadky alebo stĺpce, ktoré obsahujú niekoľko alebo dokonca všetky nulové hodnoty? Tieto nastavenia môžete špecifikovať v `dropna` pomocou parametrov `how` a `thresh`. Predvolene je `how='any'` (ak by ste si to chceli overiť alebo vidieť, aké ďalšie parametre má metóda, spustite `example4.dropna?` v bunkách kódu). Alternatívne môžete špecifikovať `how='all'`, aby ste odstránili iba riadky alebo stĺpce, ktoré obsahujú všetky nulové hodnoty. Rozšírme náš príklad `DataFrame`, aby sme to videli v praxi. ```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| Parameter `thresh` vám poskytuje jemnejšiu kontrolu: nastavíte počet *nenulových* hodnôt, ktoré musí riadok alebo stĺpec obsahovať, aby bol zachovaný: ```python example2.dropna(axis='rows', thresh=3) ``` ``` 0 1 2 3 1 2.0 5.0 8 NaN ``` Tu boli prvý a posledný riadok odstránené, pretože obsahovali iba dve nenulové hodnoty. - **Vyplňovanie nulových hodnôt**: V závislosti od vášho datasetu môže niekedy dávať väčší zmysel vyplniť nulové hodnoty platnými hodnotami, než ich odstrániť. Mohli by ste použiť `isnull` na to, aby ste to urobili na mieste, ale to môže byť pracné, najmä ak máte veľa hodnôt na vyplnenie. Keďže ide o takú bežnú úlohu v dátovej vede, pandas poskytuje `fillna`, ktorý vráti kópiu `Series` alebo `DataFrame` s chýbajúcimi hodnotami nahradenými hodnotou podľa vášho výberu. Vytvorme ďalší príklad `Series`, aby sme videli, ako to funguje v praxi. ```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 ``` Môžete vyplniť všetky nulové záznamy jednou hodnotou, napríklad `0`: ```python example3.fillna(0) ``` ``` a 1.0 b 0.0 c 2.0 d 0.0 e 3.0 dtype: float64 ``` Môžete **dopredu vyplniť** nulové hodnoty, čo znamená použiť poslednú platnú hodnotu na vyplnenie nuly: ```python example3.fillna(method='ffill') ``` ``` a 1.0 b 1.0 c 2.0 d 2.0 e 3.0 dtype: float64 ``` Môžete tiež **dozadu vyplniť**, aby ste propagovali ďalšiu platnú hodnotu dozadu na vyplnenie nuly: ```python example3.fillna(method='bfill') ``` ``` a 1.0 b 2.0 c 2.0 d 3.0 e 3.0 dtype: float64 ``` Ako by ste mohli tušiť, toto funguje rovnako s `DataFrame`, ale môžete tiež špecifikovať `axis`, pozdĺž ktorého chcete vyplniť nulové hodnoty. Použijeme opäť predtým použitý `example2`: ```python example2.fillna(method='ffill', axis=1) ``` ``` 0 1 2 3 0 1.0 1.0 7.0 7.0 1 2.0 5.0 8.0 8.0 2 NaN 6.0 9.0 9.0 ``` Všimnite si, že keď predchádzajúca hodnota nie je dostupná na dopredné vyplnenie, nulová hodnota zostáva. > **Hlavná myšlienka:** Existuje viacero spôsobov, ako sa vysporiadať s chýbajúcimi hodnotami vo vašich dátových súboroch. Konkrétna stratégia, ktorú použijete (odstránenie, nahradenie alebo spôsob, akým ich nahradíte), by mala byť určená špecifikami daných dát. Čím viac budete pracovať s dátovými súbormi, tým lepšie pochopíte, ako riešiť chýbajúce hodnoty. ## Odstraňovanie duplicitných údajov > **Cieľ učenia:** Na konci tejto podsekcie by ste mali byť schopní identifikovať a odstraňovať duplicitné hodnoty z DataFrames. Okrem chýbajúcich údajov sa často stretnete s duplicitnými údajmi v reálnych datasetoch. Našťastie, `pandas` poskytuje jednoduchý spôsob na detekciu a odstránenie duplicitných záznamov. - **Identifikácia duplikátov: `duplicated`**: Duplicitné hodnoty môžete ľahko identifikovať pomocou metódy `duplicated` v pandas, ktorá vracia Boolean masku označujúcu, či je záznam v `DataFrame` duplikátom skoršieho záznamu. Vytvorme ďalší príklad `DataFrame`, aby sme si to ukázali v praxi. ```python example4 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'], 'numbers': [1, 2, 1, 3, 3]}) example4 ``` | |letters|numbers| |------|-------|-------| |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 ``` - **Odstraňovanie duplikátov: `drop_duplicates`:** jednoducho vráti kópiu údajov, kde všetky hodnoty označené ako `duplicated` sú `False`: ```python example4.drop_duplicates() ``` ``` letters numbers 0 A 1 1 B 2 3 B 3 ``` Metódy `duplicated` a `drop_duplicates` predvolene zohľadňujú všetky stĺpce, ale môžete špecifikovať, že majú skúmať iba podmnožinu stĺpcov vo vašom `DataFrame`: ```python example4.drop_duplicates(['letters']) ``` ``` letters numbers 0 A 1 1 B 2 ``` > **Záver:** Odstraňovanie duplicitných údajov je nevyhnutnou súčasťou takmer každého projektu v oblasti dátovej vedy. Duplicitné údaje môžu zmeniť výsledky vašich analýz a poskytnúť vám nepresné výsledky! ## 🚀 Výzva Všetky diskutované materiály sú dostupné ako [Jupyter Notebook](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/2-Working-With-Data/08-data-preparation/notebook.ipynb). Navyše, po každej sekcii sú k dispozícii cvičenia, vyskúšajte si ich! ## [Kvíz po prednáške](https://ff-quizzes.netlify.app/en/ds/quiz/15) ## Prehľad & Samoštúdium Existuje mnoho spôsobov, ako objaviť a pristupovať k príprave vašich údajov na analýzu a modelovanie, pričom čistenie údajov je dôležitým krokom, ktorý si vyžaduje praktické skúsenosti. Vyskúšajte tieto výzvy z Kaggle, aby ste preskúmali techniky, ktoré táto lekcia nepokrývala. - [Výzva na čistenie údajov: Parsovanie dátumov](https://www.kaggle.com/rtatman/data-cleaning-challenge-parsing-dates/) - [Výzva na čistenie údajov: Škálovanie a normalizácia údajov](https://www.kaggle.com/rtatman/data-cleaning-challenge-scale-and-normalize-data) ## Zadanie [Hodnotenie údajov z formulára](assignment.md) --- **Upozornenie**: Tento dokument bol preložený pomocou služby AI prekladu [Co-op Translator](https://github.com/Azure/co-op-translator). Aj keď sa snažíme o presnosť, prosím, berte na vedomie, že automatizované preklady môžu obsahovať chyby alebo nepresnosti. Pôvodný dokument v jeho pôvodnom jazyku by mal byť považovaný za autoritatívny zdroj. Pre kritické informácie sa odporúča profesionálny ľudský preklad. Nie sme zodpovední za akékoľvek nedorozumenia alebo nesprávne interpretácie vyplývajúce z použitia tohto prekladu.