Skip to content

Úpravy textů #82

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 0 additions & 39 deletions python-pro-data-1/agregace-a-spojovani/assets/maturita.csv

This file was deleted.

12 changes: 0 additions & 12 deletions python-pro-data-1/agregace-a-spojovani/assets/nakupy.csv

This file was deleted.

This file was deleted.

23 changes: 0 additions & 23 deletions python-pro-data-1/agregace-a-spojovani/assets/studenti.csv

This file was deleted.

16 changes: 0 additions & 16 deletions python-pro-data-1/agregace-a-spojovani/assets/u202.csv

This file was deleted.

16 changes: 0 additions & 16 deletions python-pro-data-1/agregace-a-spojovani/assets/u203.csv

This file was deleted.

15 changes: 0 additions & 15 deletions python-pro-data-1/agregace-a-spojovani/assets/u302.csv

This file was deleted.

138 changes: 31 additions & 107 deletions python-pro-data-1/agregace-a-spojovani/pokrocile-upravy.md
Original file line number Diff line number Diff line change
@@ -1,145 +1,69 @@
## Pokročilé úpravy

V předchozí lekci jsme si ukázali, jak v `pandas` vytváříme `DataFrame` a jak z něj můžeme vybírat data pomocí různých způsobů dotazování. Nyní se posuneme o kus dále a ukážeme si, jak můžeme s `DataFrame` dělat složitější operace jako je filtrování chybějících hodnot, spojování a agregace.

### Maturita

Abychom měli nějaký praktický příklad k procvičování, použijeme fiktivní data z výsledků maturitních zkoušek během jednoho týdne na nějakém menším gymnáziu. Maturita se odehrává ve třech místnostech: U202, U203 a U302. Máme tedy tři tabulky dat, z každé místnosti jednu. Níže si můžete prohlédnout příklad tabulky z místnosti U202. Všechny tabulky jsou ke stažení zde: [u202.csv](assets/u202.csv), [u203.csv](assets/u203.csv), [u302.csv](assets/u302.csv).

Funkce `read_csv()` knihovny `pandas` umí stáhnout CSV soubor rovnou z internetu.

```py
import pandas

u202 = pandas.read_csv("https://kodim.cz/cms/assets/analyza-dat/python-data-1/python-pro-data-1/agregace-a-spojovani/pokrocile-upravy/u202.csv")
u203 = pandas.read_csv("https://kodim.cz/cms/assets/analyza-dat/python-data-1/python-pro-data-1/agregace-a-spojovani/pokrocile-upravy/u203.csv")
u302 = pandas.read_csv("https://kodim.cz/cms/assets/analyza-dat/python-data-1/python-pro-data-1/agregace-a-spojovani/pokrocile-upravy/u302.csv")
```

|cisloStudenta |predmet |znamka|den|
|---:|:----------------|------:|:---|
|1 |Chemie | |pá |
|2 |Dějepis |3 |pá |
|3 |Matematika |2 |út |
|2 |Společenské vědy|2 |pá |
|4 |Biologie |1 |pá |
|5 |Dějepis |1 |po |
|6 |Fyzika |2 |čt |
|7 |Dějepis |4 |po |
|8 |Matematika |2 |po |
|9 |Dějepis | |pá |
|10 |Chemie |2 |st |
|3 |Chemie |5 |út |
|11 |Matematika |1 |st |
|12 |Biologie |4 |st |
|10 |Dějepis |5 |st |
V předchozí lekci jsme si ukázali, jak v `pandas` načteme data do tabulky (`DataFrame`) a jak z něj můžeme vybírat data pomocí různých způsobů dotazování. Nyní se posuneme o kus dále a ukážeme si, jak můžeme s `DataFrame` dělat složitější operace jako je filtrování chybějících hodnot, spojování a agregace.

### Práce s chybějícími hodnotami

V praxi se poměrně často setkáme s tím, že v datovém setu některé hodnoty chybí. Můžeme si například všimnout, že v tabulce U202 dvěma studentům chybí známka. To znamená, že se studenti k maturitě nedostavili. Na takové případy je třeba být připraven.

V `pandas`, ale i obecně v datové analýze, je možné se s chybějícími daty vypořádat různými způsoby:
V praxi se poměrně často setkáme s tím, že v datovém setu některé hodnoty chybí. Můžeme si například všimnout, že v tabulce `food_nutrient.csv` jsou chybějící hodnoty. Ty jsou při výpisu zobrazovány jako `NaN`.

