From f68982cdbaf8f64594118fd51c8ae84c085bba30 Mon Sep 17 00:00:00 2001 From: toravest Date: Mon, 26 May 2025 12:42:44 +0200 Subject: [PATCH] reread notebooks, "nan" to 'NaN', explain regression (linear and polynomial) --- README.md | 2 +- notebooks/notebook_compare_one_day_data.ipynb | 14 +- .../notebook_compare_one_week_data.ipynb | 27 +- .../notebook_compare_statistic_data.ipynb | 23 +- notebooks/notebook_current_data.ipynb | 4 +- notebooks/notebook_interactive_data.ipynb | 8 +- notebooks/notebook_one_day_data.ipynb | 153 ++++++++--- notebooks/notebook_one_week_data.ipynb | 23 +- notebooks/notebook_regression.ipynb | 237 +++++++++++++++--- notebooks/notebook_statistic_data.ipynb | 164 +++++++----- src/my_package/util.py | 10 +- tests/unit/test_clean_data.py | 6 +- 12 files changed, 494 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index b3f363d..5e28fcf 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ Vi har stort sett brukt matplotlib i alle notebook-ene. Vi har også brukt Seabo ##### Demonstrer hvordan manglende data håndteres i visualiseringene. Lag en graf som viser hvordan manglende verdier påvirker datatrender, og diskuter hvordan dette kan påvirke tolkningen av dataene. -Visualiseringen finner man i notebook-ene. Vi har identifisert manglende data og fylt NaN med 0 der det er nødvendig og gitt en ny visualisering der dette er fylt inn. Manglende verdier kan påvirke datatrender og tolkning blant annet ved at dersom dataen interpoleres automatisk kan man tolke trender som ikke finnes. Eller så kan manglende verdier føre til at viktige mønstre blir skjult. Det kan også hende at dette da fører til at en analytiker har en modell eller beslutning basert på trender som ikke har virkelig data. +Visualiseringen finner man i notebook-ene. Vi har identifisert manglende data og fylt 'NaN' med 0 der det er nødvendig og gitt en ny visualisering der dette er fylt inn. Manglende verdier kan påvirke datatrender og tolkning blant annet ved at dersom dataen interpoleres automatisk kan man tolke trender som ikke finnes. Eller så kan manglende verdier føre til at viktige mønstre blir skjult. Det kan også hende at dette da fører til at en analytiker har en modell eller beslutning basert på trender som ikke har virkelig data. ##### Skriv en kort evaluering av de utviklede visualiseringene. Diskuter hvilke visualiseringer som var mest effektive for å formidle informasjon, og hvorfor. Reflekter over tilbakemeldinger fra medstudenter eller veileder. diff --git a/notebooks/notebook_compare_one_day_data.ipynb b/notebooks/notebook_compare_one_day_data.ipynb index 4c06a91..57ed33c 100644 --- a/notebooks/notebook_compare_one_day_data.ipynb +++ b/notebooks/notebook_compare_one_day_data.ipynb @@ -227,11 +227,11 @@ "metadata": {}, "source": [ "### Viser temperaturen\n", - "Vi bruker pandas SQL for å hente ut temperaturen for begge stedene, og lagrer de i en tabell. Ved hjelp av 'pivot' , en innebygd funksjon for å rotere tabeller, setter vi den opp for bedre lesbarhet, ved å sette begge byene ved siden av hverandre og 'dt' som index. Dette gjør det lettere å sammenligne temperaturen for begge stedene til samme tid.\n", + "Vi bruker pandas SQL for å hente ut temperaturen for begge stedene, og lagrer de i en tabell. Ved hjelp av 'pivot', en innebygd funksjon for å rotere tabeller, setter vi den opp for bedre lesbarhet, ved å sette begge byene ved siden av hverandre og 'dt' som index. Dette gjør det lettere å sammenligne temperaturen for begge stedene til samme tid.\n", "\n", "Ved hjelp av en pandas SQL setning kan vi hente og lagre gjennomsnitt, maksimalt og minste målte temperatur for begge stedene. Senere kan vi bare skrive en SELECT setning til denne variabelen, for å eksepelhvis hente ut gjennomsnitts data for sted 1.\n", "\n", - "Det å regne ut median og standardavvik er ikke innebygd i SQL, i motsetning til gjennomsnitt, maks og min. Derfor regner vi ut disse verdiene manuelt. Vi henter temperatur data fra, grupperer dataen basert på city_name, og bruker den innebygde pandas funksjonen `median()` og `std()`, for hendholdsvis median og standardavvik. Siden verdiene grupperes på city_name, blir det indeksen med medianverdi som verdi. Derfor bruker vi `.reset_index()` for å nullstille og gjøre city_name til en kolonne, som bruker til å koble de to tabellene samen, med funksjonen `merge()`." + "Det å regne ut median og standardavvik er ikke innebygd i SQL, i motsetning til gjennomsnitt, maks og min. Derfor regner vi ut disse verdiene manuelt. Vi henter temperatur data fra temp_data, grupperer dataen basert på city_name, og bruker de innebygde pandas og numpy funksjonene `median()` og `std()`, for hendholdsvis median og standardavvik. Siden verdiene grupperes på city_name, blir det indeksen med median/standardavvik som verdi. Derfor bruker vi `.reset_index()` for å nullstille og gjøre city_name til en kolonne, som bruker til å koble de to tabellene samen, med funksjonen `merge()`." ] }, { @@ -340,7 +340,7 @@ "source": [ "### Endre manglende verdier\n", "\n", - "Om vi har manglende verdieer kan det tyde på to ting, 1. feil i målingen eller 2. det er ingenting å måle. Nr. 2 ser vi spesielt på kolonnene 'rain.1h' og 'snow.1h', om det ikke er snødd/regnet vil verdien bli lagret for 'NaN'. 'NaN' er ikke mulig å plotte, så vi ønsker å lagre verdien som 0 isteden. Vi importerer derfor funksjonen `fill_column_0` som tar inn datafram og kolonner vi ønsker at 'NaN' verdien skal byttes ut med 0. \n", + "Om vi har manglende verdier kan det tyde på to ting, 1. feil i målingen eller 2. det er ingenting å måle. Nr. 2 ser vi spesielt på kolonnene 'rain.1h' og 'snow.1h', om det ikke er snødd/regnet vil verdien bli lagret for 'NaN'. 'NaN' er ikke mulig å plotte, så vi ønsker å lagre verdien som 0 isteden. Vi importerer derfor funksjonen `fill_column_0` som tar inn dataframe og kolonner vi ønsker at 'NaN' verdien skal byttes ut med 0. \n", "\n", "Om det er kolonner hvor alle verdiene er 'NaN' fjerner vi hele kolonnen, dette fordi verdien 0 ikke vil gi oss mer informasjon uansett.\n", "\n", @@ -364,7 +364,7 @@ "\n", "columns_to_0 = ['rain.1h', 'snow.1h']\n", "\n", - "# Fill NaN values with 0, if there are any, for both rain/snow column\n", + "# Fill 'NaN' values with 0, if there are any, for both rain/snow column\n", "both_cities_df = fill_column_0(both_cities_df, columns_to_0)\n", "\n", "# Drops the whole column, if it only has 'NaN' value.\n", @@ -403,7 +403,7 @@ "### Visualisere data i en graf\n", "Ved hjelp av Matplotlib har vi visualiert ønsket data, og ved hjelp av subplot, en modul i matplotlib, kan vi plotte flere verdier i samme graf, og få \"to y-akse\" på samme x-akse. \n", "\n", - "Temperatur for begge stedene finner vi i den øverste grafen, hvor vi også har lagt inn gjennomsnittstemperaturen. Her har vi bare skrevet nye SELECT setninger som henter ut gjennomsnitt for begge steder fra 'stat_temp_per_city'.\n", + "Temperatur for begge stedene finner vi i den øverste grafen, hvor vi også har lagt inn gjennomsnittstemperaturen og medianen. Her har vi bare skrevet nye SELECT setninger som henter ut gjennomsnitt og median for begge steder fra 'stat_temp_per_city'.\n", "\n", "I grafen under ser vi oversikt over nedbør for begge stedene sammenlignet 'side om side'. Vi skiller også mellom snø og regn, og dersom det skulle snø og regne i samme time, vil de bare 'stables' oppå hverandre.\n", "\n", @@ -529,7 +529,7 @@ "\n", "For å lese av grafen, finner man en variabel vertikalt og en horisontal variabel. Der de møtes i diagrammet er korrelasjons koeffisienten mellom disse.\n", "\n", - "Her har vi laget en korrelasjonsmatrsie for hver av stedene, slik at man kan sammeligne om et sted har sterkere eller svakere sammenhenger mellom de ulike variablene.\n", + "Her har vi laget en korrelasjonsmatrise for hver av stedene, slik at man kan sammeligne om et sted har sterkere eller svakere sammenhenger mellom de ulike variablene.\n", "\n", "Grafen lagres i mappen `../data/figures/output_fig_compare_one_day`" ] @@ -556,7 +556,7 @@ "columns_needed = ['main.temp', 'main.pressure', 'main.humidity', 'wind.speed', 'wind.gust', 'clouds.all', 'rain.1h', 'snow.1h']\n", "\n", "# Two horisontally plots (1 row, 2 columns), width and height of the figure\n", - "fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # Adjust figsize as needed\n", + "fig, axes = plt.subplots(1, 2, figsize=(15, 8)) # Adjust figsize as needed\n", "\n", "# Loops through both cities, the enumerate make sure we get both the city and the index of the city\n", "for i, city in enumerate(cities):\n", diff --git a/notebooks/notebook_compare_one_week_data.ipynb b/notebooks/notebook_compare_one_week_data.ipynb index a81168e..adac993 100644 --- a/notebooks/notebook_compare_one_week_data.ipynb +++ b/notebooks/notebook_compare_one_week_data.ipynb @@ -7,7 +7,7 @@ "source": [ "# Notebook - Compare one week data\n", "\n", - "Denne notebooken henter data fra to ønskede steder i Norge, etter ønsket tidspreiode (intill 7-dager) og sammenligner dataen ved hjelp av visualisering i matplotlib av temperatur og nedbør." + "Denne notebooken henter data fra to ønskede steder i Norge, etter ønsket tidspreiode (inntil 7-dager) og sammenligner dataen ved hjelp av visualisering i matplotlib av temperatur og nedbør." ] }, { @@ -69,9 +69,10 @@ "id": "0b9d1a95", "metadata": {}, "source": [ - "### Velg første sted til sammenligning\n", + "### Velg første sted til sammenligningen\n", + "For å kunne sammenligne data fra to steder, trenger vi først to steder å sammenligne. Stedene er foreløpig begrenset til Norge.\n", "\n", - "Skriv inn et av stedene du ønsker å sammenligne, foreløpig begrenset til Norge." + "Her kunne vi brukt en løkke, spesielt en while løkke for å sjekke at stedet fungerer, og for å kjøre begge stedene på samme celle. Men vi har valgt å kjøre en og en for lettere å oppfatte feil ved sted, og at dersom sted 1 blir feil, må du ikke velge sted 2 på nytt." ] }, { @@ -106,7 +107,9 @@ "metadata": {}, "source": [ "### Velg andre sted til sammenligningen\n", - "Velg det andre stedet som skal brukes i sammenligningen, fortsatt begrenset til Norge." + "Velg det andre stedet som skal brukes i sammenligningen, fortsatt begrenset til Norge.\n", + "\n", + "Det er vanskelig å sammenligne det samme stedet. Derfor har vi lagt inn en while-løkke som sjekker om sted 2 er likt sted 1, og kjører frem til de er forskjellige." ] }, { @@ -149,7 +152,7 @@ "\n", "Vi samler dataen for begge stedene og skriver de til en json fil.\n", "\n", - "Skriv inn navn for til filen du vil lagre med dataen.\n", + "Skriv inn navn for filen du vil lagre med dataen.\n", "\n", "Eks. filnavn: test\n", "\n", @@ -246,11 +249,11 @@ "metadata": {}, "source": [ "### Viser temperaturen\n", - "Vi bruker pandas SQL for å hente ut temperaturen for begge stedene, og lagrer de i en tabell. Ved hjelp av 'pivot' , en innebygd funksjon for å rotere tabeller, setter vi den opp for bedre lesbarhet, ved å sette begge byene ved siden av hverandre og 'dt' som index. Dette gjør det lettere å sammenligne temperaturen for begge stedene til samme tid.\n", + "Vi bruker pandas SQL for å hente ut temperaturen for begge stedene, og lagrer de i en tabell. Ved hjelp av 'pivot', en innebygd funksjon for å rotere tabeller, setter vi den opp for bedre lesbarhet, ved å sette begge byene ved siden av hverandre og 'dt' som index. Dette gjør det lettere å sammenligne temperaturen for begge stedene til samme tid.\n", "\n", "Ved hjelp av en pandas SQL setning kan vi hente og lagre gjennomsnitt, maksimalt og minste målte temperatur for begge stedene. Senere kan vi bare skrive en SELECT setning til denne variabelen, for å eksepelhvis hente ut gjennomsnitts data for sted 1.\n", "\n", - "Det å regne ut median og standardavvik er ikke innebygd i SQL, i motsetning til gjennomsnitt, maks og min. Derfor regner vi ut disse verdiene manuelt. Vi henter temperatur data fra, grupperer dataen basert på city_name, og bruker den innebygde pandas funksjonen `median()` og `std()`, for hendholdsvis median og standardavvik. Siden verdiene grupperes på city_name, blir det indeksen med medianverdi som verdi. Derfor bruker vi `.reset_index()` for å nullstille og gjøre city_name til en kolonne, som bruker til å koble de to tabellene samen, med funksjonen `merge()`." + "Det å regne ut median og standardavvik er ikke innebygd i SQL, i motsetning til gjennomsnitt, maks og min. Derfor regner vi ut disse verdiene manuelt. Vi henter temperatur data fra temp_data, grupperer dataen basert på city_name, og bruker de innebygde pandas og numpy funksjonene `median()` og `std()`, for hendholdsvis median og standardavvik. Siden verdiene grupperes på city_name, blir det indeksen med median/standardavvik som verdi. Derfor bruker vi `.reset_index()` for å nullstille og gjøre city_name til en kolonne, som bruker til å koble de to tabellene samen, med funksjonen `merge()`." ] }, { @@ -365,7 +368,7 @@ "source": [ "### Endre manglende verdier\n", "\n", - "Om vi har manglende verdieer kan det tyde på to ting, 1. feil i målingen eller 2. det er ingenting å måle. Nr. 2 ser vi spesielt på kolonnene 'rain.1h' og 'snow.1h', om det ikke er snødd/regnet vil verdien bli lagret for 'NaN'. 'NaN' er ikke mulig å plotte, så vi ønsker å lagre verdien som 0 isteden. Vi importerer derfor funksjonen `fill_column_0` som tar inn datafram og kolonner vi ønsker at 'NaN' verdien skal byttes ut med 0. \n", + "Om vi har manglende verdier kan det tyde på to ting, 1. feil i målingen eller 2. det er ingenting å måle. Nr. 2 ser vi spesielt på kolonnene 'rain.1h' og 'snow.1h', om det ikke er snødd/regnet vil verdien bli lagret for 'NaN'. 'NaN' er ikke mulig å plotte, så vi ønsker å lagre verdien som 0 isteden. Vi importerer derfor funksjonen `fill_column_0` som tar inn dataframe og kolonner vi ønsker at 'NaN' verdien skal byttes ut med 0. \n", "\n", "Om det er kolonner hvor alle verdiene er 'NaN' fjerner vi hele kolonnen, dette fordi verdien 0 ikke vil gi oss mer informasjon uansett.\n", "\n", @@ -390,7 +393,7 @@ "\n", "columns_to_0 = ['rain.1h', 'snow.1h']\n", "\n", - "# Fill NaN values with 0, if there are any, for both rain/snow column\n", + "# Fill 'NaN' values with 0, if there are any, for both rain/snow column\n", "both_cities_df = fill_column_0(both_cities_df, columns_to_0)\n", "\n", "# Drops the whole column, if it only has 'NaN' value.\n", @@ -432,7 +435,7 @@ "### Visualisere data i en graf\n", "Ved hjelp av Matplotlib har vi visualiert ønsket data, og ved hjelp av subplot, en modul i matplotlib, kan vi plotte flere verdier i samme graf, og få \"to y-akse\" på samme x-akse. \n", "\n", - "Temperatur for begge stedene finner vi i den øverste grafen, hvor vi også har lagt inn gjennomsnittstemperaturen. Her har vi bare skrevet nye SELECT setninger som henter ut gjennomsnitt for begge steder fra 'stat_temp_per_city'.\n", + "Temperatur for begge stedene finner vi i den øverste grafen, hvor vi også har lagt inn gjennomsnittstemperaturen og medianen. Her har vi bare skrevet nye SELECT setninger som henter ut gjennomsnitt og median for begge steder fra 'stat_temp_per_city'.\n", "\n", "I grafen under ser vi oversikt over nedbør for begge stedene sammenlignet 'side om side'. Vi skiller også mellom snø og regn, og dersom det skulle snø og regne i samme time, vil de bare 'stables' oppå hverandre.\n", "\n", @@ -560,7 +563,7 @@ "\n", "For å lese av grafen, finner man en variabel vertikalt og en horisontal variabel. Der de møtes i diagrammet er korrelasjons koeffisienten mellom disse.\n", "\n", - "Her har vi laget en korrelasjonsmatrsie for hver av stedene, slik at man kan sammeligne om et sted har sterkere eller svakere sammenhenger mellom de ulike variablene.\n", + "Her har vi laget en korrelasjonsmatrise for hver av stedene, slik at man kan sammeligne om et sted har sterkere eller svakere sammenhenger mellom de ulike variablene.\n", "\n", "Grafen lagres i mappen `../data/figures/output_fig_compare_one_week`" ] @@ -588,7 +591,7 @@ "columns_needed = ['main.temp', 'main.pressure', 'main.humidity', 'wind.speed', 'wind.gust', 'clouds.all', 'rain.1h', 'snow.1h']\n", "\n", "# Two horisontally plots (1 row, 2 columns), width and height of the figure\n", - "fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # Adjust figsize as needed\n", + "fig, axes = plt.subplots(1, 2, figsize=(15, 8)) # Adjust figsize as needed\n", "\n", "# Loops through both cities, the enumerate make sure we get both the city and the index of the city\n", "for i, city in enumerate(cities):\n", diff --git a/notebooks/notebook_compare_statistic_data.ipynb b/notebooks/notebook_compare_statistic_data.ipynb index 467db6c..170773a 100644 --- a/notebooks/notebook_compare_statistic_data.ipynb +++ b/notebooks/notebook_compare_statistic_data.ipynb @@ -23,7 +23,7 @@ "\n", "Statistikken er basert på de historiske datane total sett, ikke for hvert år.\n", "\n", - "API-en bruker mellom 30 og 50s på å hente dataen, så vær tålmodig!" + "API-en kan bruke litt tid, så det er bare å være tålmodig." ] }, { @@ -56,7 +56,8 @@ "id": "41293f67", "metadata": {}, "source": [ - "### Velg det andre stedet til sammenligningen" + "### Velg det andre stedet til sammenligningen\n", + "Det er vanskelig å sammenligne det samme stedet. Derfor har vi lagt inn en while-løkke som sjekker om sted 2 er likt sted 1, og kjører frem til de er forskjellige." ] }, { @@ -96,7 +97,7 @@ "source": [ "### Lagre data i json-fil\n", "\n", - "Skriv inn navn for til filen du vil lagre med dataen.\n", + "Skriv inn navn til filen du vil lagre med dataen.\n", "\n", "Eks. filnavn: test\n", "\n", @@ -141,7 +142,7 @@ "### Lese fra fil\n", "Sørger for at dataen lagret over blir mer lesbar.\n", "\n", - "Og lagrer verdiene for hver av stedene i egne dataframes." + "Og lagrer verdiene for hver av stedene i egne dataframes, legger til stednr og stedsnavn. Før de blir slått sammen til en dataframe, som vi kan bruke pandasSQL for å hente data mot." ] }, { @@ -185,9 +186,9 @@ "metadata": {}, "source": [ "### Rydder i data\n", - "Fjerner alle kolonner vi ikke trenger, som standardavvik for alle kategorier for alle dager, vi kan regne ut en felles ved å bruke statistisc modulen. \n", + "Fjerner alle kolonner vi ikke trenger, som standardavvik for alle kategorier for alle dager, vi kan regne ut en felles ved å bruke den innebygde numpy funksjonen `.std()`.\n", "\n", - "Ettersom alle kateogirene har lik data, ogg vi vil fjerne noen av verdiene fra alle kategoriene. Kan vi bruke filter funksjonen til å filtrere ut dataene som inneholder f.eks. '.st_dev'. Dette gjør at alle kategoirene fjernes på likt å vi slipper å skrive alle flere ganger." + "Ettersom alle kategorier har lik data, og vi vil fjerne noen av verdiene fra alle kategoriene. Derfor importerer vi en funksjon vi har lagd, `clean_df` som fjerner alle disse kolonne med et filter på kategoriens slutt." ] }, { @@ -211,11 +212,11 @@ "metadata": {}, "source": [ "### Viser temperaturen\n", - "Vi bruker pandas SQL for å hente ut temperaturen for begge stedene, og lagrer de i en tabell. Ved hjelp av 'pivot' , en innebygd funksjon for å rotere tabeller, setter vi den opp for bedre lesbarhet, ved å sette begge byene ved siden av hverandre og en sammenslåing av kolonnene måned og dag ('month_day') som index. Dette gjør det lettere å sammenligne temperaturen for begge stedene til samme tid.\n", + "Vi bruker pandas SQL for å hente ut temperaturen for begge stedene, og lagrer de i en tabell. Ved hjelp av 'pivot', en innebygd funksjon for å rotere tabeller, setter vi den opp for bedre lesbarhet, ved å sette begge byene ved siden av hverandre og en sammenslåing av kolonnene måned og dag ('month_day') som index. Dette gjør det lettere å sammenligne temperaturen for begge stedene til samme tid.\n", "\n", "Ved hjelp av en pandas SQL setning kan vi hente og lagre gjennomsnitt, maksimalt og minste målte temperatur for begge stedene. Senere kan vi bare skrive en SELECT setning til denne variabelen, for å eksepelhvis hente ut gjennomsnitts data for sted 1.\n", "\n", - "Det å regne ut median og standardavvik er ikke innebygd i SQL, i motsetning til gjennomsnitt, maks og min. Derfor regner vi ut disse verdiene manuelt. Vi henter temperatur data fra, grupperer dataen basert på city_name, og bruker den innebygde pandas funksjonen `median()` og `std()`, for hendholdsvis median og standardavvik. Siden verdiene grupperes på city_name, blir det indeksen med medianverdi som verdi. Derfor bruker vi `.reset_index()` for å nullstille og gjøre city_name til en kolonne, som bruker til å koble de to tabellene samen, med funksjonen `merge()`." + "Det å regne ut median og standardavvik er ikke innebygd i SQL, i motsetning til gjennomsnitt, maks og min. Derfor regner vi ut disse verdiene manuelt. Vi henter temperatur data fra, grupperer dataen basert på city_name, og bruker de innebygde pandas og numpy funksjonen `median()` og `std()`, for hendholdsvis median og standardavvik. Siden verdiene grupperes på city_name, blir det indeksen med median/standardavvik som verdi. Derfor bruker vi `.reset_index()` for å nullstille og gjøre city_name til en kolonne, som bruker til å koble de to tabellene samen, med funksjonen `merge()`." ] }, { @@ -364,7 +365,7 @@ "\n", "ax3.plot(x_axis, wind_city_1, color='#008080', label=f'Wind {city_1}')\n", "ax3.plot(x_axis, wind_city_2, color='#FFA500', label=f'Wind {city_2}')\n", - "# ax3.plot(x_axis, wind_speed, color='tab:purple', linestyle='dashed', label='Wind_speed')\n", + "\n", "ax3.set_ylabel('Wind (m/s)')\n", "ax3.set_xlabel('Datetime')\n", "ax3.legend(loc='upper right')\n", @@ -400,7 +401,7 @@ "\n", "For å lese av grafen, finner man en variabel vertikalt og en horisontal variabel. Der de møtes i diagrammet er korrelasjons koeffisienten mellom disse.\n", "\n", - "Her har vi laget en korrelasjonsmatrsie for hver av stedene, slik at man kan sammeligne om et sted har sterkere eller svakere sammenhenger mellom de ulike variablene.\n", + "Her har vi laget en korrelasjonsmatrise for hver av stedene, slik at man kan sammeligne om et sted har sterkere eller svakere sammenhenger mellom de ulike variablene.\n", "\n", "Grafen lagres i mappen `../data/figures/output_fig_compare_statistic`" ] @@ -428,7 +429,7 @@ "columns_needed = ['temp.mean_celsius', 'pressure.mean', 'humidity.mean', 'wind.mean', 'clouds.mean', 'precipitation.mean']\n", "\n", "# Two horisontally plots (1 row, 2 columns), width and height of the figure\n", - "fig, axes = plt.subplots(1, 2, figsize=(14, 6)) # Adjust figsize as needed\n", + "fig, axes = plt.subplots(1, 2, figsize=(15, 8)) # Adjust figsize as needed\n", "\n", "# Loops through both cities, the enumerate make sure we get both the city and the index of the city\n", "for i, city in enumerate(cities):\n", diff --git a/notebooks/notebook_current_data.ipynb b/notebooks/notebook_current_data.ipynb index 0d1a0fb..2651552 100644 --- a/notebooks/notebook_current_data.ipynb +++ b/notebooks/notebook_current_data.ipynb @@ -52,7 +52,7 @@ "\n", "Eks. filnavn: test\n", "\n", - "Da vil filen lagres som data_**test**.json, i mappen \"../data/json/output_current/data_{filnavn}.json\"\n", + "Da vil filen lagres som data_**test**.json, i mappen `../data/json/output_current/data_{filnavn}.json`\n", "\n" ] }, @@ -106,7 +106,7 @@ "metadata": {}, "source": [ "### Rydde i data\n", - "For å gjøre det enkelre å lese dataen, normaliserer vi json-filen ved hjelp av pandas.\n", + "For å gjøre det enklere å lese dataen, normaliserer vi json-filen ved hjelp av pandas.\n", "\n", "Vi fjerner også irrellevante kolonner som:\n", "- weather: denne inneholder informasjon om været (beskrivelse, id, icon osv.)\n", diff --git a/notebooks/notebook_interactive_data.ipynb b/notebooks/notebook_interactive_data.ipynb index b96398f..42b94db 100644 --- a/notebooks/notebook_interactive_data.ipynb +++ b/notebooks/notebook_interactive_data.ipynb @@ -6,7 +6,7 @@ "source": [ "# Notebook - Interactive data\n", "\n", - "Denne notebooken henter data fra ønsket dag og sted, skriver til fil. Deretter er det en interaktiv graf hvor bruker kan endre på layout av diagrammet. Kan blant annet endre på farge, rutenett, størrelse av scatterplots og om man ønsker gjennomsnitt eller ikke. " + "Denne notebooken henter data fra ønsket dag og sted, skriver til fil. Deretter er det en interaktiv graf hvor bruker kan endre på layout av diagrammet. Kan blant annet endre på farge, rutenett, størrelse av scatterplots og om man ønsker gjennomsnitt og median eller ikke. " ] }, { @@ -135,7 +135,7 @@ "\n", "# Reads from file using pandas\n", "weather_data = pd.read_json(f'../data/json/output_interactive/data_{filename}.json')\n", - "#output_stedsnavn\n", + "\n", "from my_package.data import extract_city_df\n", "\n", "df = extract_city_df(weather_data)\n", @@ -147,7 +147,7 @@ "metadata": {}, "source": [ "### Viser temperaturen\n", - "Regner ut gjennomsnittst-temperatur ved hjelp av innebygde funksjoner. Finner også høyeste og laveste målte temperatur.\n", + "Regner ut gjennomsnittst-temperatur og median ved hjelp av innebygde funksjoner. Finner også høyeste og laveste målte temperatur.\n", "Plotter gjennomsnittstemperaturen, median temperatur og temperaturen per time for dagen valgt, ved hjelp av matplotlib.\n", "\n", "Ved hjelp av ipywidgets så er dette et interaktivt diagram som brukeren selv kan justere på ønskelige effekter ved diagrammet. Når koden først kjøres vil det komme standard layout men disse er det bare å endre, for eksempel farge og størrelse på plots. \n", @@ -203,7 +203,7 @@ " print(\"Highest temperature:\", max_temp)\n", " print(\"Lowest temperature:\", min_temp)\n", "\n", - " plt.figure(figsize=(12, 6))\n", + " plt.figure(figsize=(15, 8))\n", " plt.scatter(x_axis, temp, color=dot_color, s=dot_size, alpha=0.7, label='Temperaturmålinger')\n", "\n", " if show_mean:\n", diff --git a/notebooks/notebook_one_day_data.ipynb b/notebooks/notebook_one_day_data.ipynb index 007cd55..a9ed561 100644 --- a/notebooks/notebook_one_day_data.ipynb +++ b/notebooks/notebook_one_day_data.ipynb @@ -89,7 +89,7 @@ "source": [ "### Lagre data i en json-fil\n", "\n", - "Skriv inn navn for til filen du vil lagre med dataen.\n", + "Skriv inn navn til filen du vil lagre med dataen.\n", "\n", "Eks. filnavn: test\n", "\n", @@ -185,7 +185,7 @@ "x_axis = df.index\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(14, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Scatter plot for each temperature reading\n", "plt.scatter(x_axis, temp, color='tab:red', label='Temperaturmålinger', alpha=0.7)\n", @@ -259,7 +259,7 @@ "### Sjekk for manglende verdier\n", "Missigno sjekker og visualiserer manglende verdier, slik at det blir lettere å se hvilke kolonner feilen ligger i. \n", "\n", - "Hvis det blir \"hull\" i en søyle, tyder the på manglende verdier." + "Hvis det blir \"hull\" i en søyle, tyder det på manglende verdier." ] }, { @@ -279,13 +279,13 @@ "metadata": {}, "source": [ "### Endre manglende verdier\n", - "I de fleste tilfeller virker dataene å være tilnærmet \"perfekte\", men de inkluderer bare snø og regn dersom det er snø eller regn. Derfor vil vi fa NaN verdier i de målingene det ikke har regnet/snødd. \n", + "I de fleste tilfeller virker dataene å være tilnærmet \"perfekte\", men de inkluderer bare snø og regn dersom det er snø eller regn. Derfor vil vi ha 'NaN' verdier i de målingene det ikke har regnet/snødd. \n", "\n", - "Under sjekker vi først om regn eller snø er i målingen, og hvis de er, bytter vi ut NaN med 0. \n", + "Under fyller vi inne ønskede 'NaN' verdier med 0. \n", "\n", "Så sjekker vi om alle verdiene i en kolonne er 'NaN', isåfall så fjerner vi hele kolonnen. Grunnen til at dette ikke inkluderer snø og regn, er fordi vi senere plotter disse verdiene, og da får vi ikke feil om verdien er 0, men vil få om hele kolonnen mangler.\n", "\n", - "Deretter bruker vi interpolate dersom de skulle være NaN verdier, det er en funksjon som tar utgangspunkt i verdien før og verdien etter for å 'gjette' verdien som mangler. Vi har lagt til 'limit-direction', som gjør at den gjetter selv om man bare har en verdi på siden, som feks. første og siste verdi. " + "Deretter bruker vi interpolate dersom de skulle være 'NaN' verdier, det er en funksjon som tar utgangspunkt i verdien før og verdien etter for å 'gjette' verdien som mangler. Vi har lagt til 'limit-direction', som gjør at den gjetter selv om man bare har en verdi på siden, som feks. første og siste verdi. " ] }, { @@ -308,7 +308,7 @@ "# Interpolate other missing 'NaN'-values\n", "df = df.interpolate(method='linear', limit_direction='both')\n", "\n", - "# Display the df, now without NaN\n", + "# Display the df, now without 'NaN'\n", "display(df)" ] }, @@ -375,7 +375,7 @@ "temp_median = temp.median().round()\n", "\n", "# Two vertically stacked axis, (2 rows, 1 column), width and height of the figure, and the axis share the same x_axis\n", - "fig, (ax1, ax3) = plt.subplots(2, 1,figsize=(14, 6), sharex=True)\n", + "fig, (ax1, ax3) = plt.subplots(2, 1,figsize=(15, 8), sharex=True)\n", "\n", "# Set the title for the diagram, above the first axis, with city_name and input_date\n", "ax1.set_title(f'Weather data for {city_name} ({date}) ')\n", @@ -484,7 +484,7 @@ "corr_matrix = df_selected.corr()\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(14, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Makes a seaborn heatmat, with the values in the rectangel and 2 decimals\n", "sns.heatmap(corr_matrix, annot=True, cmap=\"coolwarm\", fmt=\".2f\")\n", @@ -504,10 +504,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Lineær regresjons og prediktiv analyse\n", + "### Regresjons og prediktiv analyse\n", "\n", - "Lager en lineær regresjon og bruker den til å finne temperaturer vi kan forvente å få samme tid, neste år.\n", - "Bruker scikit-learn biblioteket, sklearn.linear_model, LinearRegression for å få til dette." + "Lager en lineær og polynom regresjon, som predikterer variasjonen i temperatur endringer i løpet av en dag.\n", + "For å gjennomføre dette bruker vi scikit-learn biblioteket, sklearn.linear_model, LinearRegression og PolynomialRegression.\n", + "\n", + "Her henter vi temperatur og 'dt' fra dataframen 'df'. Vi lagrer de i en ny dataframe med timer, og temperatur. " ] }, { @@ -521,9 +523,13 @@ "import matplotlib.pyplot as plt\n", "from sklearn.linear_model import LinearRegression\n", "\n", + "temp = df['main.temp']\n", + "dt = df.index\n", + "hours = dt.hour\n", + "\n", "#Hours of the day (0 to 23) and temperatures\n", "data = {\n", - " 'Hour': np.arange(24), # 24 hours of the day\n", + " 'Hour': hours, # 24 hours of the day\n", " 'Temperature': temp # get the temperatures\n", "}\n", "\n", @@ -535,9 +541,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Klargjøre data til regresjonsmodellen\n", + "### Klargjøre data til lineær regresjonsmodell\n", "\n", - "Klargjør dataen, og lagrer en regresjosnmodel ved bruk av `LinearRegression()`." + "Klargjør dataen, og lagrer en linjær regresjosnmodel som skal passe mellom temperatur dataen ved bruk av `LinearRegression()`." ] }, { @@ -551,17 +557,74 @@ "y = df['Temperature'].values # Temperatures (y-axis)\n", "\n", "# Create and train the regression model\n", - "model = LinearRegression()\n", - "model.fit(X, y)" + "linear_model = LinearRegression()\n", + "linear_model.fit(X, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Trene modellen og predikerte fremtidig data\n", + "### Klargjøre data til en polynom regresjonsmodell\n", + "\n", + "For å lage en polynom regresjonsmodell. Importerer vi `make_pipeline` fra sklearn, som sørger for at vi først gir dataene mer mening som gjør det lettere for modellen å tegne en bedre linje som passer variasjonen og utviklingen av temperatur gjennom dagen.\n", "\n", - "Gir dataen inn til modellen, som predikterer verdien." + "Her kommer en kort forklaring av degree:\n", + "- 1 degree: x (lineær)\n", + "- 2 degrees: x + x^2 (polynom)\n", + "- 3 degrees: x + x^2 + x^3 (polynom)\n", + "- n degrees: x + x^2 + ... + x^n\n", + "\n", + "Degrees vil altså gi mer info til hver av dataene, og sørge for en bedre linje. Men vi kan få noe som heter 'overfitting', dette hander om at flere degrees jo bedre blir dataen, men den blir også mer skånsom for støy, heller enn å følge de faktiske trendene. Derfor velger vi å forhold oss til 2 degrees, da det vil gi en jevn linje som fortsatt viser tydelige trender." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.preprocessing import PolynomialFeatures\n", + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.pipeline import make_pipeline\n", + "\n", + "# Degree of the polynomial, 2 degrees = x + x^2\n", + "degree = 2\n", + "\n", + "# Create polynomial regression pipeline\n", + "poly_model = make_pipeline(PolynomialFeatures(degree), LinearRegression())\n", + "\n", + "# Fit the model\n", + "poly_model.fit(X, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Prediktere data\n", + "Vi gir dataen til modellen, og får den til å prediktere verdier. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Predict linear regression\n", + "predicted_temperatures_linear = linear_model.predict(X)\n", + "# Predict polynomial regression\n", + "predicted_temperatures_poly = poly_model.predict(X)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Visualisere, prediktert og faktisk data\n", + "\n", + "Vi plotter både lineær og polynom regresjonslinje, sammen med de faktiske dataene." ] }, { @@ -572,26 +635,25 @@ "source": [ "from matplotlib.dates import DateFormatter\n", "\n", + "# Stores the actuall temperature values as y\n", "y = np.array(df['Temperature'].values)\n", "\n", + "# Sets the 'dt' as x_axis\n", "x_axis = df.index\n", "\n", - "plt.figure(figsize=(14, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Plot the original data\n", "plt.scatter(x_axis, y, color='green', label='Original data', alpha=0.6)\n", "\n", - "predicted_temperatures = model.predict(X)\n", + "# Plot the regression for both linear and polynomial\n", + "plt.plot(x_axis, predicted_temperatures_linear, color='red', linestyle='dashed', label='Linear regression')\n", + "plt.plot(x_axis, predicted_temperatures_poly, color='red', label=f'Polynomial regression ({degree})')\n", "\n", - "# Plot the regression line\n", - "plt.plot(x_axis, predicted_temperatures, color='red', label='Prediktiv temperatur')\n", - "\n", - "#title for the axis\n", + "# Title for the axis\n", "plt.xlabel('Datetime')\n", "plt.ylabel('Temperature (°C)')\n", "\n", - "#ax = plt.gca()\n", - "\n", "# Customize the x-axis to show ticks for each hour\n", "plt.xticks(rotation=45)\n", "plt.gca().xaxis.set_major_formatter(DateFormatter('%H:%M'))\n", @@ -605,10 +667,41 @@ "\n", "plt.legend(loc='upper right')\n", "\n", - "plt.show()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sjekker modellen\n", + "For å sjekke hvor god modellen er, kan vi regne ut ulike verdier.\n", + "\n", + "- Koeffisienten: den viser sammenhengen mellom x og y. Og regner ut en verdi på hvor mye x endrer seg når y endres med 1.\n", + "- MSE: gjennomsnittelig kvadrerte avvik. Forteller hvor godt modellen passer til punktene, jo lavere MSE jo mindre avstand er det mellom de faktiske punktene og de predikterte punktene.\n", + "- R2 score: forteller oss hvor godt modellen passer, og har alltid en verdi mellom 0 og 1. Der 0 betyr at modellen er svak og ikke klarer å predikere den avhengige variabelen, og 1 betyr at modellen er sterk og klarer å predikere den avhengigee variabelen. Vi kan også tolke R2 scoren forskjellig for enkel og multippel regresjon.\n", + " - For enkel regresjon sier R2 hvor mye av variasjonen i den avhengige variabelen som kan forklares av den uavhengige.\n", + " - For multippel regresjon sier R2 hvor mye av variasjonen den avhengige variablene som tilsammen kan forklares av alle de uavhengige variablene." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.metrics import mean_squared_error, r2_score\n", + "\n", + "# The coefficient, how much does x change if y change one\n", + "print(\"Coefficients:\", linear_model.coef_.round(2))\n", + "\n", + "# The mean squared error, how far the predictions are on average\n", + "print(\"Mean squared error linear: {:.2f}\".format(mean_squared_error(y, predicted_temperatures_linear)))\n", + "print(\"Mean squared error polynomial: {:.2f}\".format(mean_squared_error(y, predicted_temperatures_poly)))\n", "\n", - "# Display the predicted temperatures\n", - "print(f'predicted temperatures: {predicted_temperatures}')\n" + "# The R2-score or coefficient of determination, how well the the model fits the data\n", + "print(\"R2 score linear: {:.2f}\".format(r2_score(y, predicted_temperatures_linear)))\n", + "print(\"R2 score polynomial: {:.2f}\".format(r2_score(y, predicted_temperatures_poly)))" ] } ], diff --git a/notebooks/notebook_one_week_data.ipynb b/notebooks/notebook_one_week_data.ipynb index 53838e7..2d1e1db 100644 --- a/notebooks/notebook_one_week_data.ipynb +++ b/notebooks/notebook_one_week_data.ipynb @@ -102,11 +102,11 @@ "source": [ "### Lagre data i en json-fil\n", "\n", - "Skriv inn navn for til filen du vil lagre med dataen.\n", + "Skriv inn navn til filen du vil lagre med dataen.\n", "\n", "Eks. filnavn: test\n", "\n", - "Da vil filen lagres som data_**test**.json, i mappen \"../data/json/output_one_week/data_{filnavn}.json\"" + "Da vil filen lagres som data_**test**.json, i mappen `../data/json/output_one_week/data_{filnavn}.json`" ] }, { @@ -159,12 +159,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Rensking av riktig data\n", - "Vi går inn i 'list' for å finne den relevante informasjonen, og ikke bare meta-informasjon.\n", + "### Sjekker eksitensen av kolonner\n", "\n", - "Sørger for å fjerne duplikater, og andre irelevante kolonner. Samt setter index kolonnen til tid.\n", + "Gjennom prosjektet har vi oppdaget at kolonnene som ofte mangler er 'rain.1h' og 'snow.1h'. Derfor importerer vi funksjonen `ensure_column` som tar inn dataframen og kolonnene vi vil sjekke. Dersom kolonnene ikke eksisterer blir de lagt til og fylt med 'NaN' før dataframen returneres.\n", "\n", - "Sjekker om kolonnene ['rain.1h'] eller ['snow.1h'] er tilstede, hvis ikke blir de lagd og fylt med NaN. Vi trenger denne kolonnen, selvom den er tom, for senere å plotte grafen og unngå feilmeldinger. Dette fordi vi senere sjekker manglende verdier som NaN. " + "Sjekker også for kolonnene 'wind.gust' og 'wind.speed' da de skal brukes til plotting senere." ] }, { @@ -229,7 +228,7 @@ "x_axis = df.index\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(12, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Scatter plot for each temperature reading\n", "plt.scatter(x_axis, temp, color='tab:red', label='Temperature', alpha=0.7)\n", @@ -294,13 +293,13 @@ "metadata": {}, "source": [ "### Endre manglende verdier\n", - "I de fleste tilfeller virker dataene å være tilnærmet \"perfekte\", men de inkluderer bare snø og regn dersom det er snø eller regn. Derfor vil vi fa NaN verdier i de målingene det ikke har regnet/snødd. \n", + "I de fleste tilfeller virker dataene å være tilnærmet \"perfekte\", men de inkluderer bare snø og regn dersom det er snø eller regn. Derfor vil vi ha 'NaN' verdier i de målingene det ikke har regnet/snødd. \n", "\n", - "Under sjekker vi først om regn eller snø er i målingen, og hvis de er, bytter vi ut NaN med 0. \n", + "Under fyller vi inne ønskede 'NaN' verdier med 0. \n", "\n", "Så sjekker vi om alle verdiene i en kolonne er 'NaN', isåfall så fjerner vi hele kolonnen. Grunnen til at dette ikke inkluderer snø og regn, er fordi vi senere plotter disse verdiene, og da får vi ikke feil om verdien er 0, men vil få om hele kolonnen mangler.\n", "\n", - "Deretter bruker vi interpolate dersom de skulle være NaN verdier, det er en funksjon som tar utgangspunkt i verdien før og verdien etter for å 'gjette' verdien som mangler. Vi har lagt til 'limit-direction', som gjør at den gjetter selv om man bare har en verdi på siden, som feks. første og siste verdi. " + "Deretter bruker vi interpolate dersom de skulle være 'NaN' verdier, det er en funksjon som tar utgangspunkt i verdien før og verdien etter for å 'gjette' verdien som mangler. Vi har lagt til 'limit-direction', som gjør at den gjetter selv om man bare har en verdi på siden, som feks. første og siste verdi. " ] }, { @@ -323,7 +322,7 @@ "# Interpolate other missing 'NaN'-values\n", "df = df.interpolate(method='linear', limit_direction='both')\n", "\n", - "# Display the df, now without NaN\n", + "# Display the df, now without 'NaN'\n", "display(df)" ] }, @@ -503,7 +502,7 @@ "corr_matrix = selected_df.corr()\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(14, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Makes a seaborn heatmat, with the values in the rectangel and 2 decimals\n", "sns.heatmap(corr_matrix, annot=True, cmap=\"coolwarm\", fmt=\".2f\")\n", diff --git a/notebooks/notebook_regression.ipynb b/notebooks/notebook_regression.ipynb index fbf0c38..5a31594 100644 --- a/notebooks/notebook_regression.ipynb +++ b/notebooks/notebook_regression.ipynb @@ -40,10 +40,10 @@ "from my_package.data import extract_city_df\n", "\n", "# Data for et helt år\n", - "# filepath = '../data/test/merged_data_2024_mai_2025.json'\n", + "filepath = '../data/test/merged_data_2024_mai_2025.json'\n", "\n", "# Data for april måned 2025\n", - "filepath = '../data/test/merged_data_april.json'\n", + "# filepath = '../data/test/merged_data_april.json'\n", "\n", "# Reads from file using pandas\n", "weather_data = pd.read_json(filepath)\n", @@ -106,7 +106,8 @@ "source": [ "### Definere variabler til regresjon\n", "\n", - "Her definerer vi målvariable, og hvilke variabler som det skal sjekkes sammenheng mellom for å prediktere målvariabelen som i dette tilfellet er temperatur." + "Her definerer vi den avhengige og de uavhengige variablene, altså den avhengige variabelen er den vi ønsker å forutsi basert på de uavhengige. \n", + "I dette tilfellet er den avhengige variabelen temperatur, og vil se hvordan de uavhengige variablene luftfuktighet, skyer, regn og snø påvirker temperaturen." ] }, { @@ -116,10 +117,10 @@ "metadata": {}, "outputs": [], "source": [ - "# Variables to see context and affect and wanted variabel\n", - "X = df[['main.humidity', 'wind.speed', 'main.pressure', 'wind.gust', 'clouds.all', 'rain.1h', 'snow.1h']]\n", + "# Independent variables to see context and affect on the depentend variable\n", + "X = df[['main.humidity', 'clouds.all', 'rain.1h', 'snow.1h']]\n", "\n", - "# Wanted variabel\n", + "# Depentend variable\n", "y = df['main.temp']" ] }, @@ -141,10 +142,29 @@ "outputs": [], "source": [ "from sklearn.model_selection import train_test_split\n", - "from sklearn.linear_model import LinearRegression\n", "\n", "# Split data to train and test, test-size 0.2, random-state 42, normal value\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n", + "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)" + ] + }, + { + "cell_type": "markdown", + "id": "b78c195d", + "metadata": {}, + "source": [ + "### Klargjøre data til lineær regresjonsmodell\n", + "\n", + "Klargjør dataen, og lagrer en linjær regresjosnmodel som skal prøve å finne sammenhengen mellom treningssettet." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66e33e6b", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.linear_model import LinearRegression\n", "\n", "# Make a linear regression model\n", "model = LinearRegression()\n", @@ -153,19 +173,61 @@ "model.fit(X_train, y_train)" ] }, + { + "cell_type": "markdown", + "id": "b9acea20", + "metadata": {}, + "source": [ + "### Klargjøre data til en polynom regresjonsmodell\n", + "\n", + "For å lage en polynom regresjonsmodell. Importerer vi `make_pipeline` fra sklearn, som sørger for at vi først gir dataene mer mening som gjør det lettere for modellen å finne en bedre sammenheng mellom de uavhengige og den avhengige variabelen.\n", + "\n", + "Her kommer en kort forklaring av degree:\n", + "- 1 degree: x (lineær)\n", + "- 2 degrees: x + x^2 (polynom)\n", + "- 3 degrees: x + x^2 + x^3 (polynom)\n", + "- n degrees: x + x^2 + ... + x^n\n", + "\n", + "Degrees vil altså gi mer info til hver av dataene, og sørge for en bedre linje. Men vi kan få noe som heter 'overfitting', dette hander om at flere degrees jo bedre blir dataen, men den blir også mer skånsom for støy, heller enn å følge de faktiske trendene. Derfor velger vi å forhold oss til 2 degrees, da det vil gi en jevn linje som fortsatt viser tydelige trender." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3a7ec146", + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.preprocessing import PolynomialFeatures\n", + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.pipeline import make_pipeline\n", + "\n", + "# Degree of the polynomial, 2 degrees = x + x^2\n", + "degree = 2\n", + "\n", + "# Create polynomial regression pipeline\n", + "poly_model = make_pipeline(PolynomialFeatures(degree), LinearRegression())\n", + "\n", + "# Fit the model\n", + "poly_model.fit(X_train, y_train)" + ] + }, { "cell_type": "markdown", "id": "d10f1a7b", "metadata": {}, "source": [ - "### Prediksjon\n", + "### Prediksjon og sjekk av modellens styrke\n", "\n", "Denne cellen kjører test dataen gjennom den opptrente modellen for å prediktere data.\n", "\n", - "Viser også ulike variabler som forteller oss hvor god modellen vår er:\n", - "- Coefficients: viser hvor mye de ulike variablene påvirker målvariabelen.\n", - "- Mean squared error(MSE): hvor langt unna er modellen virkeligheten.\n", - "- R2 score: overordnet hvor god modellen er." + "For å sjekke hvor god modellen er, kan vi regne ut ulike verdier.\n", + "\n", + "- Koeffisienten: den viser sammenhengen mellom x og y. Og regner ut en verdi på hvor mye x endrer seg når y endres med 1. Verdien regnes for hver enkelt av de uavhengige variablene, for å se hvor mye hver og en påvirker den avhengige variabelen.\n", + "- MSE: gjennomsnittelig kvadrerte avvik. Forteller hvor godt modellen passer til punktene, jo lavere MSE jo mindre avstand er det mellom de faktiske punktene og de predikterte punktene.\n", + "- R2 score: forteller oss hvor godt modellen passer, og har alltid en verdi mellom 0 og 1. Der 0 betyr at modellen er svak og ikke klarer å predikere den avhengige variabelen, og 1 betyr at modellen er sterk og klarer å predikere den avhengigee variabelen. Vi kan også tolke R2 scoren forskjellig for enkel og multippel regresjon.\n", + " - For enkel regresjon sier R2 hvor mye av variasjonen i den avhengige variabelen som kan forklares av den uavhengige.\n", + " - For multippel regresjon sier R2 hvor mye av variasjonen den avhengige variablene som tilsammen kan forklares av alle de uavhengige variablene." ] }, { @@ -179,21 +241,18 @@ "\n", "# Predicts values based on the trained model with the test, the last 20%\n", "predictions = model.predict(X_test)\n", - "\n", - "# Values predicted from the model\n", - "print(\"Predicted values:\", predictions)\n", - "\n", - "# Just to get space between\n", - "print()\n", + "poly_predictions = poly_model.predict(X_test)\n", "\n", "# The coefficient, the value of each input\n", "print(\"Coefficients:\", model.coef_)\n", "\n", "# The mean squared error, how far the predictions are on average\n", - "print(\"Mean squared error: {:.2f}\".format(mean_squared_error(y_test, predictions)))\n", + "print(\"Mean squared error linear: {:.2f}\".format(mean_squared_error(y_test, predictions)))\n", + "print(\"Mean squared error polynomial: {:.2f}\".format(mean_squared_error(y_test, poly_predictions)))\n", "\n", "# The R2-score or coefficient of determination, how well the the model fits the data\n", - "print(\"R2 score: {:.2f}\".format(r2_score(y_test, predictions)))" + "print(\"R2 score linear: {:.2f}\".format(r2_score(y_test, predictions)))\n", + "print(\"R2 score polynomial: {:.2f}\".format(r2_score(y_test, poly_predictions)))" ] }, { @@ -201,9 +260,9 @@ "id": "eec0bdd1", "metadata": {}, "source": [ - "### Plot av prediktert og faktisk data\n", + "### Plot av prediktert og faktisk data - lineær regresjon\n", "\n", - "Her plottes den predikterte dataen mot den faktiske dataen. I de fleste tilfeller kan vi se at den predikterte dataen følger store deler av den faktiske. " + "Her lager vi et scatter diagram, hvor vi plotter den faktiske og de predikterte verdiene fra den lineære regresjonsmodellen." ] }, { @@ -216,13 +275,14 @@ "import matplotlib.pyplot as plt\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(12, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", - "# Plot the actual data from the test\n", - "plt.plot(y_test.values, label='Actual', color='green', alpha=0.6)\n", + "# Create an index for the x-axis (just sample numbers)\n", + "x = range(len(y_test))\n", "\n", - "# Plot the predicted data\n", - "plt.plot(predictions, label='Predicted', color='red')\n", + "# Scatter both actual and predicted temeperatures\n", + "plt.scatter(x, y_test, label='Actual', color='green', alpha=0.6)\n", + "plt.scatter(x, predictions, label='Predicted', color='red', alpha=0.6)\n", "\n", "# Show legend\n", "plt.legend(loc='upper right')\n", @@ -240,6 +300,116 @@ "plt.show()" ] }, + { + "cell_type": "markdown", + "id": "0461cd92", + "metadata": {}, + "source": [ + "### Plot av prediktert og faktisk data - polynom regresjon\n", + "\n", + "Her lager vi et scatter diagram, hvor vi plotter den faktiske og de predikterte verdiene fra den polynome regresjonsmodellen." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84d5071d", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "# Choose the width and height of the plot\n", + "plt.figure(figsize=(15, 8))\n", + "\n", + "# Create an index for the x-axis (just sample numbers)\n", + "x = range(len(y_test))\n", + "\n", + "plt.scatter(x, y_test, label='Actual', color='green', alpha=0.6)\n", + "plt.scatter(x, poly_predictions, label='Predicted', color='red', alpha=0.6)\n", + "\n", + "# Show legend\n", + "plt.legend(loc='upper right')\n", + "\n", + "# Add title for the plot\n", + "plt.title('Weather Prediction')\n", + "\n", + "# Add label for the x-axis\n", + "plt.xlabel('Sample')\n", + "\n", + "# Add label for the y-axis\n", + "plt.ylabel('Temperature')\n", + "\n", + "# Show the plot\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "b7037ab8", + "metadata": {}, + "source": [ + "### Plotter data for tid - lineær regresjon\n", + "\n", + "Ettersom vi har tilgang på tidsstempelet til testsettet kan vi tilpasse x aksen, slik at den viser tiden." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd2dcbcb", + "metadata": {}, + "outputs": [], + "source": [ + "# Restore datetime index to test set (if available)\n", + "datetime_index = y_test.index # Assuming it kept the datetime index\n", + "\n", + "plt.figure(figsize=(15, 8))\n", + "plt.scatter(datetime_index, y_test, label='Actual', color='green', alpha=0.5)\n", + "plt.scatter(datetime_index, predictions, label='Predicted', color='red', alpha=0.3)\n", + "\n", + "plt.xlabel('Datetime')\n", + "plt.ylabel('Temperature')\n", + "plt.title('Actual vs Predicted Temperatures')\n", + "plt.legend()\n", + "plt.xticks(rotation=45)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "e3ffb6ef", + "metadata": {}, + "source": [ + "### Plotter data for tid - polynom regresjon\n", + "\n", + "Ettersom vi har tilgang på tidsstempelet til testsettet kan vi tilpasse x aksen, slik at den viser tiden." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc4e1cad", + "metadata": {}, + "outputs": [], + "source": [ + "# Restore datetime index to test set (if available)\n", + "datetime_index = y_test.index # Assuming it kept the datetime index\n", + "\n", + "plt.figure(figsize=(15, 8))\n", + "plt.scatter(datetime_index, y_test, label='Actual', color='green', alpha=0.5)\n", + "plt.scatter(datetime_index, poly_predictions, label='Predicted', color='red', alpha=0.3)\n", + "\n", + "plt.xlabel('Datetime')\n", + "plt.ylabel('Temperature')\n", + "plt.title('Actual vs Predicted Temperatures')\n", + "plt.legend()\n", + "plt.xticks(rotation=45)\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, { "cell_type": "markdown", "id": "e0753a0b", @@ -261,15 +431,18 @@ "\n", "# Input for the different variables\n", "humidity = float(input(\"Enter humidity (%): \"))\n", - "wind_speed = float(input(\"Enter wind speed (km/h): \"))\n", - "pressure = float(input(\"Enter pressure (hPa): \"))\n", - "wind_gust = float(input(\"Enter wind gust (km/h): \"))\n", "clouds = float(input(\"Enter cloud coverage (%): \"))\n", "rain = float(input(\"Enter rain (mm): \"))\n", "snow = float(input(\"Enter snow (mm): \"))\n", "\n", + "# Prints input values\n", + "print(f'Humidity: {humidity}%')\n", + "print(f'Cloud coverage: {clouds}%')\n", + "print(f'Rain: {rain}mm')\n", + "print(f'Snow: {snow}mm')\n", + "\n", "# Stores all the inputed data in an array\n", - "new_data = np.array([[humidity, wind_speed, pressure, wind_gust, clouds, rain, snow]])\n", + "new_data = np.array([[humidity, clouds, rain, snow]])\n", "\n", "# Use the model, with the new data\n", "predicted_temp = model.predict(new_data)\n", diff --git a/notebooks/notebook_statistic_data.ipynb b/notebooks/notebook_statistic_data.ipynb index 20abaf2..04798e4 100644 --- a/notebooks/notebook_statistic_data.ipynb +++ b/notebooks/notebook_statistic_data.ipynb @@ -49,7 +49,7 @@ "source": [ "### Lagre data i json-fil\n", "\n", - "Skriv inn navn for til filen du vil lagre med dataen.\n", + "Skriv inn navn til filen du vil lagre med dataen.\n", "\n", "Eks. filnavn: test\n", "\n", @@ -123,9 +123,9 @@ "metadata": {}, "source": [ "### Rydder i data\n", - "Fjerner alle kolonner vi ikke trenger, som standardavvik for alle kategorier for alle dager, vi kan regne ut en felles ved å bruke statistisc modulen. \n", + "Fjerner alle kolonner vi ikke trenger, som standardavvik for alle kategorier for alle dager, vi kan regne ut en felles ved å bruke den innebygde numpy funksjonen `.std()`.\n", "\n", - "Ettersom alle kateogirene har lik data, ogg vi vil fjerne noen av verdiene fra alle kategoriene. Kan vi bruke filter funksjonen til å filtrere ut dataene som inneholder f.eks. '.st_dev'. Dette gjør at alle kategoirene fjernes på likt å vi slipper å skrive alle flere ganger." + "Ettersom alle kategorier har lik data, og vi vil fjerne noen av verdiene fra alle kategoriene. Derfor importerer vi en funksjon vi har lagd, `clean_df` som fjerner alle disse kolonne med et filter på kategoriens slutt." ] }, { @@ -206,8 +206,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Plotter data\n", - "Her plottes temperatur og regn på samme akse, med vind i en egen graf under, men de deler samme x-akse, som er month_date.\n", + "### Visualisere data i en graf\n", + "Ved hjelp av Matplotlib har vi visualiert ønsket data, og ved hjelp av subplot, en modul i matplotlib, kan vi plotte flere verdier i samme graf, og få \"to y-akse\" på samme x-akse. \n", + "\n", + "Temperatur og nedbør får plass i samme graf, hvor man leser temperatur verdiene på venstre side, og nedbørsverdiene på høyre side.\n", + "\n", + "I grafen under, men på samme x-akse, finner vi informasjon om vind, både vindhastighet og vindkast.\n", "\n", "Grafen lagres i mappen `../data/figures/output_fig_statistic`" ] @@ -322,7 +326,7 @@ "corr_matrix = df_selected.corr()\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(14, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Makes a seaborn heatmat, with the values in the rectangel and 2 decimals\n", "sns.heatmap(corr_matrix, annot=True, cmap=\"coolwarm\", fmt=\".2f\")\n", @@ -386,7 +390,7 @@ "x_axis = df['month_day']\n", "\n", "# Defines the height and width of the figure\n", - "plt.figure(figsize=(12, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Plots the temperatur\n", "plt.plot(x_axis, temp_mean, color='tab:gray', label='Mean temperatur')\n", @@ -421,7 +425,9 @@ "metadata": {}, "source": [ "### Sjekker uteliggere\n", - "Denne koden sjekker om det er noen uteliggere i de ulike temperatur grafene, altså om noen verdier ligger mer enn 3 standardavvik i fra gjennomsnittet." + "Denne koden sjekker om det er noen uteliggere i de ulike temperatur grafene, altså om noen verdier ligger mer enn 3 standardavvik i fra gjennomsnittet.\n", + "\n", + "Vi har brukt pandas mask, for å kunne skille mellom de ulike årstidene. Da temperaturen kan variere veldig mellom sommer og vinter. Så sjekker vi for uteligger i alle sesongene. Om det finnes uteliggere vil verdier gjøres til 'NaN', før vi bruker interpolate for å få en jevn overgang mellom de nå, manglende verdiene." ] }, { @@ -461,7 +467,7 @@ " The function then calculates both the mean and standard deviation based on the temp. Before calculating the upper and\n", " lower limit with 3 standard deviation away from the mean. Then it uses these values to find the outliers, which is \n", " either 3 standarddeviation above or below the mean. This is based on the seasons, so for each season, it find the outliers.\n", - " The outliers are then given the nan value, before using interpolate to 'guess' the missing value. Then the outliers are dealt with. \n", + " The outliers are then given the 'NaN' value, before using interpolate to 'guess' the missing value. Then the outliers are dealt with. \n", " '''\n", "\n", " # Finds the temperature in the dataframe according to the inputed value\n", @@ -502,7 +508,7 @@ " print(season_name)\n", " print(outliers)\n", "\n", - " # Replace with NaN\n", + " # Replace with 'NaN'\n", " df.loc[outlier_index, temp_column] = np.nan\n", "\n", " # Interpolate other missing 'NaN'-values\n", @@ -541,7 +547,7 @@ "temp_record_min = df['temp.record_min_celsius']\n", "\n", "# Plot the updated temperature data\n", - "plt.figure(figsize=(12, 6))\n", + "plt.figure(figsize=(15, 8))\n", "\n", "# Plot mean, max, and min temperatures\n", "plt.plot(temp_mean.index, temp_mean, color='tab:gray', label='Mean Temperature')\n", @@ -654,9 +660,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Definere variabler til regresjon\n", + "### Regresjons og prediktiv analyse\n", + "\n", + "Lager en lineær og polynom regresjon, som predikterer variasjonen i temperatur endringer i løpet av et år.\n", + "For å gjennomføre dette bruker vi scikit-learn biblioteket, sklearn.linear_model, LinearRegression og PolynomialRegression.\n", "\n", - "Her definerer vi målvariable, og hvilke variabler som det skal sjekkes sammenheng mellom for å prediktere målvariabelen som i dette tilfellet er temperatur." + "Klargjør dataen, og lagrer en linjær regresjosnmodel som skal passe mellom temperatur dataen ved bruk av `LinearRegression()`." ] }, { @@ -665,20 +674,36 @@ "metadata": {}, "outputs": [], "source": [ - "# Variables to see context and affect and wanted variabel\n", - "X = df[['humidity.mean','wind.mean', 'pressure.mean', 'precipitation.mean', 'clouds.mean']]\n", + "from sklearn.linear_model import LinearRegression\n", + "\n", + "# Day of the year\n", + "X = df['index'].values.reshape(-1, 1)\n", "\n", "# Wanted variabel\n", - "y = df['temp.mean_celsius']" + "y = df['temp.mean_celsius']\n", + "\n", + "# Make a linear regression model\n", + "model = LinearRegression()\n", + "\n", + "# Gives the model the train data\n", + "model.fit(X, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Splitte og trene model\n", + "### Klargjøre data til en polynom regresjonsmodell\n", + "\n", + "For å lage en polynom regresjonsmodell. Importerer vi `make_pipeline` fra sklearn, som sørger for at vi først gir dataene mer mening som gjør det lettere for modellen å finne en bedre sammenheng mellom de uavhengige og den avhengige variabelen.\n", "\n", - "Vi splitter dataen inn i train og test, hvor test-size er 0.2, det vil si at 80% av dataen går til trening av modellen, mens 20% går til testingen." + "Her kommer en kort forklaring av degree:\n", + "- 1 degree: x (lineær)\n", + "- 2 degrees: x + x^2 (polynom)\n", + "- 3 degrees: x + x^2 + x^3 (polynom)\n", + "- n degrees: x + x^2 + ... + x^n\n", + "\n", + "Degrees vil altså gi mer info til hver av dataene, og sørge for en bedre linje. Men vi kan få noe som heter 'overfitting', dette hander om at flere degrees jo bedre blir dataen, men den blir også mer skånsom for støy, heller enn å følge de faktiske trendene. I dette tilfellet hvor vi antar at temperaturen vil ha flere topp-punkt og bunn-punkt velger vi 4 degrees." ] }, { @@ -687,31 +712,26 @@ "metadata": {}, "outputs": [], "source": [ - "from sklearn.model_selection import train_test_split\n", + "from sklearn.preprocessing import PolynomialFeatures\n", "from sklearn.linear_model import LinearRegression\n", + "from sklearn.pipeline import make_pipeline\n", "\n", - "# Split data to train and test, test-size 0.2, random-state 42, normal value\n", - "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)\n", + "# Degree of the polynomial, 4 degrees = x + x^2 + x^3 + x^4\n", + "degree = 4\n", "\n", - "# Make a linear regression model\n", - "model = LinearRegression()\n", + "# Create polynomial regression pipeline\n", + "poly_model = make_pipeline(PolynomialFeatures(degree), LinearRegression())\n", "\n", - "# Gives the model the train data\n", - "model.fit(X_train, y_train)" + "# Fit the model\n", + "poly_model.fit(X, y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Prediksjon\n", - "\n", - "Denne cellen kjører test dataen gjennom den opptrente modellen for å prediktere data.\n", - "\n", - "Viser også ulike variabler som forteller oss hvor god modellen vår er:\n", - "- Coefficients: viser vhvor mye de ulike variablene påvirker målvariabelen.\n", - "- Mean squared error(MSE): hvor langt unna er modellen virkeligheten.\n", - "- R2 score: overordnet hvor god modellen er." + "### Prediktere data\n", + "Vi gir dataen til modellen, og får den til å prediktere verdier. " ] }, { @@ -720,34 +740,19 @@ "metadata": {}, "outputs": [], "source": [ - "from sklearn.metrics import mean_squared_error, r2_score\n", - "\n", - "# Predicts values based on the trained model with the test, the last 20%\n", - "predictions = model.predict(X_test)\n", - "\n", - "# Values predicted from the model\n", - "print(\"Predicted values:\", predictions)\n", - "\n", - "# Just to get space between\n", - "print()\n", - "\n", - "# The coefficient, the value of each input\n", - "print(\"Coefficients:\", model.coef_)\n", - "\n", - "# The mean squared error, how far the predictions are on average\n", - "print(\"Mean squared error: {:.2f}\".format(mean_squared_error(y_test, predictions)))\n", - "\n", - "# The R2-score or coefficient of determination, how well the the model fits the data\n", - "print(\"R2 score: {:.2f}\".format(r2_score(y_test, predictions)))" + "# Predict linear regression\n", + "predictions = model.predict(X)\n", + "# Predict polynomial regression\n", + "poly_predictions = poly_model.predict(X)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Plot av prediktert og faktisk data\n", + "### Visualisere, prediktert og faktisk data\n", "\n", - "Her plottes den predikterte dataen mot den faktiske dataen. I de fleste tilfeller kan vi se at den predikterte dataen følger store deler av den faktiske. " + "Vi plotter både lineær og polynom regresjonslinje, sammen med de faktiske dataene." ] }, { @@ -759,13 +764,19 @@ "import matplotlib.pyplot as plt\n", "\n", "# Choose the width and height of the plot\n", - "plt.figure(figsize=(12, 6))\n", + "plt.figure(figsize=(15, 8))\n", + "\n", + "# Customize the x-axis to show ticks and labels only at the start of each month\n", + "plt.gca().xaxis.set_major_locator(mdates.MonthLocator())\n", + "# Format ticks to show abbreviated month names (e.g., Jan, Feb)\n", + "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b')) \n", "\n", "# Plot the actual data from the test\n", - "plt.plot(y_test.values, label='Actual', color='green', alpha=0.6)\n", + "plt.plot(x_axis, y.values, label='Actual', color='green', alpha=0.6)\n", "\n", - "# Plot the predicted data\n", - "plt.plot(predictions, label='Predicted', color='red')\n", + "# Plot the predicted data, both linear and polynomial\n", + "plt.plot(x_axis, predictions, label='linear regression', color='red')\n", + "plt.plot(poly_predictions, label=f'polynomial regression ({degree})', color='red')\n", "\n", "# Show legend\n", "plt.legend(loc='upper right')\n", @@ -779,9 +790,46 @@ "# Add label for the y-axis\n", "plt.ylabel('Temperature')\n", "\n", + "# Show grid\n", + "plt.grid()\n", + "\n", "# Show the plot\n", "plt.show()" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sjekker modellen\n", + "For å sjekke hvor god modellen er, kan vi regne ut ulike verdier.\n", + "\n", + "- Koeffisienten: den viser sammenhengen mellom x og y. Og regner ut en verdi på hvor mye x endrer seg når y endres med 1.\n", + "- MSE: gjennomsnittelig kvadrerte avvik. Forteller hvor godt modellen passer til punktene, jo lavere MSE jo mindre avstand er det mellom de faktiske punktene og de predikterte punktene.\n", + "- R2 score: forteller oss hvor godt modellen passer, og har alltid en verdi mellom 0 og 1. Der 0 betyr at modellen er svak og ikke klarer å predikere den avhengige variabelen, og 1 betyr at modellen er sterk og klarer å predikere den avhengigee variabelen. Vi kan også tolke R2 scoren forskjellig for enkel og multippel regresjon.\n", + " - For enkel regresjon sier R2 hvor mye av variasjonen i den avhengige variabelen som kan forklares av den uavhengige.\n", + " - For multippel regresjon sier R2 hvor mye av variasjonen den avhengige variablene som tilsammen kan forklares av alle de uavhengige variablene." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.metrics import mean_squared_error, r2_score\n", + "\n", + "# The coefficient, the value of each input\n", + "print(\"Coefficients:\", model.coef_)\n", + "\n", + "# The mean squared error, how far the predictions are on average\n", + "print(\"Mean squared error linear: {:.2f}\".format(mean_squared_error(y, predictions)))\n", + "print(\"Mean squared error polynomial: {:.2f}\".format(mean_squared_error(y, poly_predictions)))\n", + "\n", + "# The R2-score or coefficient of determination, how well the the model fits the data\n", + "print(\"R2 score linear: {:.2f}\".format(r2_score(y, predictions)))\n", + "print(\"R2 score polynomial: {:.2f}\".format(r2_score(y, poly_predictions)))" + ] } ], "metadata": { diff --git a/src/my_package/util.py b/src/my_package/util.py index ea83dc5..d3d86fe 100644 --- a/src/my_package/util.py +++ b/src/my_package/util.py @@ -42,24 +42,24 @@ def kelvin_to_celsius(temp_in_kelvin): temp_in_celsius = temp_in_kelvin - 273.15 return temp_in_celsius -# Ensure wqnted columns, fill with "NaN" if they dont exsist +# Ensure wqnted columns, fill with 'NaN' if they dont exsist def ensure_column(df, columns): ''' This function is taking in the parametre df and columns. It will then check if the columns are in the df. If the columns are not present, it will print a statement saying it is not present, before adding the columns - and fill in the value NaN. + and fill in the value 'NaN'. ''' for col in columns: if col not in df.columns: - print(f"'{col}' is not present in the DataFrame. Filling with NaN.") + print(f"'{col}' is not present in the DataFrame. Filling with 'NaN'.") df[col] = np.nan return df -# Fill "NaN" in wanted columns with 0 +# Fill 'NaN' in wanted columns with 0 def fill_column_0(df, columns): ''' - This function is taking in the parameters df and columns. It will then check if the columns include any NaN + This function is taking in the parameters df and columns. It will then check if the columns include any 'NaN' values and fill these with 0. ''' diff --git a/tests/unit/test_clean_data.py b/tests/unit/test_clean_data.py index dbed895..e200c37 100644 --- a/tests/unit/test_clean_data.py +++ b/tests/unit/test_clean_data.py @@ -39,12 +39,12 @@ def test_ensure_column(self): # Check if the 'rain.1h' column is present after function call self.assertTrue('rain.1h' in df.columns) self.assertTrue('snow.1h' in df.columns) - # Check if the column has NaN values + # Check if the column has 'NaN' values self.assertTrue(df['rain.1h'].isna().all()) self.assertTrue(df['snow.1h'].isna().all()) - # Test if NaN values in 'rain.1h' are filled with 0 + # Test if 'NaN' values in 'rain.1h' are filled with 0 def test_fill_rain_column(self): df = pd.DataFrame({ 'temp': [300, 302, 305], @@ -56,7 +56,7 @@ def test_fill_rain_column(self): df = fill_column_0(df, columns_to_fill) - # Check if NaN values are replaced with 0 + # Check if 'NaN' values are replaced with 0 self.assertEqual(df['rain.1h'].iloc[0], 0) self.assertEqual(df['rain.1h'].iloc[2], 0) self.assertEqual(df['snow.1h'].iloc[0], 0)