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/sl/1-Introduction/04-stats-and-probability/notebook.ipynb

581 lines
18 KiB

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Uvod v verjetnost in statistiko\n",
"V tem zvezku se bomo igrali z nekaterimi koncepti, o katerih smo že govorili. Veliko konceptov iz verjetnosti in statistike je dobro predstavljeno v glavnih knjižnicah za obdelavo podatkov v Pythonu, kot sta `numpy` in `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": [
"## Naključne spremenljivke in porazdelitve\n",
"Začnimo z vlečenjem vzorca 30 vrednosti iz enakomerne porazdelitve od 0 do 9. Izračunali bomo tudi povprečje in varianco.\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": [
"Za vizualno oceno, koliko različnih vrednosti je v vzorcu, lahko narišemo **histogram**:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.hist(sample)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Analiza dejanskih podatkov\n",
"\n",
"Povprečje in varianca sta zelo pomembna pri analizi podatkov iz resničnega sveta. Naložimo podatke o igralcih baseballa z [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": [
"> Tukaj za analizo podatkov uporabljamo paket [**Pandas**](https://pandas.pydata.org/). Kasneje v tem tečaju bomo več govorili o Pandas in delu s podatki v Pythonu.\n",
"\n",
"Izračunajmo povprečne vrednosti za starost, višino in težo:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df[['Age','Height','Weight']].mean()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Sedaj se osredotočimo na višino ter izračunajmo standardni odklon in varianco:\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": [
"Poleg povprečja je smiselno pogledati tudi mediano in kvartile. Te lahko vizualiziramo z uporabo **škatlastega diagrama**:\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": [
"Lahko tudi naredimo škatlaste diagrame podskupin našega nabora podatkov, na primer razvrščene po vlogi igralca.\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": [
"> **Opomba**: Ta diagram nakazuje, da so povprečne višine prvo baznih igralcev višje od višin drugobaznih igralcev. Kasneje se bomo naučili, kako lahko to hipotezo bolj formalno testiramo in kako dokazati, da so naši podatki statistično značilni za to. \n",
"\n",
"Starost, višina in teža so vse zvezne naključne spremenljivke. Kakšna mislite, da je njihova porazdelitev? Dobro je to ugotoviti z risanjem histograma vrednosti: \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": [
"## Normalna porazdelitev\n",
"\n",
"Ustvarimo umetni vzorec teže, ki sledi normalni porazdelitvi z enakim povprečjem in varianco kot naši dejanski podatki:\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": [
"Ker je večina vrednosti v resničnem življenju normalno porazdeljena, ne bi smeli uporabljati generatorja enakomerno porazdeljenih naključnih števil za generiranje vzorčnih podatkov. Tukaj je, kaj se zgodi, če poskušamo generirati teže z enakomerno porazdelitvijo (generirano z `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": [
"## Intervali zaupanja\n",
"\n",
"Izračunajmo intervale zaupanja za težo in višino bejzbol igralcev. Uporabili bomo kodo [iz te razprave na stackoverflow](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": [
"## Testiranje hipotez\n",
"\n",
"Raziščimo različne vloge v našem naboru podatkov bejzbolskih igralcev:\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": [
"Preizkusimo hipotezo, da so prvi igralci na bazi višji od drugih igralcev na bazi. Najenostavnejši način za to je testiranje intervalov zaupanja:\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": [
"Lahko vidimo, da se intervali ne prekrivajo.\n",
"\n",
"Statistično bolj pravilno potrditev hipoteze izvedemo z uporabo **Studentove t-teste**:\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": [
"Dve vrednosti, ki jih vrne funkcija `ttest_ind`, sta:\n",
"* p-vrednost lahko razumemo kot verjetnost, da imata dve porazdelitvi enak povprečje. V našem primeru je zelo nizka, kar pomeni, da obstajajo trdni dokazi, da so prve baze višje.\n",
"* t-vrednost je vmesna vrednost normalizirane razlike povprečij, ki se uporablja v t-testu, in se primerja z mejno vrednostjo za dano stopnjo zaupanja.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Simulacija normalne porazdelitve s centralnim limitnim izrekom\n",
"\n",
"Generator psevdonaključnih števil v Pythonu je zasnovan tako, da nam daje enakomerno porazdelitev. Če želimo ustvariti generator za normalno porazdelitev, lahko uporabimo centralni limitni izrek. Da dobimo normalno porazdeljeno vrednost, bomo preprosto izračunali povprečje vzorca, ki je ustvarjen z enakomerno porazdelitvijo.\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": [
"## Korelacija in Zlobna Baseball Korporacija\n",
"\n",
"Korelacija nam omogoča, da najdemo povezave med podatkovnimi zaporedji. V našem preprostemu primeru si zamislimo, da obstaja zlobna baseball korporacija, ki svojim igralcem plačuje glede na njihovo višino - višji kot je igralec, več denarja prejme. Predpostavimo, da je osnovna plača 1000 $, in dodatna nagrada od 0 do 100 $, odvisno od višine. Vzamemo resnične igralce iz MLB in izračunamo njihove namišljene plače:\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": [
"Izračunajmo zdaj kovarianco in korelacijo teh zaporedij. `np.cov` nam bo dala t.i. **kovariančno matriko**, ki je razširitev kovariance na več spremenljivk. Element $M_{ij}$ kovariančne matrike $M$ je korelacija med vhodnima spremenljivkama $X_i$ in $X_j$, diagonalne vrednosti $M_{ii}$ pa so varianca $X_i$. Podobno nam bo `np.corrcoef` dala **korelacijsko matriko**.\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": [
"Korelacija enaka 1 pomeni, da obstaja močna **linearna povezava** med dvema spremenljivkama. Linearno povezavo lahko vizualno vidimo z risanjem vrednosti ene spremenljivke proti drugi:\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": [
"Poglejmo, kaj se zgodi, če relacija ni linearna. Predpostavimo, da se je naše podjetje odločilo skriti očitno linearno odvisnost med višino in plačami ter uvedlo nekaj nelinearnosti v formulo, kot je `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": [
"V tem primeru je korelacija nekoliko manjša, a je še vedno precej visoka. Zdaj, da bi razmerje naredili še manj očitno, bi morda želeli dodati nekaj dodatne naključnosti tako, da bi k plači dodali neko naključno spremenljivko. Poglejmo, kaj se zgodi:\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": [
"> Uganete, zakaj se pikice poravnajo v navpične črte tako?\n",
"\n",
"Opazili smo korelacijo med umetno zasnovanim konceptom, kot je plača, in opazovano spremenljivko *višina*. Oglejmo si tudi, ali se dve opazovani spremenljivki, kot sta višina in teža, prav tako korelirata:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].ffill(),df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Na žalost nismo dobili nobenih rezultatov - samo nekaj nenavadnih vrednosti `nan`. To je posledica dejstva, da so nekatere vrednosti v naši seriji nedefinirane, predstavljene kot `nan`, kar tudi povzroči, da je rezultat operacije nedefiniran. Če pogledamo matriko, vidimo, da je problematičen stolpec `Weight`, ker je bila izračunana samokorelacija med vrednostmi `Height`.\n",
"\n",
"> Ta primer prikazuje pomen **priprave podatkov** in **čiščenja**. Brez ustreznih podatkov ne moremo izračunati ničesar.\n",
"\n",
"Uporabimo metodo `fillna` za zapolnitev manjkajočih vrednosti in izračunajmo korelacijo:\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"np.corrcoef(df['Height'].fillna(method='pad'), df['Weight'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Res je, da obstaja korelacija, vendar ne tako močna kot v našem umetnem primeru. Pravzaprav, če pogledamo razpršeni diagram ene vrednosti glede na drugo, bi bila povezava veliko manj očitna:\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": [
"## Zaključek\n",
"\n",
"V tem zapisku smo se naučili, kako izvajati osnovne operacije na podatkih za izračun statističnih funkcij. Sedaj vemo, kako uporabiti ustrezno orodje matematike in statistike za dokazovanje nekaterih hipotez ter kako izračunati intervale zaupanja za poljubne spremenljivke, glede na vzorec podatkov.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Omejitev odgovornosti**:\nTa dokument je bil preveden z uporabo AI prevajalske storitve [Co-op Translator](https://github.com/Azure/co-op-translator). Čeprav si prizadevamo za natančnost, upoštevajte, da lahko avtomatizirani prevodi vsebujejo napake ali netočnosti. Izvirni dokument v njegovem izvorno jeziku se šteje za avtoritativni vir. Za ključne informacije priporočamo strokovni človeški prevod. Ne odgovarjamo za morebitna nesporazuma ali napačne interpretacije, ki bi izhajali iz uporabe tega prevoda.\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-16T20:28:14+00:00",
"source_file": "1-Introduction/04-stats-and-probability/notebook.ipynb",
"language_code": "sl"
}
},
"nbformat": 4,
"nbformat_minor": 4
}