1. Nejlepší je vždy ověření, proč údaje chybí (např. u poskytovatele dat) a pokud je to možné, zajistit jejich doplnění.
1. Nahradit chybějící hodnoty jinými hodnotami.
1. Odstranit všechny řádky s chybějícími daty z datového setu.
1. Vyčlenit je do separátního datasetu a zpracovat je zvlášť.
Při práci s daty, je možné se s chybějícími daty vypořádat různými způsoby.

Důležité je mít na paměti, že vyřazením některých řádků může dojít ke zkreslení výsledků analýzy!
Nejprve bychom si měli uvědomit, zda jsou pro nějaké sloupec chybějící hodnoty vlastně problém. Typický příklad sloupečku, kde to nevadí, je `footnote`. To, že k nějaké hodnotě není poznámka pod čarou, nevadí, zkrátka k měření žádná doplňující poznámka není. Naopak u sloupce `amount` to vadit může. U nějaké konkrétní výživné látky nevíme její obsah v nějaké konkrétní potravině.

### Odstranění neúplných řádků
Co v takovém případě udělat? Nejlepší je vždy ověření, proč údaje chybí (např. u poskytovatele dat, v metodice sběru, v programu na export dat) a pokud je to možné, zajistit jejich doplnění. Při hledání příčiny může pomoci i uložení těchto dat do samostatné tabulky, protože v ní můžeme vidět nějaké společné znaky, které tyto neúplné řádky mají. Zkusme si to na našich datech.

Předpokládejme, že jsme si ověřili, že data chybí skutečně pouze u studentů, kteří z daného předmětu nematurovali. Protože nás budou zajímat především statistiky jednotlivých předmětů, můžeme prázdné řádky vynechat, protože označují zkoušky, které ve skutečnosti neproběhly.

Pokud jsme tak ještě neučinili, načteme si naši první tabulku jako DataFrame.
Pokud nemáš načtená data, použij stejný příkaz jako v minulé lekci.

```py
import pandas
u202 = pandas.read_csv('u202.csv')
import pandas as pd
food_nutrient = pd.read_csv('food_nutrient.csv')
```

Pokud `pandas` narazí na prázdnou buňku, vloží místo ní do tabulky speciální hodnotu `NaN`, se kterou už jsme se setkali.

Série obsahují metodu `isnull()`, která vrátí pravdivostní sérii s hodnotou `True` všude tam, kde v původní sérii chybí hodnota. Metoda `notnull()` pracuje přesně opačně. Vrátí pravdivostní sérii s hodnotami `True` všude tam, kde v původní sérii hodnota nechybí.
Zkusíme si uložit řádky bez množství výživné látky do tabulky `food_nutrient_incomplete`. Použijeme metodu `isna()`, která pro každý řádek vrátí pravdivostní hodnotu (tj. hodnotu `True` pro řádek s hodnotou nebo `False` pro prázdný řádek). Poté můžeme použít dotaz, který jsme si ukázali už v minulé lekci.

```py
print(u202['znamka'].isnull())
food_nutrient_incomplete = food_nutrient[food_nutrient["amount"].isna()]
food_nutrient_incomplete.head()
```

```shell
0 True
1 False
2 False
3 False
4 False
5 False
6 False
7 False
8 False
9 True
10 False
11 False
12 False
13 False
14 False
Name: znamka, dtype: bool
```

Tyto metody můžeme využít například k tomu, abychom získali všechna data, kde chybí hodnota ve sloupečku `znamka`.
Metoda `.notna()` funuje obráceně (tj. vrací hodnotu `False` pro řádek s hodnotou nebo `True` pro prázdný řádek).

```py
print(u202[u202['znamka'].isnull()])
food_nutrient_complete = food_nutrient[food_nutrient["amount"].notna()]
food_nutrient_complete.head()
```

```shell
cisloStudenta predmet znamka den
0 1 Chemie NaN pá
9 9 Dějepis NaN pá
```
V některých případech může být vhodné nahradit chybějící hodnoty jinými hodnotami. Uvažujme třeba výkaz práce, kde je chybějící hodnota u nějakého zaměstnance a projektu. V programu, který data generuje, zjistíme, že to znamená, že daný zaměstnanec na projektu ten měsíc nepracoval. Prázdnou hodnotu tedy můžeme nahradit nulou.

Další užitečné metody na práci s chybějícími hodnotami najdeme na DataFrame.
Poslední možností je odstranit všechny řádky, které nejsou úplné. Musíme pak ale pamatovat na to, že již nepracujeme s kompletními daty. Vyřazením některých řádků může dojít ke zkreslení výsledků analýzy.

