import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
def plot_xbar_test(mu0, sigma, n, x_bar, alpha=0.05, kind='left', title=''):
se = sigma / np.sqrt(n)
x_grid = np.linspace(mu0 - 4 * se, mu0 + 4 * se, 1000)
y_grid = norm.pdf(x_grid, loc=mu0, scale=se)
plt.figure(figsize=(8, 4))
plt.plot(x_grid, y_grid, lw=2, label='Плотность распределения $\\bar{X}$ при $H_0$')
if kind == 'left':
z_crit = norm.ppf(alpha)
k = mu0 + z_crit * se
mask = x_grid <= k
plt.fill_between(x_grid[mask], y_grid[mask], alpha=0.35, color='tomato', label='Критическая зона')
plt.axvline(k, color='tomato', ls='--', lw=2, label=f'K = {k:.3f}')
elif kind == 'right':
z_crit = norm.ppf(1 - alpha)
k = mu0 + z_crit * se
mask = x_grid >= k
plt.fill_between(x_grid[mask], y_grid[mask], alpha=0.35, color='tomato', label='Критическая зона')
plt.axvline(k, color='tomato', ls='--', lw=2, label=f'K = {k:.3f}')
elif kind == 'two-sided':
z_half = norm.ppf(1 - alpha / 2)
k_l = mu0 - z_half * se
k_r = mu0 + z_half * se
mask_l = x_grid <= k_l
mask_r = x_grid >= k_r
plt.fill_between(x_grid[mask_l], y_grid[mask_l], alpha=0.35, color='tomato', label='Критические зоны')
plt.fill_between(x_grid[mask_r], y_grid[mask_r], alpha=0.35, color='tomato')
plt.axvline(k_l, color='tomato', ls='--', lw=2, label=f'K_L = {k_l:.3f}')
plt.axvline(k_r, color='tomato', ls='--', lw=2, label=f'K_R = {k_r:.3f}')
else:
raise ValueError("kind должен быть 'left', 'right' или 'two-sided'")
plt.axvline(x_bar, color='navy', lw=2, label=f'Наблюдаемое $\\bar{{x}}$ = {x_bar:.3f}')
plt.title(title)
plt.xlabel('$\\bar{X}$')
plt.ylabel('Плотность')
plt.legend(loc='upper left')
plt.grid(alpha=0.2)
plt.show()Проверка гипотезы о неизвестном матожидании (известная дисперсия)
Разбираем сюжет с жирафами в трех вариантах: - левосторонний тест; - правосторонний тест; - двусторонний тест.
Общие условия применимости \(Z\)-теста для среднего: - наблюдения независимы; - либо распределение исследуемой величины нормальное, либо выборка достаточно большая; - известна истинная дисперсия \(\sigma^2\); - уровень значимости фиксирован: \(\alpha = 0.05\).
Во всех графиках показывается именно распределение выборочного среднего при нулевой гипотезе: \[ \bar X \mid H_0 \sim \mathcal N\!\left(\mu_0, \frac{\sigma^2}{n}\right). \]
1) Левосторонний тест
Условия задачи: - \(X\) — длина шеи жирафа (м); - независимая выборка объема \(n = 20\); - известное стандартное отклонение \(\sigma = 0.4\); - наблюдаемое среднее \(\bar x = 2.8\); - проверяем гипотезу о среднем \(\mu_0 = 6.0\) при \(\alpha = 0.05\).
Теория: - гипотезы: \(H_0: \mu = \mu_0\) против \(H_1: \mu < \mu_0\); - при \(H_0\): \[ \bar X \sim \mathcal N\!\left(\mu_0, \frac{\sigma^2}{n}\right); \] - решающая граница задается условием: \[ P_{H_0}(\bar X < K) = \alpha; \] - стандартизуем и делаем замену переменной: \[ P\!\left(\frac{\bar X-\mu_0}{\sigma/\sqrt n} < \frac{K-\mu_0}{\sigma/\sqrt n}\right)=\alpha \Rightarrow P(Z<z_\alpha)=\alpha; \]
- нужно понимать, что так как \(\alpha\) по своей логике должна быть небольшой вероятностью и по здравому смыслу меньше \(0.5\), то в уравнении выше эта точка по факту будет отрицательной. Можно обозначить ее \((-|z_{\alpha}|)\), чтобы не было сомнений.
- восстанавливаем границу: \[ \frac{K-\mu_0}{\sigma/\sqrt n}=-|z_{\alpha}| \Rightarrow K=\mu_0 - |z_\alpha| \frac{\sigma}{\sqrt n}; \]
- правило: отклоняем \(H_0\), если \(\bar x < K\).
# Левосторонний тест
mu0 = 6.0
sigma = 0.4
n = 20
x_bar = 2.8
alpha = 0.05
z_alpha = norm.ppf(1 - alpha)
K = mu0 - z_alpha * sigma / np.sqrt(n)
print(f"K = {K:.3f}")
print("Решение:", "Отклоняем H0" if x_bar < K else "Не отклоняем H0")
plot_xbar_test(
mu0=mu0,
sigma=sigma,
n=n,
x_bar=x_bar,
alpha=alpha,
kind='left',
title='Левосторонний тест: распределение $\\bar{X}$ при $H_0$'
)2) Правосторонний тест
Условия задачи: - \(X\) — длина шеи жирафа (м); - независимая выборка объема \(n = 20\); - известное стандартное отклонение \(\sigma = 0.1\); - наблюдаемое среднее \(\bar x = 2.8\); - проверяем гипотезу о среднем \(\mu_0 = 1.8\) при \(\alpha = 0.05\).
Теория: - гипотезы: \(H_0: \mu = \mu_0\) против \(H_1: \mu > \mu_0\); - при \(H_0\): \[ \bar X \sim \mathcal N\!\left(\mu_0, \frac{\sigma^2}{n}\right); \] - решающая граница задается условием: \[ P_{H_0}(\bar X > K) = \alpha; \] - стандартизуем и делаем замену переменной: \[ P\!\left(\frac{\bar X-\mu_0}{\sigma/\sqrt n} > \frac{K-\mu_0}{\sigma/\sqrt n}\right)=\alpha \Rightarrow P(Z>z_{\alpha})=\alpha; \] - снова так как \(\alpha\) по своей логике должна быть небольшой вероятностью и по здравому смыслу меньше \(0.5\), то в уравнении выше эта точка должна быть положительной. Тут не возникнет путаницы, можно продолжать без знака модуля.
- восстанавливаем границу: \[ \frac{K-\mu_0}{\sigma/\sqrt n}=z_{\alpha} \Rightarrow K=\mu_0+z_{\alpha}\frac{\sigma}{\sqrt n}; \]
- правило: отклоняем \(H_0\), если \(\bar x > K\).
# Правосторонний тест
mu0 = 1.8
sigma = 0.1
n = 20
x_bar = 2.8
alpha = 0.05
z_alpha = norm.ppf(1 - alpha)
K = mu0 + z_alpha * sigma / np.sqrt(n)
print(f"K = {K:.3f}")
print("Решение:", "Отклоняем H0" if x_bar > K else "Не отклоняем H0")
plot_xbar_test(
mu0=mu0,
sigma=sigma,
n=n,
x_bar=x_bar,
alpha=alpha,
kind='right',
title='Правосторонний тест: распределение $\\bar{X}$ при $H_0$'
)3) Двусторонний тест
Условия задачи (модификация): - \(X\) — длина шеи жирафа (м); - независимая выборка объема \(n = 20\); - известное стандартное отклонение \(\sigma = 0.4\); - наблюдаемое среднее \(\bar x = 2.8\); - проверяем гипотезу о среднем \(\mu_0 = 3.0\) при \(\alpha = 0.05\).
Теория: - гипотезы: \(H_0: \mu = \mu_0\) против \(H_1: \mu \neq \mu_0\); - при \(H_0\): \[ \bar X \sim \mathcal N\!\left(\mu_0, \frac{\sigma^2}{n}\right); \] - границы задаются условиями: \[ P_{H_0}(\bar X < K_L)=\frac{\alpha}{2},\qquad P_{H_0}(\bar X > K_R)=\frac{\alpha}{2}; \] - стандартизуем и делаем замену переменной: \[ P\!\left(\frac{K_L-\mu_0}{\sigma/\sqrt n} < Z < \frac{K_R-\mu_0}{\sigma/\sqrt n}\right)=1-\alpha \Rightarrow P(-z_{\alpha/2}<Z<z_{\alpha/2})=1-\alpha; \] - восстанавливаем границы: \[ K_L=\mu_0-z_{\alpha/2}\frac{\sigma}{\sqrt n},\qquad K_R=\mu_0+z_{\alpha/2}\frac{\sigma}{\sqrt n}; \] - правило: отклоняем \(H_0\), если \(\bar x < K_L\) или \(\bar x > K_R\).
# Двусторонний тест
mu0 = 3.0
sigma = 0.4
n = 20
x_bar = 2.8
alpha = 0.05
z_half = norm.ppf(1 - alpha / 2)
K_L = mu0 - z_half * sigma / np.sqrt(n)
K_R = mu0 + z_half * sigma / np.sqrt(n)
print(f"K_L = {K_L:.3f}, K_R = {K_R:.3f}")
print("Решение:", "Отклоняем H0" if (x_bar < K_L or x_bar > K_R) else "Не отклоняем H0")
plot_xbar_test(
mu0=mu0,
sigma=sigma,
n=n,
x_bar=x_bar,
alpha=alpha,
kind='two-sided',
title='Двусторонний тест: распределение $\\bar{X}$ при $H_0$'
)