You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Data-Science-For-Beginners/translations/no/1-Introduction/04-stats-and-probability/notebook.ipynb

581 lines
18 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Introduksjon til sannsynlighet og statistikk\n",
"I denne notatboken skal vi leke med noen av begrepene vi tidligere har diskutert. Mange begreper fra sannsynlighet og statistikk er godt representert i store biblioteker for databehandling i Python, som `numpy` og `pandas`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import random\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tilfeldige variable og fordelinger\n",
"La oss begynne med å trekke et utvalg på 30 verdier fra en uniform fordeling fra 0 til 9. Vi vil også beregne gjennomsnitt og varians.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sample = [ random.randint(0,10) for _ in range(30) ]\n",
"print(f\"Sample: {sample}\")\n",
"print(f\"Mean = {np.mean(sample)}\")\n",
"print(f\"Variance = {np.var(sample)}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"For å visuelt anslå hvor mange forskjellige verdier det er i prøven, kan vi plotte **histogrammet**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.hist(sample)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Analyserer ekte data\n",
"\n",
"Gjennomsnitt og varians er veldig viktige når man analyserer virkelige data. La oss laste inn data om baseballspillere fra [SOCR MLB Height/Weight Data](http://wiki.stat.ucla.edu/socr/index.php/SOCR_Data_MLB_HeightsWeights)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv(\"../../data/SOCR_MLB.tsv\",sep='\\t', header=None, names=['Name','Team','Role','Weight','Height','Age'])\n",
"df\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Vi bruker en pakke kalt [**Pandas**](https://pandas.pydata.org/) her for dataanalyse. Vi vil snakke mer om Pandas og å jobbe med data i Python senere i dette kurset.\n",
"\n",
"La oss beregne gjennomsnittsverdier for alder, høyde og vekt:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[['Age','Height','Weight']].mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La oss nå fokusere på høyde, og beregne standardavvik og varians:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(list(df['Height'])[:20])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mean = df['Height'].mean()\n",
"var = df['Height'].var()\n",
"std = df['Height'].std()\n",
"print(f\"Mean = {mean}\\nVariance = {var}\\nStandard Deviation = {std}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I tillegg til gjennomsnittet gir det mening å se på medianverdien og kvartilene. De kan visualiseres ved hjelp av en **boksplott**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,2))\n",
"plt.boxplot(df['Height'].ffill(), vert=False, showmeans=True)\n",
"plt.grid(color='gray', linestyle='dotted')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vi kan også lage boksdiagrammer av delmengder av datasettet vårt, for eksempel gruppert etter spillerrolle.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.boxplot(column='Height', by='Role', figsize=(10,8))\n",
"plt.xticks(rotation='vertical')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> **Merk**: Dette diagrammet antyder at gjennomsnittlig høyde for førstebaser er høyere enn høyden til andrebaser. Senere skal vi lære hvordan vi kan teste denne hypotesen mer formelt, og hvordan vi kan vise at dataene våre er statistisk signifikante for å påvise dette. \n",
"\n",
"Alder, høyde og vekt er alle kontinuerlige stokastiske variabler. Hva tror du fordelingen deres er? En god måte å finne det ut på er å tegne histogrammet av verdiene: \n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df['Weight'].hist(bins=15, figsize=(10,6))\n",
"plt.suptitle('Weight distribution of MLB Players')\n",
"plt.xlabel('Weight')\n",
"plt.ylabel('Count')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Normalfordeling\n",
"\n",
"La oss lage et kunstig utvalg av vekter som følger en normalfordeling med samme gjennomsnitt og varians som våre virkelige data:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generated = np.random.normal(mean, std, 1000)\n",
"generated[:20]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.hist(generated, bins=15)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.hist(np.random.normal(0,1,50000), bins=300)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Siden de fleste verdier i det virkelige liv er normalfordelte, bør vi ikke bruke en uniform tilfeldig tallgenerator til å generere prøve-data. Her er hva som skjer hvis vi prøver å generere vekter med en uniform fordeling (generert av `np.random.rand`):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"wrong_sample = np.random.rand(1000)*2*std+mean-std\n",
"plt.figure(figsize=(10,6))\n",
"plt.hist(wrong_sample)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Konfidensintervaller\n",
"\n",
"La oss nå beregne konfidensintervaller for vektene og høydene til baseballspillere. Vi vil bruke koden [fra denne stackoverflow-diskusjonen](https://stackoverflow.com/questions/15033511/compute-a-confidence-interval-from-sample-data):\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import scipy.stats\n",
"\n",
"def mean_confidence_interval(data, confidence=0.95):\n",
" a = 1.0 * np.array(data)\n",
" n = len(a)\n",
" m, se = np.mean(a), scipy.stats.sem(a)\n",
" h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)\n",
" return m, h\n",
"\n",
"for p in [0.85, 0.9, 0.95]:\n",
" m, h = mean_confidence_interval(df['Weight'].fillna(method='pad'),p)\n",
" print(f\"p={p:.2f}, mean = {m:.2f} ± {h:.2f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Hypotesetesting\n",
"\n",
"La oss utforske forskjellige roller i vårt baseballspiller-datasett:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df.groupby('Role').agg({ 'Weight' : 'mean', 'Height' : 'mean', 'Age' : 'count'}).rename(columns={ 'Age' : 'Count'})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La oss teste hypotesen om at førstebaser er høyere enn andrebaser. Den enkleste måten å gjøre dette på er å teste konfidensintervallene:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for p in [0.85,0.9,0.95]:\n",
" m1, h1 = mean_confidence_interval(df.loc[df['Role']=='First_Baseman',['Height']],p)\n",
" m2, h2 = mean_confidence_interval(df.loc[df['Role']=='Second_Baseman',['Height']],p)\n",
" print(f'Conf={p:.2f}, 1st basemen height: {m1-h1[0]:.2f}..{m1+h1[0]:.2f}, 2nd basemen height: {m2-h2[0]:.2f}..{m2+h2[0]:.2f}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vi kan se at intervallene ikke overlapper.\n",
"\n",
"En statistisk mer korrekt måte å bevise hypotesen på er å bruke en **Student t-test**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from scipy.stats import ttest_ind\n",
"\n",
"tval, pval = ttest_ind(df.loc[df['Role']=='First_Baseman',['Height']], df.loc[df['Role']=='Second_Baseman',['Height']],equal_var=False)\n",
"print(f\"T-value = {tval[0]:.2f}\\nP-value: {pval[0]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"De to verdiene som returneres av `ttest_ind`-funksjonen er:\n",
"* p-verdien kan betraktes som sannsynligheten for at to fordelinger har samme gjennomsnitt. I vårt tilfelle er den veldig lav, noe som betyr at det er sterkt bevis som understøtter at førstebaserne er høyere.\n",
"* t-verdien er den mellomliggende verdien av normalisert gjennomsnittsforskjell som brukes i t-testen, og den blir sammenlignet med en terskelverdi for en gitt konfidensverdi.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simulering av en normalfordeling med sentralgrenseteoremet\n",
"\n",
"Den pseudo-tilfeldige generatoren i Python er designet for å gi oss en jevn fordeling. Hvis vi ønsker å lage en generator for normalfordeling, kan vi bruke sentralgrenseteoremet. For å få en normalt fordelt verdi vil vi bare beregne gjennomsnittet av et utvalg som er generert jevnt.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def normal_random(sample_size=100):\n",
" sample = [random.uniform(0,1) for _ in range(sample_size) ]\n",
" return sum(sample)/sample_size\n",
"\n",
"sample = [normal_random() for _ in range(100)]\n",
"plt.figure(figsize=(10,6))\n",
"plt.hist(sample)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Korrelasjon og Evil Baseball Corp\n",
"\n",
"Korrelasjon gjør det mulig for oss å finne relasjoner mellom dataserier. I vårt lekeksempel later vi som om det finnes et ondsinnet baseball-selskap som betaler spillerne sine etter høyden deres jo høyere spilleren er, desto mer penger får han/hun. Anta at det er en grunnlønn på $1000, og en ekstra bonus fra $0 til $100, avhengig av høyde. Vi vil ta de ekte spillerne fra MLB, og beregne deres tenkte lønninger:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"heights = df['Height'].fillna(method='pad')\n",
"salaries = 1000+(heights-heights.min())/(heights.max()-heights.mean())*100\n",
"print(list(zip(heights, salaries))[:10])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La oss nå beregne kovarians og korrelasjon for disse sekvensene. `np.cov` vil gi oss en såkalt **kovariansmatrise**, som er en utvidelse av kovarians til flere variabler. Elementet $M_{ij}$ i kovariansmatrisen $M$ er en korrelasjon mellom inngangsvariablene $X_i$ og $X_j$, og diagonale verdier $M_{ii}$ er variansen til $X_{i}$. På samme måte vil `np.corrcoef` gi oss **korrelasjonsmatrisen**.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(f\"Covariance matrix:\\n{np.cov(heights, salaries)}\")\n",
"print(f\"Covariance = {np.cov(heights, salaries)[0,1]}\")\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"En korrelasjon lik 1 betyr at det er en sterk **lineær sammenheng** mellom to variabler. Vi kan visuelt se den lineære sammenhengen ved å plotte én verdi mot den andre:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(heights,salaries)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La oss se hva som skjer hvis relasjonen ikke er lineær. Anta at selskapet vårt bestemte seg for å skjule den åpenbare lineære avhengigheten mellom høyder og lønninger, og introduserte noe ikke-lineær i formelen, som for eksempel `sin`:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"salaries = 1000+np.sin((heights-heights.min())/(heights.max()-heights.mean()))*100\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"I dette tilfellet er korrelasjonen litt mindre, men den er fortsatt ganske høy. Nå, for å gjøre sammenhengen enda mindre åpenbar, kan vi ønske å legge til litt ekstra tilfeldighet ved å legge til en tilfeldig variabel til lønnen. La oss se hva som skjer:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"salaries = 1000+np.sin((heights-heights.min())/(heights.max()-heights.mean()))*100+np.random.random(size=len(heights))*20-10\n",
"print(f\"Correlation = {np.corrcoef(heights, salaries)[0,1]}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(heights, salaries)\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Kan du gjette hvorfor prikkene stiller seg opp i vertikale linjer slik? \n",
"\n",
"Vi har observert korrelasjonen mellom et kunstig konstruert konsept som lønn og den observerte variabelen *høyde*. La oss også se om de to observerte variablene, som høyde og vekt, korrelerer:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].ffill(),df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dessverre fikk vi ingen resultater bare noen merkelige `nan`-verdier. Dette skyldes at noen av verdiene i serien vår er udefinerte, representert som `nan`, noe som gjør at resultatet av operasjonen også blir udefinert. Ved å se på matrisen kan vi se at `Weight` er den problematiske kolonnen, fordi selvkorrelasjonen mellom `Height`-verdiene er blitt beregnet.\n",
"\n",
"> Dette eksemplet viser viktigheten av **datapreparering** og **rensing**. Uten riktige data kan vi ikke beregne noe.\n",
"\n",
"La oss bruke `fillna`-metoden for å fylle inn de manglende verdiene, og beregne korrelasjonen:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].fillna(method='pad'), df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Det er faktisk en korrelasjon, men ikke en så sterk en som i vårt kunstige eksempel. Hvis vi ser på spredningsdiagrammet av en verdi mot den andre, ville sammenhengen være mye mindre åpenbar:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.figure(figsize=(10,6))\n",
"plt.scatter(df['Weight'],df['Height'])\n",
"plt.xlabel('Weight')\n",
"plt.ylabel('Height')\n",
"plt.tight_layout()\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Konklusjon\n",
"\n",
"I denne notatboken har vi lært hvordan man utfører grunnleggende operasjoner på data for å beregne statistiske funksjoner. Vi vet nå hvordan vi kan bruke et solid apparat av matematikk og statistikk for å bevise noen hypoteser, og hvordan vi kan beregne konfidensintervaller for tilfeldige variabler gitt et datasett.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Ansvarsfraskrivelse**:\nDette dokumentet er oversatt ved hjelp av AI-oversettelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selv om vi jobber for nøyaktighet, vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på originalspråket skal betraktes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for eventuelle misforståelser eller feiltolkninger som oppstår som følge av bruk av denne oversettelsen.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"interpreter": {
"hash": "86193a1ab0ba47eac1c69c1756090baa3b420b3eea7d4aafab8b85f8b312f0c5"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.6"
},
"coopTranslator": {
"original_hash": "0f899e3c5019f948e7c787b22f3b2304",
"translation_date": "2026-01-16T15:48:06+00:00",
"source_file": "1-Introduction/04-stats-and-probability/notebook.ipynb",
"language_code": "no"
}
},
"nbformat": 4,
"nbformat_minor": 4
}