{ "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:25:48+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "uk" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Побудова регресійної моделі: підготовка та візуалізація даних\n", "\n", "## **Лінійна регресія для гарбузів - Урок 2**\n", "#### Вступ\n", "\n", "Тепер, коли ви налаштували інструменти для створення моделей машинного навчання за допомогою Tidymodels і Tidyverse, ви готові почати ставити запитання до своїх даних. Працюючи з даними та застосовуючи рішення машинного навчання, дуже важливо вміти правильно формулювати запитання, щоб максимально розкрити потенціал вашого набору даних.\n", "\n", "У цьому уроці ви дізнаєтеся:\n", "\n", "- Як підготувати дані для побудови моделі.\n", "\n", "- Як використовувати `ggplot2` для візуалізації даних.\n", "\n", "Запитання, на яке ви хочете отримати відповідь, визначатиме, які алгоритми машинного навчання ви будете використовувати. А якість отриманої відповіді значною мірою залежатиме від характеру ваших даних.\n", "\n", "Давайте розглянемо це на практичному прикладі.\n", "\n", "
\n",
" \n",
"
\n",
"\n",
"> Нагадування: Оператор pipe (`%>%`) виконує операції в логічній послідовності, передаючи об'єкт далі у функцію або вираз виклику. Ви можете уявити оператор pipe як \"а потім\" у вашому коді.\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Перевірка на відсутні дані\n",
"\n",
"Однією з найпоширеніших проблем, з якими стикаються дата-сайентисти, є неповні або відсутні дані. У R відсутні або невідомі значення позначаються спеціальним значенням-сторожем: `NA` (Not Available).\n",
"\n",
"Тож як ми можемо дізнатися, що у фреймі даних є відсутні значення? \n",
"
\n",
"- Один із простих способів — використати базову функцію R `anyNA`, яка повертає логічні значення `TRUE` або `FALSE`.\n"
],
"metadata": {
"id": "Zxfb3AM5YbUe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" anyNA()"
],
"outputs": [],
"metadata": {
"id": "G--DQutAYltj"
}
},
{
"cell_type": "markdown",
"source": [
"Чудово, здається, деякі дані відсутні! Це гарне місце, щоб почати.\n",
"\n",
"- Інший спосіб — використати функцію `is.na()`, яка вказує, які окремі елементи стовпця відсутні, за допомогою логічного значення `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": [
"Гаразд, завдання виконано, але з таким великим фреймом даних, як цей, було б неефективно і практично неможливо переглянути всі рядки та стовпці окремо😴.\n",
"\n",
"- Більш інтуїтивним способом було б обчислити суму відсутніх значень для кожного стовпця:\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": [
"Набагато краще! Даних не вистачає, але, можливо, це не матиме значення для виконання завдання. Подивимося, до чого приведе подальший аналіз.\n",
"\n",
"> Окрім чудового набору пакетів і функцій, R має дуже хорошу документацію. Наприклад, використовуйте `help(colSums)` або `?colSums`, щоб дізнатися більше про функцію.\n"
],
"metadata": {
"id": "9gv-crB6ZD1Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Dplyr: Граматика обробки даних\n",
"\n",
"
\n",
" \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": [
"Так!💪\n",
"\n",
"\"Стривайте!\", скажете ви, переглянувши весь набір даних за допомогою `View(pumpkins)`, \"Тут щось дивне!\"🤔\n",
"\n",
"Якщо подивитися на стовпець `Package`, гарбузи продаються в багатьох різних конфігураціях. Деякі продаються в мірах `1 1/9 bushel`, деякі в мірах `1/2 bushel`, деякі поштучно, деякі за вагу, а деякі в великих коробках з різною шириною.\n",
"\n",
"Давайте перевіримо це:\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": [
"Дивовижно!👏\n",
"\n",
"Гарбузи, здається, дуже важко зважувати стабільно, тому давайте відфільтруємо їх, вибравши лише ті гарбузи, у яких у стовпці `Package` є рядок *bushel*, і помістимо це в новий датафрейм `new_pumpkins`.\n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() та stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html): створює підмножину даних, яка містить лише **рядки**, що відповідають вашим умовам, у цьому випадку гарбузи зі словом *bushel* у стовпці `Package`.\n",
"\n",
"[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html): визначає наявність або відсутність шаблону в рядку.\n",
"\n",
"Пакет [`stringr`](https://github.com/tidyverse/stringr) надає прості функції для поширених операцій з рядками.\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": [
"Ви можете побачити, що ми звузили вибір до приблизно 415 рядків даних, які містять гарбузи за бушель.🤩 \n",
"
\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**Але зачекайте! Є ще одна річ, яку потрібно зробити**\n",
"\n",
"Ви помітили, що кількість бушелів змінюється в кожному рядку? Вам потрібно нормалізувати ціни, щоб показувати вартість за бушель, а не за 1 1/9 або 1/2 бушеля. Час зробити трохи математики, щоб стандартизувати це.\n",
"\n",
"Ми використаємо функцію [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html), щоб *змінити* колонку Price залежно від певних умов. `case_when` дозволяє векторизувати кілька операторів `if_else()`.\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": [
"Тепер ми можемо проаналізувати ціни за одиницю, базуючись на їх вимірюванні в бушелях. Уся ця робота з бушелями гарбузів, однак, показує, наскільки `важливо` `розуміти природу ваших даних`!\n",
"\n",
"> ✅ Згідно з [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308), вага бушеля залежить від типу продукту, оскільки це об'ємне вимірювання. \"Бушель помідорів, наприклад, має важити 56 фунтів... Листя та зелень займають більше місця з меншою вагою, тому бушель шпинату важить лише 20 фунтів.\" Це все досить складно! Давайте не будемо займатися перетворенням бушелів у фунти, а замість цього визначимо ціну за бушель. Уся ця робота з бушелями гарбузів, однак, показує, наскільки важливо розуміти природу ваших даних!\n",
">\n",
"> ✅ Ви помітили, що гарбузи, які продаються за півбушеля, дуже дорогі? Можете здогадатися, чому? Підказка: маленькі гарбузи набагато дорожчі за великі, ймовірно, тому що їх набагато більше в одному бушелі, враховуючи невикористаний простір, який займає один великий порожнистий гарбуз для пирога.\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"Тепер, нарешті, заради пригоди 💁♀️, давайте також перемістимо стовпець Month на першу позицію, тобто `перед` стовпцем `Package`.\n",
"\n",
"Функція `dplyr::relocate()` використовується для зміни позицій стовпців.\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": [
"Молодець!👌 Тепер у вас є чистий, впорядкований набір даних, на основі якого ви можете створити нову регресійну модель! \n",
"
\n"
],
"metadata": {
"id": "y8TJ0Za_bn5Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Візуалізація даних за допомогою ggplot2\n",
"\n",
"
\n",
" \n",
"
\n"
],
"metadata": {
"id": "Ml7SDCLQcPvE"
}
},
{
"cell_type": "markdown",
"source": [
"### **Як зробити це корисним?**\n",
"\n",
"Щоб графіки відображали корисні дані, зазвичай потрібно якось згрупувати ці дані. Наприклад, у нашому випадку, визначення середньої ціни гарбузів за кожен місяць надасть більше розуміння прихованих закономірностей у наших даних. Це приводить нас до ще одного швидкого огляду **dplyr**:\n",
"\n",
"#### `dplyr::group_by() %>% summarize()`\n",
"\n",
"Групову агрегацію в R можна легко виконати за допомогою\n",
"\n",
"`dplyr::group_by() %>% summarize()`\n",
"\n",
"- `dplyr::group_by()` змінює одиницю аналізу з усього набору даних на окремі групи, наприклад, за місяцями.\n",
"\n",
"- `dplyr::summarize()` створює новий набір даних із одним стовпцем для кожної змінної групування та одним стовпцем для кожної з обчислених статистик.\n",
"\n",
"Наприклад, ми можемо використати `dplyr::group_by() %>% summarize()` для групування гарбузів за стовпцем **Month**, а потім знайти **середню ціну** для кожного місяця.\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": [
"Лаконічно!✨\n",
"\n",
"Категоріальні ознаки, такі як місяці, краще представляти за допомогою стовпчастої діаграми 📊. Шари, які відповідають за створення стовпчастих діаграм, це `geom_bar()` і `geom_col()`. Зверніться до `?geom_bar`, щоб дізнатися більше.\n",
"\n",
"Давайте створимо одну!\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": [
"🤩🤩Це більш корисна візуалізація даних! Здається, вона показує, що найвища ціна на гарбузи спостерігається у вересні та жовтні. Чи відповідає це вашим очікуванням? Чому так або чому ні?\n",
"\n",
"Вітаю з завершенням другого уроку 👏! Ви підготували свої дані для побудови моделі, а потім виявили більше інсайтів за допомогою візуалізацій!\n"
],
"metadata": {
"id": "zDm0VOzzcuzR"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Відмова від відповідальності**: \nЦей документ було перекладено за допомогою сервісу автоматичного перекладу [Co-op Translator](https://github.com/Azure/co-op-translator). Хоча ми прагнемо до точності, зверніть увагу, що автоматичні переклади можуть містити помилки або неточності. Оригінальний документ мовою оригіналу слід вважати авторитетним джерелом. Для критично важливої інформації рекомендується професійний людський переклад. Ми не несемо відповідальності за будь-які непорозуміння або неправильні тлумачення, що виникли внаслідок використання цього перекладу.\n"
]
}
]
}