{ "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-06T13:50:30+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "sr" } }, "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",
"> Подсетник: Оператор цеви (`%>%`) извршава операције у логичком низу тако што прослеђује објекат функцији или изразу. Можете замислити оператор цеви као да у вашем коду каже \"и онда\".\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": "i5o33MQBZWWw"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::select()\n",
"\n",
"`select()` је функција у пакету `dplyr` која вам помаже да изаберете колоне које желите да задржите или изузмете.\n",
"\n",
"Да бисте свој рад са подацима учинили једноставнијим, уклоните неколико колона из вашег оквира података користећи `select()`, задржавајући само оне колоне које су вам потребне.\n",
"\n",
"На пример, у овој вежби, наша анализа ће обухватати колоне `Package`, `Low Price`, `High Price` и `Date`. Хајде да изаберемо те колоне.\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()` је функција у пакету `dplyr` која вам помаже да креирате или модификујете колоне, а да притом задржите постојеће колоне.\n",
"\n",
"Општа структура функције `mutate` је:\n",
"\n",
"`data %>% mutate(new_column_name = what_it_contains)`\n",
"\n",
"Хајде да испробамо `mutate` користећи колону `Date` и извршимо следеће операције:\n",
"\n",
"1. Претворимо датуме (који су тренутно типа карактер) у формат месеца (ово су датуми у америчком формату, дакле `MM/DD/YYYY`).\n",
"\n",
"2. Извуцимо месец из датума у нову колону.\n",
"\n",
"У програмском језику R, пакет [lubridate](https://lubridate.tidyverse.org/) олакшава рад са подацима типа датум-време. Дакле, хајде да користимо `dplyr::mutate()`, `lubridate::mdy()`, `lubridate::month()` и видимо како да постигнемо горе наведене циљеве. Можемо избацити колону `Date` јер нам више неће бити потребна у наредним операцијама.\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": [
"Ура! 🤩\n",
"\n",
"Следеће, хајде да направимо нову колону `Price`, која представља просечну цену бундеве. Сада, хајде да узмемо просек из колона `Low Price` и `High Price` како бисмо попунили нову колону 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": [
"Дааа!💪\n",
"\n",
"\"Али чекај!\", рећи ћеш након што прелетиш цео скуп података помоћу `View(pumpkins)`, \"Овде нешто није у реду!\"🤔\n",
"\n",
"Ако погледаш колону `Package`, бундеве се продају у различитим конфигурацијама. Неке се продају у мерама `1 1/9 бушел`, неке у мерама `1/2 бушел`, неке по бундеви, неке по фунти, а неке у великим кутијама различитих ширина.\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": [
"Сада, зарад авантуре 💁♀️, хајде да преместимо колону \"Месец\" на прву позицију, односно `пре` колоне `Пакет`.\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"
]
}
]
}