Math 183 • Statistical Methods • Spring 2026
% % \providecommand{}{p_{0}} \providecommand{}{p_{1}} \providecommand{}{p_{2}} \providecommand{}{p_{12}} \providecommand{1n}{p_{1n}} % % % % $$
Sums of Binomial Random Variables
Let \(X \sim {\text{Bin}}(n, p)\), \(Y \sim {\text{Bin}}(m, p)\) and \(X \perp\kern-5pt \perp Y\), then \[ X + Y \sim {\text{Bin}}(n + m, p) \]
Sums of \(n\) \(iid\) Binomial Random Variables
Let \(X_1, X_2, \dots, X_n{\stackrel{iid}{\sim}}{\text{Bin}}(k, p)\) be \(iid\) Binomial random variables then \[ n\overline{X}= X_1 + X_2 + \dots + X_n \sim {\text{Bin}}(n \cdot k, p) \]
Sums of Poisson Random Variables
Let \(X \sim {\text{Poi}}(\lambda)\), \(Y \sim {\text{Poi}}(\gamma)\) and \(X \perp\kern-5pt \perp Y\), then \[ X + Y \sim {\text{Poi}}(\lambda + \gamma) \]
Sums of \(n\) \(iid\) Poisson Random Variables
Let \(X_1, X_2, \dots, X_n{\stackrel{iid}{\sim}}{\text{Poi}}(\lambda)\) be \(iid\) Poisson random variables then \[ n \cdot \overline{X}= X_1 + X_2 + \dots + X_n \sim {\text{Poi}}(n \cdot \lambda) \]
Sums of Chi-Squared Random Variables
Let \(X \sim {\chi^2}(d)\), \(Y \sim {\chi^2}(k)\) and \(X \perp\kern-5pt \perp Y\), then \[ X + Y \sim {\chi^2}(d+k) \]
Sums of \(n\) \(iid\) Chi-Squared Random Variables
Let \(X_1, X_2, \dots, X_n{\stackrel{iid}{\sim}}{\chi^2}(d)\) be \(iid\) Chi Squared random variables then \[ n \cdot \overline{X}= X_1 + X_2 + \dots + X_n \sim {\chi^2}(n \cdot d) \]
Sums of Normal Random Variables
Let \(X \sim N(\mu_X, \sigma_X^2)\), \(Y \sim N(\mu_Y, \sigma_Y^2)\) and \(X \perp\kern-5pt \perp Y\), then for all \(a, b \in {\mathbb R}\) \[ aX + bY \sim N\Big(a \mu_X + b \mu_Y, \ \ \ a^2 \sigma_X^2 + b^2 \sigma_Y^2\Big) \]
What happens when \(b=0\)? What happens when \(Y=1\) is not random?
Sums of \(n\) \(iid\) Normal Random Variables
Let \(X_1, X_2, \dots, X_n{\stackrel{iid}{\sim}}N(\mu, \sigma^2)\) be \(iid\) Normal random variables then \[ \overline{X}= \frac{X_1 + X_2 + \dots + X_n}{n} \sim N\Big(\mu, \frac{\sigma^2}{n}\Big) \]
Standardizing a Normal Random Variable
Let \(X \sim N(\mu, \sigma^2)\) be a Normal random variable with mean \(\mu\) and variance \(\sigma^2\) \[ \frac{X - \mu}{\sigma} \sim N(0, 1) \equiv Z \]
Why?
\[\begin{aligned} X &\sim N(\mu, \sigma^2)\\ X - \mu &\sim N(0, \sigma^2)\\ \sigma^{-1}(X - \mu) &\sim N(0, \sigma^2 / \sigma^2) = N(0, 1)\\ \end{aligned}\]
Student’s \(t\)-distribution
A random variable \(X \sim t(d)\) is said to follow the Student’s \(t\)-distribution with \(d\) degrees of freedom if \[ X = \frac{Z}{\sqrt{Y/d}} \qquad \text{where } Z \sim N(0, 1), \quad Y \sim {\chi^2}(d) \text{ and } X \perp\kern-5pt \perp Y. \]
Let \(X_1, X_2, \dots, X_n\) be \(iid\) random variables with:
Then
\[ \overline{X}= \frac{X_1 + X_2 + \dots + X_n}{n} \approx {\mathbb E}(X) \qquad \text{as } n \rightarrow \infty. \]
#| standalone: true
#| viewerHeight: 600
#| components: viewer
#| layout: vertical
import numpy as np
import scipy
import pandas as pd
import scipy.stats as stats
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from shiny import App, render, ui
from matplotlib.patches import Patch
import statsmodels.api as sm
from ipywidgets import interact, fixed
# Generate a random sample
# Define the UI
app_ui = ui.page_fluid(
ui.layout_sidebar(
ui.sidebar(
ui.input_slider(
"n",
"n",
min = 1,
max = 100,
value = 1,
step = 1,
ticks=True,
animate=False
),
ui.input_radio_buttons(
"dist",
"Distribution",
choices=[
"Bernoulli",
"Uniform",
"Exponential",
"Normal",
],
inline=False
),
ui.panel_conditional(
"input.dist == 'Bernoulli'",
ui.input_slider(
"p",
"p",
min = 1e-1, max=1-1e-1, value=0.5, step=1e-1
)
),
ui.panel_conditional(
"input.dist == 'Uniform'",
ui.input_slider(
"a",
"a",
min = -5, max=0, value=-1, step=0.5
),
ui.input_slider(
"b",
"b",
min = 0, max=5, value=1, step=0.5
)
),
ui.panel_conditional(
"input.dist == 'Exponential'",
ui.input_slider(
"lam",
"lambda",
min = 1e-1, max=2-1e-1, value=1.0, step=1e-1
)
),
ui.panel_conditional(
"input.dist == 'Normal'",
ui.input_slider(
"mu",
"mu",
min = -2.0, max=2.0, value=0.0, step=5e-1
),
ui.input_slider(
"sigma",
"sigma",
min = 0.5, max=2.5, value=0.5, step=0.5
)
),
ui.input_slider(
"n_exp",
"n_exp",
min = 1,
max = 10,
value = 1,
step = 1,
ticks=True,
animate=False
),
),
ui.output_plot("plots", height="500px")
)
)
# Define the server logic
def server(input, output, session):
@output
@render.plot
def plots():
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
n = input.n()
if input.dist() == "Bernoulli":
p = input.p()
X = stats.bernoulli(p)
zlim = np.array([-0.5, 1.5])
elif input.dist() == "Uniform":
a, b = input.a(), input.b()
X = stats.uniform(loc=a, scale=b-a)
zlim = np.array([-5, 5])
elif input.dist() == "Exponential":
lam = input.lam()
X = stats.expon(0, 1 / lam)
zlim = np.array([-0.5, 3])
elif input.dist() == "Normal":
mu, sigma = input.mu(), input.sigma()
X = stats.norm(mu, sigma)
zlim = np.array([-4, 4])
np.random.seed(2024)
for i in range(input.n_exp()):
Xs = X.rvs(n)
hist, edges = np.histogram(Xs, bins=20)
ys = np.array([])
xs = np.array([])
for i in range(len(hist)):
ys = np.append(ys, np.arange(hist[i]))
xs = np.append(xs, np.repeat(edges[i], hist[i]))
ax[0].scatter(xs, ys, alpha=max(0.2, 1 / input.n_exp()))
ax[0].set_ylim([-0.5, 20])
# ax[0].hist(Xs, bins=20, density=False, alpha=0.6, color='g')
ax[0].set_xlim(zlim)
average_X = np.cumsum(Xs) / np.arange(1, n + 1)
ax[1].plot(range(1, n + 1), average_X)
ax[1].axhline(y=X.mean(), color='red', linestyle='--')
ax[1].set_ylim(zlim)
ax[1].set_xlim([1, 100])
ax[1].set_xlabel('Number of trials')
ax[1].set_ylabel('Average')
ax[1].set_title(f'Average of {n} samples from {X.dist.name}{X.args}')
plt.tight_layout()
return fig
# Create the Shiny app
app = App(app_ui, server)
app
Let \(X_1, X_2, \dots, X_n\) be \(iid\) random variables with:
Then
\[ \frac{\overline{X}- {\mathbb E}(X)}{\sqrt{{{\text{Var}}(X)}/{n}}} \approx N(0,1) \qquad \text{as } n \rightarrow \infty. \]
Equivalently,
\[ \sqrt{n}\Bigg(\frac{\overline{X}- {\mathbb E}(X)}{{{\text{SD}(X)}}}\Bigg) \approx N(0,1) \qquad \text{as } n \rightarrow \infty. \]
#| standalone: true
#| viewerHeight: 600
#| components: viewer
#| layout: vertical
import numpy as np
import scipy
import pandas as pd
import scipy.stats as stats
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D
from shiny import App, render, ui
from matplotlib.patches import Patch
import statsmodels.api as sm
from ipywidgets import interact, fixed
import seaborn as sns
# Generate a random sample
# Define the UI
app_ui = ui.page_fluid(
ui.layout_sidebar(
ui.sidebar(
ui.input_slider(
"n",
"n",
min = 10,
max = 500,
value = 1,
step = 1,
ticks=True,
animate=False
),
ui.input_radio_buttons(
"dist",
"Distribution",
choices=[
"Bernoulli",
"Uniform",
"Exponential",
"Normal",
],
inline=False
),
ui.panel_conditional(
"input.dist == 'Bernoulli'",
ui.input_slider(
"p",
"p",
min = 1e-1, max=1-1e-1, value=0.5, step=1e-1
)
),
ui.panel_conditional(
"input.dist == 'Uniform'",
ui.input_slider(
"a",
"a",
min = -5, max=0, value=-1, step=0.5
),
ui.input_slider(
"b",
"b",
min = 0, max=5, value=1, step=0.5
)
),
ui.panel_conditional(
"input.dist == 'Exponential'",
ui.input_slider(
"lam",
"lambda",
min = 1e-1, max=2-1e-1, value=1.0, step=1e-1
)
),
ui.panel_conditional(
"input.dist == 'Normal'",
ui.input_slider(
"mu",
"mu",
min = -2.0, max=2.0, value=0.0, step=5e-1
),
ui.input_slider(
"sigma",
"sigma",
min = 0.5, max=2.5, value=0.5, step=0.5
)
),
),
ui.output_plot("plots", height="500px")
)
)
# Define the server logic
def server(input, output, session):
@output
@render.plot
def plots():
fig, ax = plt.subplots(1, 2, figsize=(12, 5))
n = input.n()
if input.dist() == "Bernoulli":
p = input.p()
X = stats.bernoulli(p)
zlim = np.array([-0.5, 1.5])
elif input.dist() == "Uniform":
a, b = input.a(), input.b()
X = stats.uniform(loc=a, scale=b-a)
zlim = np.array([-5, 5])
elif input.dist() == "Exponential":
lam = input.lam()
X = stats.expon(0, 1 / lam)
zlim = np.array([-0.5, 3])
elif input.dist() == "Normal":
mu, sigma = input.mu(), input.sigma()
X = stats.norm(mu, sigma)
zlim = np.array([-4, 4])
np.random.seed(2024)
# ax[0].set_xlim(zlim)
Xn = np.array([(X.rvs(n).mean() - X.mean()) / (X.std() / np.sqrt(n)) for _ in range(n)])
ax[0].hist(Xn, bins=20, density=True, alpha=0.6, color='dodgerblue')
xlim = ax[0].get_xlim()
xs = np.linspace(*xlim, 100)
ax[0].plot(xs, stats.norm.pdf(xs), color='red', linestyle='--')
ax[0].set_title(f'{n} experiments sampling from {X.dist.name}{X.args}')
ax[0].set_ylim([0, 0.5])
ecdf = lambda x: np.sum(Xn < x) / n
ax[1].plot(xs, stats.norm.cdf(xs), color='red', linestyle='--')
ax[1].plot(xs, [ecdf(x) for x in xs])
plt.tight_layout()
return fig
# Create the Shiny app
app = App(app_ui, server)
app
Let \(X_1, X_2, \dots, X_n\) be \(iid\) with expected value \({\mathbb E}(X)\), AND variance \({\text{Var}}(X)\)
\[ \overline{X}- {\mathbb E}(X) \rightarrow 0. \]
\[ \sqrt{n}\Bigg(\frac{\overline{X}- {\mathbb E}(X)}{\text{SD}(X)}\Bigg) \Rightarrow N(0, 1). \]
Binomial-Normal Approximation (w/o continuity correction)
Let \(X \sim {\text{Bin}}(n, p)\). For large \(n\) \[ X \approx N\Big(np, \ \ \ np \cdot (1-p)\Big) \]
Poisson-Normal Approximation (w/o continuity correction)
Let \(X \sim {\text{Poi}}(\lambda)\). For large \(\lambda\) \[ X \approx N\Big(\lambda, \ \ \lambda\Big) \]