{ "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-06T11:58:28+00:00", "source_file": "2-Regression/2-Data/solution/R/lesson_2-R.ipynb", "language_code": "no" } }, "cells": [ { "cell_type": "markdown", "source": [ "# Bygg en regresjonsmodell: forbered og visualiser data\n", "\n", "## **Lineær regresjon for gresskar - Leksjon 2**\n", "#### Introduksjon\n", "\n", "Nå som du har verktøyene du trenger for å begynne å bygge maskinlæringsmodeller med Tidymodels og Tidyverse, er du klar til å begynne å stille spørsmål til dataene dine. Når du jobber med data og bruker ML-løsninger, er det svært viktig å forstå hvordan du stiller de riktige spørsmålene for å virkelig utnytte potensialet i datasettet ditt.\n", "\n", "I denne leksjonen vil du lære:\n", "\n", "- Hvordan forberede dataene dine for modellbygging.\n", "\n", "- Hvordan bruke `ggplot2` til datavisualisering.\n", "\n", "Spørsmålet du ønsker svar på, vil avgjøre hvilken type ML-algoritmer du vil bruke. Og kvaliteten på svaret du får, vil i stor grad avhenge av kvaliteten på dataene dine.\n", "\n", "La oss se på dette gjennom en praktisk øvelse.\n", "\n", "\n", "
\n",
" \n",
"
\n",
"\n",
"> En oppfriskning: Pipe-operatoren (`%>%`) utfører operasjoner i logisk rekkefølge ved å sende et objekt videre inn i en funksjon eller et uttrykk. Du kan tenke på pipe-operatoren som å si \"og så\" i koden din.\n"
],
"metadata": {
"id": "REWcIv9yX29v"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Sjekk etter manglende data\n",
"\n",
"En av de vanligste utfordringene dataforskere må håndtere er ufullstendige eller manglende data. R representerer manglende eller ukjente verdier med en spesiell sentinel-verdi: `NA` (Not Available).\n",
"\n",
"Så hvordan kan vi finne ut om datasettet inneholder manglende verdier? \n",
"
\n",
"- En enkel måte er å bruke base R-funksjonen `anyNA`, som returnerer de logiske verdiene `TRUE` eller `FALSE`.\n"
],
"metadata": {
"id": "Zxfb3AM5YbUe"
}
},
{
"cell_type": "code",
"execution_count": null,
"source": [
"pumpkins %>% \n",
" anyNA()"
],
"outputs": [],
"metadata": {
"id": "G--DQutAYltj"
}
},