{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "799ee5dc",
   "metadata": {},
   "source": [
    "# Week 2 lab: Descriptive stattistics + Bootstrap(sampling variability)\n",
    "\n",
    "Keypoints:\n",
    "- Descriptive statistics (center, spread, shape)\n",
    "- population vs sample\n",
    "- sampling variability\n",
    "\n",
    "Lab focus: \n",
    "- Bootstrap intuition (mean vs median)\n",
    "- Why estimates \"move\"\n",
    "- effect of sample size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "3cd42504",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.00123015,  0.29874554, -0.27413786])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# cell 1: Imports + settings\n",
    "import numpy as np \n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "rng = np.random.default_rng(7) \n",
    "rng.normal(size=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7dee5625",
   "metadata": {},
   "source": [
    "# Example 1: Descriptive statistic\n",
    "We will compute the mean, median, SD, variance, IQR, five-number summary, and flag out the outliers using the $1.5\\times IQR$ rule."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "7e5313f5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0    2.720289\n",
       " 1    3.251926\n",
       " 2    2.306007\n",
       " 3    1.593041\n",
       " 4    2.069273\n",
       " Name: x, dtype: float64,\n",
       " count    60.000000\n",
       " mean      3.025476\n",
       " std       2.512343\n",
       " min       0.600462\n",
       " 25%       1.674114\n",
       " 50%       2.626124\n",
       " 75%       3.280787\n",
       " max      18.123107\n",
       " Name: x, dtype: float64)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Cell 2: Build a dataset with skew + outlier\n",
    "rng = np.random.default_rng(7) \n",
    "n = 60 \n",
    "x = rng.lognormal(mean=1.0, sigma=0.6, size=n) #right-skew\n",
    "x[-1] *= 10\n",
    "x = pd.Series(x, name=\"x\")\n",
    "x.head(), x.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "34a14a88",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "({'min': np.float64(0.6004620561861885),\n",
       "  'Q1': np.float64(1.6741136607158649),\n",
       "  'median': np.float64(2.6261243464658732),\n",
       "  'Q3': np.float64(3.2807868747809836),\n",
       "  'max': np.float64(18.12310679128717)},\n",
       " np.float64(1.6066732140651188),\n",
       " np.float64(-0.7358961603818135),\n",
       " np.float64(5.690796695878662))"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Cell 3: Five-numbers + IQR + outliers fence:\n",
    "q1 = x.quantile(0.25)\n",
    "q2 = x.quantile(0.50)\n",
    "q3 = x.quantile(0.75)\n",
    "iqr = q3-q1\n",
    "\n",
    "lowerFence = q1-1.5*iqr\n",
    "upperFence = q3+1.5*iqr\n",
    "\n",
    "fiveN = {\n",
    "    \"min\": x.min(),\n",
    "    \"Q1\": q1,\n",
    "    \"median\": x.median(),\n",
    "    \"Q3\": q3,\n",
    "    \"max\": x.max()\n",
    "}\n",
    "fiveN, iqr, lowerFence, upperFence"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "1886a0a7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "({'mean': np.float64(3.0254764501575737),\n",
       "  'median': np.float64(2.6261243464658732),\n",
       "  'std': np.float64(2.512343173247777),\n",
       "  'var': np.float64(6.31186822016471),\n",
       "  'IQR': np.float64(1.6066732140651188),\n",
       "  'nOutliers': 5},\n",
       " 7      6.074679\n",
       " 44     6.142882\n",
       " 49     9.027269\n",
       " 58     6.443769\n",
       " 59    18.123107\n",
       " Name: x, dtype: float64)"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "outliers = x[(x<lowerFence) | (x>upperFence)]\n",
    "summary = {\n",
    "    \"mean\": x.mean(),\n",
    "    \"median\": x.median(),\n",
    "    \"std\": x.std(ddof=1),\n",
    "    \"var\": x.var(ddof=1),\n",
    "    \"IQR\": iqr,\n",
    "    \"nOutliers\": len(outliers)\n",
    "}\n",
    "summary, outliers"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "af45b496",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 12912 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 10096 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Cell 5: Visual Diagnostics - boxplot + histogram\n",
    "nBins = 25\n",
    "plt.figure()\n",
    "plt.hist(x, bins=nBins)\n",
    "plt.title(\"Histogram\")\n",
    "plt.xlabel(\"x\"); plt.ylabel(\"Counts\")\n",
    "plt.show()\n",
    "\n",
    "plt.figure()\n",
    "plt.boxplot(x, vert=False, showmeans=True)\n",
    "plt.title(\"Boxplot\")\n",
    "plt.xlabel(\"x\")\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv (3.14.2)",
   "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.14.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
