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.
581 lines
18 KiB
581 lines
18 KiB
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Introduction to Probability and Statistics\n",
|
|
"For dis notebook, we go play with some of di concepts we don tok before. Plenty concepts from probability and statistics dey well show for big libraries wey dey do data processing for Python, like `numpy` and `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": [
|
|
"## Random Variables and Distributions\n",
|
|
"Make we start by draw sample of 30 values from one uniform distribution wey dey from 0 go 9. We go also calculate mean and variance.\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": [
|
|
"To visually estimate how many different values dem get for the sample, we fit plot di **histogram**:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"plt.hist(sample)\n",
|
|
"plt.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Analyzing Real Data\n",
|
|
"\n",
|
|
"Mean and variance na very important tin wen you dey analyze real-world data. Make we load di data about baseball players from [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": [
|
|
"> We dey use one package wey dem dey call [**Pandas**](https://pandas.pydata.org/) here for data analysis. We go talk more about Pandas and how to dey work with data for Python later for this course.\n",
|
|
"\n",
|
|
"Make we calculate average values for age, height and weight:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"df[['Age','Height','Weight']].mean()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Now make we focus on height, and calculate standard deviation and variance:\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": [
|
|
"Besides mean, e dey make sense to look di median value and quartiles. Dem fit show for **box plot**:\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": [
|
|
"Wi fit also make box plots of small parts of our dataset, for example, group by player role.\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": [
|
|
"> **Note**: Dis diagram dey show say, for average, di height of first basemen taller pass di height of second basemen. Later we go learn how to test dis hypothesis for forma way, and how to show say our data get statistical meaning to prove am. \n",
|
|
"\n",
|
|
"Age, height and weight na continuous random variables. Wetin you think na di distribution dem get? One beta way to sabi na to plot di histogram of values: \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": [
|
|
"## Normal Distribution\n",
|
|
"\n",
|
|
"Make we create one artificial sample of weights wey follow normal distribution wey get the same mean and variance as our real 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": [
|
|
"Since most values for real life dey normally distributed, we no suppose use uniform random number generator to generate sample data. Na wetin go happen if we try generate weights with uniform distribution (wey `np.random.rand` generate):\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": [
|
|
"## Confidence Intervals\n",
|
|
"\n",
|
|
"Make we calculate confidence intervals for the weights and heights of baseball players now. We go use the code [from this stackoverflow discussion](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": [
|
|
"## Hypothesis Testing\n",
|
|
"\n",
|
|
"Make we check different role dem for our baseball players dataset:\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": [
|
|
"Make we test di hypothesis say First Basemen tall pass Second Basemen. Di easiest way to do dis na to test di confidence intervals:\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": [
|
|
"We fit see say di intervals no dey overlap.\n",
|
|
"\n",
|
|
"One statistically correct way to take prove di hypothesis na to use **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": [
|
|
"Di two values wey di `ttest_ind` function return na:\n",
|
|
"* p-value fit be considered as di chance say two distributions get di same mean. For our case, e low well well, meaning say e get strong evidence wey dey support say first basemen tall pass.\n",
|
|
"* t-value na di intermediate value of normalized mean difference wey dem dey use for di t-test, and dem dey compare am against one threshold value based on di confidence value wey dem set.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Simulating a Normal Distribution wit di Central Limit Theorem\n",
|
|
"\n",
|
|
"Di pseudo-random generator wey dey Python na him dem design to give us uniform distribution. If we wan create generator for normal distribution, we fit use di central limit theorem. To get normal distributed value, we go just compute di mean of uniform-generated sample.\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": [
|
|
"## Correlation and Evil Baseball Corp\n",
|
|
"\n",
|
|
"Correlation dey allow us find relationship between data sequences. For our toy example, mek we pretend say one evil baseball corporation dey wey dey pay dia players base on how tall dem be - di taller di player be, di more money e go get. Make we suppose say base salary na $1000, plus bonus wey fit be from $0 to $100, depending on height. We go use real players from MLB, come calculate dia imaginary salaries:\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": [
|
|
"Make we calculate covariance and correlation of those sequences now. `np.cov` go give us wetin dem dey call **covariance matrix**, wey be extension of covariance to plenti variables. The element $M_{ij}$ for covariance matrix $M$ na correlation between input variables $X_i$ and $X_j$, and the diagonal values $M_{ii}$ na the variance of $X_{i}$. Likewise, `np.corrcoef` go give us the **correlation matrix**.\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": [
|
|
"One correlation wey equal to 1 mean say e get strong **linear relation** between two variables. We fit see di linear relation clearly by plotting one value against the oda:\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": [
|
|
"Make we see wetin go happen if the relation no be linear. Suppose say our company decide hide the clear linear dependence between heights and salaries, and put some non-linearity inside the formula, like `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": [
|
|
"For dis kain case, di correlation small small reduce, but e still high well well. Now, to make di relation no too clear, we fit add some extra randomness by adding some random variable for di salary. Make we see wetin go happen:\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": [
|
|
"> You fit guess why di dots dem line up to vertical lines like dis?\n",
|
|
"\n",
|
|
"We don observe di connection between one artificial engineered idea like salary and di thing wey we dey observe *height*. Make we also check if di two observed variables, like height and weight, get connection too:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"np.corrcoef(df['Height'].ffill(),df['Weight'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Unfortunately, we no see any results - na only some kind strange `nan` values. Dis one happen because some of di values inside our series no get definition, wey dem represent as `nan`, wey cause di result of di operation to be no defined too. If we look di matrix, we fit see say `Weight` na di column wey dey cause wahala, because self-correlation between `Height` values don already calculate.\n",
|
|
"\n",
|
|
"> Dis example show how **data preparation** and **cleaning** important. Without correct data, we no fit calculate anything.\n",
|
|
"\n",
|
|
"Make we use `fillna` method to fill di missing values, then calculate di correlation:\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"np.corrcoef(df['Height'].fillna(method='pad'), df['Weight'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"True true, e get correlation, but e no strong like for our artificial example. If we look the scatter plot wey show one value against the other, the relation no go too clear:\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": [
|
|
"## Conclusion\n",
|
|
"\n",
|
|
"For dis notebook we don learn how to perform basic operations on data to calculate statistical functions. Now we sabi how to use correct math and statistics tools to prove some hypotheses, and how to calculate confidence intervals for any variables wey get data sample.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Disclaimer**:\nDis dokument don translate wit AI translation service wey dem dey call [Co-op Translator](https://github.com/Azure/co-op-translator). Even though we dey try make am correct, abeg sabi say automatic translation fit get some mistake or no too clear. The original dokument wey dem write for im correct language na the real correct source. If na serious matter, better make professional human person translate am. We no go take responsibility if person no understand or misunderstand because of dis translation.\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-16T22:20:00+00:00",
|
|
"source_file": "1-Introduction/04-stats-and-probability/notebook.ipynb",
|
|
"language_code": "pcm"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |