{ "nbformat": 4, "nbformat_minor": 2, "metadata": { "colab": { "name": "lesson_2-R.ipynb", "provenance": [], "collapsed_sections": [], "toc_visible": true }, "kernelspec": { "name": "ir", "display_name": "R" }, "language_info": { "name": "R" }, "coopTranslator": { "original_hash": "f3c335f9940cfd76528b3ef918b9b342", "translation_date": "2025-09-04T07:14:33+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "cs" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Vytvoření regresního modelu: příprava a vizualizace dat\n", "\n", "## **Lineární regrese pro dýně - Lekce 2**\n", "#### Úvod\n", "\n", "Nyní, když máte k dispozici nástroje potřebné k zahájení budování modelů strojového učení pomocí Tidymodels a Tidyverse, jste připraveni začít klást otázky svým datům. Při práci s daty a aplikaci řešení strojového učení je velmi důležité vědět, jak položit správnou otázku, abyste mohli plně využít potenciál svého datasetu.\n", "\n", "V této lekci se naučíte:\n", "\n", "- Jak připravit data pro budování modelu.\n", "\n", "- Jak používat `ggplot2` pro vizualizaci dat.\n", "\n", "Otázka, na kterou potřebujete odpověď, určí, jaký typ algoritmů strojového učení budete používat. Kvalita odpovědi, kterou získáte, bude silně záviset na povaze vašich dat.\n", "\n", "Podívejme se na to prostřednictvím praktického cvičení.\n", "\n", "\n", "

\n", " \n", "

Ilustrace od @allison_horst
\n", "\n", "\n", "\n" ], "metadata": { "id": "Pg5aexcOPqAZ" } }, { "cell_type": "markdown", "source": [ "## 1. Importování dat o dýních a přivolání Tidyverse\n", "\n", "Budeme potřebovat následující balíčky, abychom mohli rozdělit a zpracovat tuto lekci:\n", "\n", "- `tidyverse`: [tidyverse](https://www.tidyverse.org/) je [sbírka balíčků pro R](https://www.tidyverse.org/packages), která je navržena tak, aby byla datová věda rychlejší, jednodušší a zábavnější!\n", "\n", "Můžete je nainstalovat pomocí:\n", "\n", "`install.packages(c(\"tidyverse\"))`\n", "\n", "Níže uvedený skript zkontroluje, zda máte balíčky potřebné k dokončení tohoto modulu, a v případě, že některé chybí, je pro vás nainstaluje.\n" ], "metadata": { "id": "dc5WhyVdXAjR" } }, { "cell_type": "code", "execution_count": null, "source": [ "suppressWarnings(if(!require(\"pacman\")) install.packages(\"pacman\"))\n", "pacman::p_load(tidyverse)" ], "outputs": [], "metadata": { "id": "GqPYUZgfXOBt" } }, { "cell_type": "markdown", "source": [ "Nyní spusťme některé balíčky a načtěme [data](https://github.com/microsoft/ML-For-Beginners/blob/main/2-Regression/data/US-pumpkins.csv) poskytnutá pro tuto lekci!\n" ], "metadata": { "id": "kvjDTPDSXRr2" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Load the core Tidyverse packages\n", "library(tidyverse)\n", "\n", "# Import the pumpkins data\n", "pumpkins <- read_csv(file = \"https://raw.githubusercontent.com/microsoft/ML-For-Beginners/main/2-Regression/data/US-pumpkins.csv\")\n", "\n", "\n", "# Get a glimpse and dimensions of the data\n", "glimpse(pumpkins)\n", "\n", "\n", "# Print the first 50 rows of the data set\n", "pumpkins %>% \n", " slice_head(n =50)" ], "outputs": [], "metadata": { "id": "VMri-t2zXqgD" } }, { "cell_type": "markdown", "source": [ "Rychlý `glimpse()` okamžitě ukazuje, že jsou zde prázdné hodnoty a směs řetězců (`chr`) a číselných dat (`dbl`). `Date` je typu znakového řetězce a je tu také zvláštní sloupec nazvaný `Package`, kde jsou data směsí mezi `sacks`, `bins` a dalšími hodnotami. Data jsou vlastně trochu chaotická 😤.\n", "\n", "Ve skutečnosti není příliš běžné dostat dataset, který je zcela připravený k použití pro vytvoření ML modelu hned na první pokus. Ale nezoufejte, v této lekci se naučíte, jak připravit surový dataset pomocí standardních knihoven v R 🧑‍🔧. Také se naučíte různé techniky vizualizace dat.📈📊\n", "
\n", "\n", "> Připomenutí: Operátor pipe (`%>%`) provádí operace v logickém sledu tím, že předává objekt dál do funkce nebo výrazu. Můžete si operátor pipe představit jako \"a potom\" ve vašem kódu.\n" ], "metadata": { "id": "REWcIv9yX29v" } }, { "cell_type": "markdown", "source": [ "## 2. Kontrola chybějících dat\n", "\n", "Jedním z nejčastějších problémů, se kterými se datoví vědci musí vypořádat, jsou neúplná nebo chybějící data. R reprezentuje chybějící nebo neznámé hodnoty pomocí speciálního sentinelového hodnoty: `NA` (Not Available).\n", "\n", "Jak tedy zjistíme, že datový rámec obsahuje chybějící hodnoty?\n", "
\n", "- Jedním z nejjednodušších způsobů je použití základní funkce R `anyNA`, která vrací logické objekty `TRUE` nebo `FALSE`.\n" ], "metadata": { "id": "Zxfb3AM5YbUe" } }, { "cell_type": "code", "execution_count": null, "source": [ "pumpkins %>% \n", " anyNA()" ], "outputs": [], "metadata": { "id": "G--DQutAYltj" } }, { "cell_type": "markdown", "source": [ "Skvělé, zdá se, že některá data chybí! To je dobré místo, kde začít.\n", "\n", "- Dalším způsobem by bylo použít funkci `is.na()`, která označuje, které jednotlivé prvky sloupce chybí pomocí logické hodnoty `TRUE`.\n" ], "metadata": { "id": "mU-7-SB6YokF" } }, { "cell_type": "code", "execution_count": null, "source": [ "pumpkins %>% \n", " is.na() %>% \n", " head(n = 7)" ], "outputs": [], "metadata": { "id": "W-DxDOR4YxSW" } }, { "cell_type": "markdown", "source": [ "Dobře, hotovo, ale s tak velkým datovým rámcem, jako je tento, by bylo neefektivní a prakticky nemožné zkontrolovat všechny řádky a sloupce jednotlivě😴.\n", "\n", "- Intuitivnější způsob by byl spočítat součet chybějících hodnot pro každý sloupec:\n" ], "metadata": { "id": "xUWxipKYY0o7" } }, { "cell_type": "code", "execution_count": null, "source": [ "pumpkins %>% \n", " is.na() %>% \n", " colSums()" ], "outputs": [], "metadata": { "id": "ZRBWV6P9ZArL" } }, { "cell_type": "markdown", "source": [ "Mnohem lepší! Chybí některá data, ale možná to nebude mít vliv na daný úkol. Uvidíme, jaký další rozbor přinese.\n", "\n", "> Spolu s úžasnými balíčky a funkcemi má R velmi dobrou dokumentaci. Například použijte `help(colSums)` nebo `?colSums`, abyste se dozvěděli více o této funkci.\n" ], "metadata": { "id": "9gv-crB6ZD1Y" } }, { "cell_type": "markdown", "source": [ "## 3. Dplyr: Gramatika manipulace s daty\n", "\n", "

\n", " \n", "

Ilustrace od @allison_horst
\n", "\n", "\n", "\n" ], "metadata": { "id": "o4jLY5-VZO2C" } }, { "cell_type": "markdown", "source": [ "[`dplyr`](https://dplyr.tidyverse.org/), balíček v Tidyverse, je gramatikou manipulace s daty, která poskytuje konzistentní sadu sloves, jež vám pomohou vyřešit nejběžnější výzvy při manipulaci s daty. V této části se podíváme na některá slovesa z dplyr! \n", "
\n" ], "metadata": { "id": "i5o33MQBZWWw" } }, { "cell_type": "markdown", "source": [ "#### dplyr::select()\n", "\n", "`select()` je funkce z balíčku `dplyr`, která vám pomáhá vybrat sloupce, které chcete zachovat nebo vyloučit.\n", "\n", "Abyste si usnadnili práci s datovým rámcem, odstraňte několik jeho sloupců pomocí `select()` a ponechte pouze ty, které potřebujete.\n", "\n", "Například v tomto cvičení bude naše analýza zahrnovat sloupce `Package`, `Low Price`, `High Price` a `Date`. Pojďme tyto sloupce vybrat.\n" ], "metadata": { "id": "x3VGMAGBZiUr" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Select desired columns\n", "pumpkins <- pumpkins %>% \n", " select(Package, `Low Price`, `High Price`, Date)\n", "\n", "\n", "# Print data set\n", "pumpkins %>% \n", " slice_head(n = 5)" ], "outputs": [], "metadata": { "id": "F_FgxQnVZnM0" } }, { "cell_type": "markdown", "source": [ "#### dplyr::mutate()\n", "\n", "`mutate()` je funkce z balíčku `dplyr`, která vám umožňuje vytvářet nebo upravovat sloupce, přičemž zachovává stávající sloupce.\n", "\n", "Obecná struktura funkce mutate je:\n", "\n", "`data %>% mutate(new_column_name = what_it_contains)`\n", "\n", "Pojďme si vyzkoušet `mutate` na sloupci `Date` provedením následujících operací:\n", "\n", "1. Převést data (aktuálně typu znak) na formát měsíce (jedná se o americká data, takže formát je `MM/DD/YYYY`).\n", "\n", "2. Extrahovat měsíc z dat do nového sloupce.\n", "\n", "V R balíček [lubridate](https://lubridate.tidyverse.org/) usnadňuje práci s daty a časy. Takže použijeme `dplyr::mutate()`, `lubridate::mdy()`, `lubridate::month()` a podíváme se, jak dosáhnout výše uvedených cílů. Sloupec Date můžeme vynechat, protože ho v dalších operacích nebudeme potřebovat.\n" ], "metadata": { "id": "2KKo0Ed9Z1VB" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Load lubridate\n", "library(lubridate)\n", "\n", "pumpkins <- pumpkins %>% \n", " # Convert the Date column to a date object\n", " mutate(Date = mdy(Date)) %>% \n", " # Extract month from Date\n", " mutate(Month = month(Date)) %>% \n", " # Drop Date column\n", " select(-Date)\n", "\n", "# View the first few rows\n", "pumpkins %>% \n", " slice_head(n = 7)" ], "outputs": [], "metadata": { "id": "5joszIVSZ6xe" } }, { "cell_type": "markdown", "source": [ "Hurá! 🤩\n", "\n", "Nyní vytvořme nový sloupec `Price`, který bude představovat průměrnou cenu dýně. Vezmeme průměr hodnot ze sloupců `Low Price` a `High Price` a použijeme jej k naplnění nového sloupce Price.\n", "
\n" ], "metadata": { "id": "nIgLjNMCZ-6Y" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Create a new column Price\n", "pumpkins <- pumpkins %>% \n", " mutate(Price = (`Low Price` + `High Price`)/2)\n", "\n", "# View the first few rows of the data\n", "pumpkins %>% \n", " slice_head(n = 5)" ], "outputs": [], "metadata": { "id": "Zo0BsqqtaJw2" } }, { "cell_type": "markdown", "source": [ "Yeees!💪\n", "\n", "„Ale počkejte!“, řeknete po rychlém prohlédnutí celého datového souboru pomocí `View(pumpkins)`, „Tady je něco zvláštního!“🤔\n", "\n", "Pokud se podíváte na sloupec `Package`, dýně se prodávají v mnoha různých konfiguracích. Některé se prodávají v mírách `1 1/9 bushel`, některé v mírách `1/2 bushel`, některé na kus, některé na váhu, a některé ve velkých krabicích s různými šířkami.\n", "\n", "Pojďme si to ověřit:\n" ], "metadata": { "id": "p77WZr-9aQAR" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Verify the distinct observations in Package column\n", "pumpkins %>% \n", " distinct(Package)" ], "outputs": [], "metadata": { "id": "XISGfh0IaUy6" } }, { "cell_type": "markdown", "source": [ "Úžasné!👏\n", "\n", "Zdá se, že dýně je velmi těžké vážit konzistentně, takže je vyfiltrujeme tím, že vybereme pouze dýně, které obsahují řetězec *bushel* ve sloupci `Package`, a uložíme je do nového datového rámce `new_pumpkins`.\n" ], "metadata": { "id": "7sMjiVujaZxY" } }, { "cell_type": "markdown", "source": [ "#### dplyr::filter() a stringr::str_detect()\n", "\n", "[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html): vytváří podmnožinu dat obsahující pouze **řádky**, které splňují vaše podmínky, v tomto případě dýně s řetězcem *bushel* ve sloupci `Package`.\n", "\n", "[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html): zjišťuje přítomnost nebo nepřítomnost vzoru v řetězci.\n", "\n", "Balíček [`stringr`](https://github.com/tidyverse/stringr) poskytuje jednoduché funkce pro běžné operace s řetězci.\n" ], "metadata": { "id": "L8Qfcs92ageF" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Retain only pumpkins with \"bushel\"\n", "new_pumpkins <- pumpkins %>% \n", " filter(str_detect(Package, \"bushel\"))\n", "\n", "# Get the dimensions of the new data\n", "dim(new_pumpkins)\n", "\n", "# View a few rows of the new data\n", "new_pumpkins %>% \n", " slice_head(n = 5)" ], "outputs": [], "metadata": { "id": "hy_SGYREampd" } }, { "cell_type": "markdown", "source": [ "Můžete vidět, že jsme zúžili výběr na přibližně 415 řádků dat obsahujících dýně po bušlech.🤩 \n", "
\n" ], "metadata": { "id": "VrDwF031avlR" } }, { "cell_type": "markdown", "source": [ "#### dplyr::case_when()\n", "\n", "**Ale počkejte! Ještě je třeba něco udělat**\n", "\n", "Všimli jste si, že množství v bušlech se liší podle řádku? Je potřeba normalizovat ceny tak, aby ukazovaly cenu za bušel, a ne za 1 1/9 nebo 1/2 bušle. Je čas provést nějaké výpočty, abychom to standardizovali.\n", "\n", "Použijeme funkci [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html) k *úpravě* sloupce Price na základě určitých podmínek. `case_when` umožňuje vektorizovat více `if_else()` výroků.\n" ], "metadata": { "id": "mLpw2jH4a0tx" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Convert the price if the Package contains fractional bushel values\n", "new_pumpkins <- new_pumpkins %>% \n", " mutate(Price = case_when(\n", " str_detect(Package, \"1 1/9\") ~ Price/(1 + 1/9),\n", " str_detect(Package, \"1/2\") ~ Price/(1/2),\n", " TRUE ~ Price))\n", "\n", "# View the first few rows of the data\n", "new_pumpkins %>% \n", " slice_head(n = 30)" ], "outputs": [], "metadata": { "id": "P68kLVQmbM6I" } }, { "cell_type": "markdown", "source": [ "Nyní můžeme analyzovat cenu za jednotku na základě jejich měření v bušlech. Celá tato studie bušlů dýní však ukazuje, jak velmi `důležité` je `pochopit povahu vašich dat`!\n", "\n", "> ✅ Podle [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308) závisí váha bušle na typu produktu, protože jde o objemové měření. \"Bušl rajčat by například měl vážit 56 liber... Listy a zelené rostliny zabírají více prostoru s menší váhou, takže bušl špenátu váží pouze 20 liber.\" Je to všechno docela složité! Nezabývejme se převodem bušlů na libry a místo toho stanovme cenu podle bušle. Celá tato studie bušlů dýní však ukazuje, jak velmi důležité je pochopit povahu vašich dat!\n", ">\n", "> ✅ Všimli jste si, že dýně prodávané na půl bušle jsou velmi drahé? Dokážete zjistit proč? Nápověda: malé dýně jsou mnohem dražší než velké, pravděpodobně proto, že jich je mnohem více na bušl, vzhledem k nevyužitému prostoru, který zabírá jedna velká dutá dýně na koláč.\n" ], "metadata": { "id": "pS2GNPagbSdb" } }, { "cell_type": "markdown", "source": [ "Nyní nakonec, čistě pro dobrodružství 💁‍♀️, pojďme také přesunout sloupec Month na první pozici, tj. `před` sloupec `Package`.\n", "\n", "Funkce `dplyr::relocate()` se používá ke změně pozic sloupců.\n" ], "metadata": { "id": "qql1SowfbdnP" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Create a new data frame new_pumpkins\n", "new_pumpkins <- new_pumpkins %>% \n", " relocate(Month, .before = Package)\n", "\n", "new_pumpkins %>% \n", " slice_head(n = 7)" ], "outputs": [], "metadata": { "id": "JJ1x6kw8bixF" } }, { "cell_type": "markdown", "source": [ "Dobrá práce!👌 Nyní máte čistý a uspořádaný dataset, na kterém můžete postavit svůj nový regresní model! \n", "
\n" ], "metadata": { "id": "y8TJ0Za_bn5Y" } }, { "cell_type": "markdown", "source": [ "## 4. Vizualizace dat s ggplot2\n", "\n", "

\n", " \n", "

Infografika od Dasani Madipalli
\n", "\n", "\n", "\n", "\n", "Existuje *moudré* rčení, které říká:\n", "\n", "> \"Jednoduchý graf přinesl analytikovi více informací než jakékoli jiné zařízení.\" --- John Tukey\n", "\n", "Součástí role datového vědce je ukázat kvalitu a povahu dat, se kterými pracuje. K tomu často vytváří zajímavé vizualizace, nebo grafy, diagramy a tabulky, které zobrazují různé aspekty dat. Tímto způsobem mohou vizuálně ukázat vztahy a mezery, které by jinak bylo obtížné odhalit.\n", "\n", "Vizualizace také mohou pomoci určit, která technika strojového učení je pro daná data nejvhodnější. Například bodový graf, který se zdá sledovat přímku, naznačuje, že data jsou vhodným kandidátem pro úlohu lineární regrese.\n", "\n", "R nabízí několik systémů pro tvorbu grafů, ale [`ggplot2`](https://ggplot2.tidyverse.org/index.html) je jedním z nejelegantnějších a nejvšestrannějších. `ggplot2` vám umožňuje skládat grafy **kombinováním nezávislých komponent**.\n", "\n", "Začněme jednoduchým bodovým grafem pro sloupce Price a Month.\n", "\n", "V tomto případě začneme s [`ggplot()`](https://ggplot2.tidyverse.org/reference/ggplot.html), dodáme dataset a estetické mapování (pomocí [`aes()`](https://ggplot2.tidyverse.org/reference/aes.html)) a poté přidáme vrstvy (jako [`geom_point()`](https://ggplot2.tidyverse.org/reference/geom_point.html)) pro bodové grafy.\n" ], "metadata": { "id": "mYSH6-EtbvNa" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Set a theme for the plots\n", "theme_set(theme_light())\n", "\n", "# Create a scatter plot\n", "p <- ggplot(data = new_pumpkins, aes(x = Price, y = Month))\n", "p + geom_point()" ], "outputs": [], "metadata": { "id": "g2YjnGeOcLo4" } }, { "cell_type": "markdown", "source": [ "Je tento graf užitečný 🤷? Překvapilo vás na něm něco?\n", "\n", "Není příliš užitečný, protože pouze zobrazuje vaše data jako rozptyl bodů v daném měsíci. \n", "
\n" ], "metadata": { "id": "Ml7SDCLQcPvE" } }, { "cell_type": "markdown", "source": [ "### **Jak to udělat užitečné?**\n", "\n", "Aby grafy zobrazovaly užitečná data, obvykle je potřeba data nějakým způsobem seskupit. Například v našem případě by nalezení průměrné ceny dýní za každý měsíc poskytlo více informací o základních vzorcích v našich datech. To nás přivádí k dalšímu rychlému přehledu **dplyr**:\n", "\n", "#### `dplyr::group_by() %>% summarize()`\n", "\n", "Seskupenou agregaci v R lze snadno vypočítat pomocí\n", "\n", "`dplyr::group_by() %>% summarize()`\n", "\n", "- `dplyr::group_by()` mění jednotku analýzy z celého datasetu na jednotlivé skupiny, například podle měsíců.\n", "\n", "- `dplyr::summarize()` vytváří nový datový rámec s jedním sloupcem pro každou seskupovací proměnnou a jedním sloupcem pro každou zadanou statistiku shrnutí.\n", "\n", "Například můžeme použít `dplyr::group_by() %>% summarize()` k seskupení dýní do skupin na základě sloupce **Month** a následně najít **průměrnou cenu** za každý měsíc.\n" ], "metadata": { "id": "jMakvJZIcVkh" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Find the average price of pumpkins per month\r\n", "new_pumpkins %>%\r\n", " group_by(Month) %>% \r\n", " summarise(mean_price = mean(Price))" ], "outputs": [], "metadata": { "id": "6kVSUa2Bcilf" } }, { "cell_type": "markdown", "source": [ "Stručně!✨\n", "\n", "Kategorie, jako jsou měsíce, se lépe zobrazují pomocí sloupcového grafu 📊. Vrstvy, které se používají pro sloupcové grafy, jsou `geom_bar()` a `geom_col()`. Podívejte se na `?geom_bar`, abyste zjistili více.\n", "\n", "Pojďme si jeden vytvořit!\n" ], "metadata": { "id": "Kds48GUBcj3W" } }, { "cell_type": "code", "execution_count": null, "source": [ "# Find the average price of pumpkins per month then plot a bar chart\r\n", "new_pumpkins %>%\r\n", " group_by(Month) %>% \r\n", " summarise(mean_price = mean(Price)) %>% \r\n", " ggplot(aes(x = Month, y = mean_price)) +\r\n", " geom_col(fill = \"midnightblue\", alpha = 0.7) +\r\n", " ylab(\"Pumpkin Price\")" ], "outputs": [], "metadata": { "id": "VNbU1S3BcrxO" } }, { "cell_type": "markdown", "source": [ "🤩🤩 Toto je užitečnější vizualizace dat! Zdá se, že naznačuje, že nejvyšší cena za dýně se vyskytuje v září a říjnu. Odpovídá to vašemu očekávání? Proč ano nebo proč ne?\n", "\n", "Gratulujeme k dokončení druhé lekce 👏! Připravili jste svá data pro tvorbu modelu a poté odhalili další poznatky pomocí vizualizací!\n" ], "metadata": { "id": "zDm0VOzzcuzR" } }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n---\n\n**Prohlášení**: \nTento dokument byl přeložen pomocí služby pro automatický překlad [Co-op Translator](https://github.com/Azure/co-op-translator). Ačkoli se snažíme o přesnost, mějte na paměti, že automatické překlady mohou obsahovat chyby nebo nepřesnosti. Původní dokument v jeho původním jazyce by měl být považován za autoritativní zdroj. Pro důležité informace doporučujeme profesionální lidský překlad. Neodpovídáme za žádné nedorozumění nebo nesprávné interpretace vyplývající z použití tohoto překladu.\n" ] } ] }