
{
"cell_type": "markdown",
"source": [
"Flott, det ser ut til å mangle noen data! Det er et godt sted å starte.\n",
"\n",
"- En annen måte er å bruke funksjonen `is.na()` som viser hvilke individuelle kolonneelementer som mangler ved å returnere en logisk `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": [
"Ok, jobben er gjort, men med en så stor dataramme som dette, ville det vært ineffektivt og praktisk talt umulig å gå gjennom alle radene og kolonnene individuelt😴.\n",
"\n",
"- En mer intuitiv måte ville være å beregne summen av de manglende verdiene for hver kolonne:\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": [
"Mye bedre! Det mangler data, men kanskje det ikke vil ha betydning for oppgaven. La oss se hva videre analyse bringer frem.\n",
"\n",
"> Sammen med de fantastiske pakkene og funksjonene, har R veldig god dokumentasjon. For eksempel, bruk `help(colSums)` eller `?colSums` for å finne ut mer om funksjonen.\n"
],
"metadata": {
"id": "9gv-crB6ZD1Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Dplyr: En grammatikk for datamanipulering\n",
"\n",
"
\n",
" \n",
"
\n"
],
"metadata": {
"id": "i5o33MQBZWWw"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::select()\n",
"\n",
"`select()` er en funksjon i pakken `dplyr` som hjelper deg med å velge kolonner du vil beholde eller utelate.\n",
"\n",
"For å gjøre datarammen din enklere å jobbe med, fjern flere av kolonnene ved å bruke `select()`, og behold kun de kolonnene du trenger.\n",
"\n",
"For eksempel, i denne øvelsen vil analysen vår involvere kolonnene `Package`, `Low Price`, `High Price` og `Date`. La oss velge disse kolonnene.\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()` er en funksjon i pakken `dplyr` som hjelper deg med å lage eller endre kolonner, samtidig som de eksisterende kolonnene beholdes.\n",
"\n",
"Den generelle strukturen for mutate er:\n",
"\n",
"`data %>% mutate(new_column_name = what_it_contains)`\n",
"\n",
"La oss prøve `mutate` ved å bruke `Date`-kolonnen og utføre følgende operasjoner:\n",
"\n",
"1. Konverter datoene (som for øyeblikket er av typen karakter) til et månedsformat (disse er amerikanske datoer, så formatet er `MM/DD/YYYY`).\n",
"\n",
"2. Ekstraher måneden fra datoene til en ny kolonne.\n",
"\n",
"I R gjør pakken [lubridate](https://lubridate.tidyverse.org/) det enklere å jobbe med dato- og tidsdata. Så la oss bruke `dplyr::mutate()`, `lubridate::mdy()`, `lubridate::month()` og se hvordan vi kan oppnå de ovennevnte målene. Vi kan fjerne Date-kolonnen siden vi ikke vil trenge den igjen i senere operasjoner.\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": [
"Woohoo! 🤩\n",
"\n",
"La oss nå opprette en ny kolonne `Price`, som representerer gjennomsnittsprisen på et gresskar. Nå skal vi ta gjennomsnittet av kolonnene `Low Price` og `High Price` for å fylle ut den nye kolonnen 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": [
"Jaaa!💪\n",
"\n",
"\"Men vent litt!\", sier du etter å ha skummet gjennom hele datasettet med `View(pumpkins)`, \"Det er noe rart her!\"🤔\n",
"\n",
"Hvis du ser på `Package`-kolonnen, blir gresskar solgt i mange forskjellige konfigurasjoner. Noen selges i `1 1/9 bushel`-mål, noen i `1/2 bushel`-mål, noen per gresskar, noen per pund, og noen i store bokser med varierende bredder.\n",
"\n",
"La oss bekrefte dette:\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": [
"Fantastisk!👏\n",
"\n",
"Gresskar ser ut til å være veldig vanskelige å veie konsekvent, så la oss filtrere dem ved å velge kun gresskar med strengen *bushel* i `Package`-kolonnen og legge dette i en ny data frame `new_pumpkins`.\n"
],
"metadata": {
"id": "7sMjiVujaZxY"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::filter() og stringr::str_detect()\n",
"\n",
"[`dplyr::filter()`](https://dplyr.tidyverse.org/reference/filter.html): lager et delsett av dataene som kun inneholder **rader** som oppfyller dine betingelser, i dette tilfellet gresskar med strengen *bushel* i `Package`-kolonnen.\n",
"\n",
"[stringr::str_detect()](https://stringr.tidyverse.org/reference/str_detect.html): oppdager tilstedeværelsen eller fraværet av et mønster i en streng.\n",
"\n",
"[`stringr`](https://github.com/tidyverse/stringr)-pakken gir enkle funksjoner for vanlige operasjoner med strenger.\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": [
"Du kan se at vi har snevret det ned til rundt 415 rader med data som inneholder gresskar i store mengder.🤩 \n",
"
\n"
],
"metadata": {
"id": "VrDwF031avlR"
}
},