1. `dropna()` vrátí datový set očištěn od chybějících dat.
1. `dropna(axis=1)` odstraní všechny sloupce, které obsahují chybějící data.
1. `fillna(x)` nahradí všechna chybějící data a hodnoty hodnotou x.
V našem případě použijeme poslední možnost, tj. odstraníme všechny řádky, kde chybí množství výživné látky. K tomu je možné použít metodu `.notna()`, kterou jsme si už ukazovali. Ukážeme si ale ještě jednu metodu, a to `dropna()`. Pokud chceme, aby se metoda řídila pouze některými sloupci, použijeme parametr `subset` (podmnožina). V opačném případě metoda smaže všechny řádky, kde je chybějící hodnota alespoň v jednom sloupci.

### Spojení dat

Nyní bychom chtěli všechny tři naše tabulky spojit do jedné. Nejprve si ukážeme, jak spojit tabulky **pod sebe**. Výsledná tabulka tedy bude mít stále **tři sloupce** a **počet řádků bude odpovídat součtu počtu řádků všech tří tabulek**. V SQL používáme pro danou operaci klíčové slovo `UNION`.

Začneme s tím, že každou tabulku uložíme do `DataFrame` s tím, že vyhodíme studenty, kteří na maturitu nedorazili.
Jako hodnotu můžeme dát název jednoho sloupce jako řetězec nebo seznam názvů sloupců.

```py
u202 = pandas.read_csv('u202.csv').dropna()
u203 = pandas.read_csv('u203.csv').dropna()
u302 = pandas.read_csv('u302.csv').dropna()
food_nutrient = food_nutrient.dropna(subset="amount")
```

Pokud chceme tyto tři DataFrame spojit do jednoho, můžeme použít funkci `concat`.
### Spojení dat

```py
maturita = pandas.concat([u202, u203, u302])
```
Nyní bychom chtěli všechny tři naše tabulky spojit do jedné. Nejprve si ukážeme, jak spojit tabulky **pod sebe**. Jaké budou rozměry výsledné tabulky?

Pozor ale na to, že v takto vzniklém DataFrame se nám **rozbije index**, protože se prostě spojí za sebe indexy jednotlivých tabulek. Pokud chceme, aby `pandas` při spojování index přepočítal, musíme nastavit hodnotu parametru `ignore_index` na `True`.
- Počet **sloupců** je ve výsledné tabulce stejný jako u spojovaných tabulek.
- Počet **řádků** odpovídá součtu řádků spojovaných tabulek.

```py
maturita = pandas.concat([u202, u203, u302], ignore_index=True)
```
V SQL používáme pro danou operaci klíčové slovo `UNION`, `pandas` používáme funkci `concat()`.

To už je lepší. Stále nám však zůstává jeden problém. Po spojení tabulek do jedné už nevíme, kdo maturoval v jaké místnosti. Tuto informaci si proto doplníme do původních tří tabulek jako nový sloupeček. Až poté tabulky spojíme do jedné.
Začneme s tím, že každou tabulku uložíme do `DataFrame` s tím, že vyhodíme studenty, kteří na maturitu nedorazili.

```py
u202['mistnost'] = 'u202'
u203['mistnost'] = 'u203'
u302['mistnost'] = 'u302'
maturita = pandas.concat([u202, u203, u302], ignore_index=True)
```
My funkci využijeme, abychom si vytvořili větší tabulku s názvy potravin. V naší tabulce `food_sample_100.csv` máme pouze 100 vybraných potravin. My si k nim přidáme data z tabulky [food_other.csv](assets/food_other.csv).

Takto už nám vznikla pěkná vyčištěná tabulka. Uložme si ji do CSV, ať ji nemusíme vyrábět pořád znova. Nebudeme ukládat index, protože ten si vždycky necháme vyrobit automaticky.
Pozor na to, že v takto vzniklém DataFrame se nám **rozbije index**, protože se spojí za sebe indexy jednotlivých tabulek. Pokud chceme, aby `pandas` při spojování index přepočítal, musíme nastavit hodnotu parametru `ignore_index` na `True`.

```py
maturita.to_csv('maturita.csv', index=False)
food_other = pd.read_csv("food_other.csv", ignore_index=True)
food = pd.concat([food_sample_100, food_other])
```

Výslednou tabulku si můžete stáhnout jako soubor [maturita.csv](assets/maturita.csv).
K čemu je spojování vlastně dobré? Některé programy například ukládají data za každý den do samostatného souboru, takže pokud potřebujeme data za jeden týden, stačí nám stáhnout a spojit 7 souborů a ostatní stovky souborů a gigabajty dat můžeme ignorovat.

Loading