
{
"cell_type": "markdown",
"source": [
"#### dplyr::case_when()\n",
"\n",
"**Men vent! Det er én ting til å gjøre**\n",
"\n",
"La du merke til at mengden per skjeppe varierer per rad? Du må normalisere prisen slik at du viser prisen per skjeppe, ikke per 1 1/9 eller 1/2 skjeppe. Tid for litt matte for å standardisere det.\n",
"\n",
"Vi skal bruke funksjonen [`case_when()`](https://dplyr.tidyverse.org/reference/case_when.html) for å *mutere* kolonnen Price avhengig av noen betingelser. `case_when` lar deg vektorisere flere `if_else()`-utsagn.\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å kan vi analysere prisen per enhet basert på deres måling i skjepper. All denne studien av skjepper med gresskar viser imidlertid hvor `viktig` det er å `forstå naturen til dataene dine`!\n",
"\n",
"> ✅ Ifølge [The Spruce Eats](https://www.thespruceeats.com/how-much-is-a-bushel-1389308) avhenger vekten av en skjepp av typen råvare, siden det er en volum-måling. \"En skjepp med tomater, for eksempel, skal veie 56 pund... Blader og grønnsaker tar opp mer plass med mindre vekt, så en skjepp med spinat veier bare 20 pund.\" Det er ganske komplisert! La oss ikke bry oss med å gjøre en skjepp-til-pund-konvertering, og heller prise per skjepp. All denne studien av skjepper med gresskar viser imidlertid hvor viktig det er å forstå naturen til dataene dine!\n",
">\n",
"> ✅ La du merke til at gresskar som selges per halv skjepp er veldig dyre? Kan du finne ut hvorfor? Hint: små gresskar er mye dyrere enn store, sannsynligvis fordi det er så mange flere av dem per skjepp, gitt den ubrukte plassen som tas opp av ett stort, hul paigresskar.\n"
],
"metadata": {
"id": "pS2GNPagbSdb"
}
},
{
"cell_type": "markdown",
"source": [
"Nå til slutt, for eventyrets skyld 💁♀️, la oss også flytte Måned-kolonnen til første posisjon, altså `før` kolonnen `Pakke`.\n",
"\n",
"`dplyr::relocate()` brukes for å endre kolonneposisjoner.\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": [
"Godt jobbet!👌 Du har nå et rent og ryddig datasett som du kan bruke til å bygge din nye regresjonsmodell!\n"
],
"metadata": {
"id": "y8TJ0Za_bn5Y"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Datavisualisering med ggplot2\n",
"\n",
"
\n",
" \n",
"
\n"
],
"metadata": {
"id": "Ml7SDCLQcPvE"
}
},
{
"cell_type": "markdown",
"source": [
"### **Hvordan gjør vi det nyttig?**\n",
"\n",
"For å få diagrammer til å vise nyttige data, må du vanligvis gruppere dataene på en eller annen måte. For eksempel, i vårt tilfelle, vil det å finne gjennomsnittsprisen på gresskar for hver måned gi mer innsikt i de underliggende mønstrene i dataene våre. Dette leder oss til enda en **dplyr** gjennomgang:\n",
"\n",
"#### `dplyr::group_by() %>% summarize()`\n",
"\n",
"Gruppert aggregering i R kan enkelt beregnes ved hjelp av\n",
"\n",
"`dplyr::group_by() %>% summarize()`\n",
"\n",
"- `dplyr::group_by()` endrer analyseenheten fra hele datasettet til individuelle grupper, som for eksempel per måned.\n",
"\n",
"- `dplyr::summarize()` lager en ny dataramme med én kolonne for hver grupperingsvariabel og én kolonne for hver av de oppsummeringsstatistikkene du har spesifisert.\n",
"\n",
"For eksempel kan vi bruke `dplyr::group_by() %>% summarize()` til å gruppere gresskar i grupper basert på **Month**-kolonnen og deretter finne **gjennomsnittsprisen** for hver måned.\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": [
"Kompakt!✨\n",
"\n",
"Kategoriske variabler som måneder blir bedre representert ved hjelp av et stolpediagram 📊. Lagene som brukes for stolpediagrammer er `geom_bar()` og `geom_col()`. Sjekk `?geom_bar` for å lære mer.\n",
"\n",
"La oss lage et!\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": [
"🤩🤩Dette er en mer nyttig datavisualisering! Det ser ut til å indikere at den høyeste prisen for gresskar forekommer i september og oktober. Stemmer dette med dine forventninger? Hvorfor eller hvorfor ikke?\n",
"\n",
"Gratulerer med å ha fullført den andre leksjonen 👏! Du forberedte dataene dine for modellbygging, og deretter avdekket du flere innsikter ved hjelp av visualiseringer!\n"
],
"metadata": {
"id": "zDm0VOzzcuzR"
}
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n---\n\n**Ansvarsfraskrivelse**: \nDette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi streber etter nøyaktighet, vær oppmerksom på at automatiserte oversettelser kan inneholde feil eller unøyaktigheter. Det originale dokumentet på sitt opprinnelige språk bør anses som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som oppstår ved bruk av denne oversettelsen.\n"
]
}
]
}