В чем разница между t-тестом и тестом Манна-Уитни?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
T-тест vs Тест Манна-Уитни: полное сравнение
Оба теста используются для сравнения двух групп данных, но они основаны на разных предположениях и работают с разными типами данных. Выбор между ними критичен для корректности статистического анализа.
T-тест (Student's t-test)
Назначение: Проверяет, отличаются ли средние значения двух групп значимо.
Нулевая гипотеза (H0): μ₁ = μ₂ (средние двух групп равны)
Альтернативная гипотеза (H1): μ₁ ≠ μ₂ (средние отличаются)
Основные предположения:
- Нормальность: Данные в обеих группах должны быть нормально распределены
- Гомогенность дисперсии: Дисперсии двух групп должны быть примерно равны
- Независимость: Наблюдения в двух группах независимы
- Количественные данные: Данные должны быть непрерывными и количественными
Формула статистики t:
t = (x₁ - x₂) / sqrt(s²ₚ * (1/n₁ + 1/n₂))
где:
x₁, x₂ — средние значения групп
s²ₚ — объединенная дисперсия
n₁, n₂ — размеры групп
Пример реализации:
from scipy import stats
import numpy as np
# Две группы данных
group1 = np.array([23, 45, 56, 78, 89, 95, 102, 110])
group2 = np.array([15, 32, 48, 61, 73, 88, 99, 105])
# Independent samples t-test
t_statistic, p_value = stats.ttest_ind(group1, group2)
print(f"T-statistic: {t_statistic:.4f}")
print(f"P-value: {p_value:.4f}")
if p_value < 0.05:
print("Отвергаем H0: средние значения значимо отличаются")
else:
print("Не отвергаем H0: средние значения не отличаются")
Пример интерпретации:
Группа 1 (обучение с методом А): среднее = 78, SD = 20
Группа 2 (обучение с методом В): среднее = 62, SD = 22
t-тест: t = 1.85, p = 0.083
Вывод: При α = 0.05, нет значимого различия между методами обучения
Тест Манна-Уитни (Mann-Whitney U test)
Назначение: Непараметрический альтернатив t-тесту. Проверяет, отличаются ли распределения двух групп.
Нулевая гипотеза (H0): Два распределения идентичны (или медианы равны)
Альтернативная гипотеза (H1): Распределения отличаются
Основные предположения:
- Независимость: Наблюдения независимы
- Порядковые/количественные данные: Данные должны быть хотя бы ординальными
- НЕ требует нормальности: Работает с любыми распределениями
- НЕ требует равных дисперсий: Не чувствителен к разным дисперсиям
Как это работает (на примере U-статистики):
1. Объединить две группы и отранжировать все значения от 1 до n₁+n₂
2. Суммировать ранги для первой группы: R₁
3. Вычислить U-статистику: U = n₁*n₂ + n₁(n₁+1)/2 - R₁
4. Найти p-value на основе U
Пример реализации:
from scipy import stats
import numpy as np
# Две группы данных (может быть любое распределение)
group1 = np.array([23, 45, 56, 78, 89, 95, 102, 110])
group2 = np.array([15, 32, 48, 61, 73, 88, 99, 105])
# Mann-Whitney U test
u_statistic, p_value = stats.mannwhitneyu(group1, group2, alternative='two-sided')
print(f"U-statistic: {u_statistic:.4f}")
print(f"P-value: {p_value:.4f}")
# Также можно получить медианы
print(f"Медиана группы 1: {np.median(group1)}")
print(f"Медиана группы 2: {np.median(group2)}")
Пример с ранжированием
Группа 1: [10, 20, 30]
Группа 2: [15, 25, 35]
Объединенные и отранжированные:
Значение: 10 15 20 25 30 35
Ранг: 1 2 3 4 5 6
Группа: 1 2 1 2 1 2
R₁ = 1 + 3 + 5 = 9
R₂ = 2 + 4 + 6 = 12
U = 3*3 + 3(3+1)/2 - 9 = 9 + 6 - 9 = 6
Сравнение: t-тест vs Манна-Уитни
| Аспект | T-тест | Манна-Уитни |
|---|---|---|
| Тип | Параметрический | Непараметрический |
| Требует нормальности | ДА | НЕТ |
| Требует равных дисперсий | ДА | НЕТ |
| Тип данных | Количественные (непрерывные) | Ординальные, количественные |
| Что сравнивает | Средние | Медианы (или распределения) |
| Мощность | Выше (если условия выполнены) | Ниже, но более робустен |
| Выбросы | Чувствителен | Устойчив (использует ранги) |
| Размер выборки | Нужно n > 30 | Работает на малых выборках |
| P-value | На основе t-распределения | На основе U-распределения |
Практический пример: когда выбрать что
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
from scipy.stats import shapiro
# Пример 1: Нормальные данные
normal_group1 = np.random.normal(100, 15, 50) # μ=100, σ=15
normal_group2 = np.random.normal(110, 15, 50) # μ=110, σ=15
# Проверка нормальности (тест Шапиро-Уилка)
stat1, p1 = shapiro(normal_group1)
stat2, p2 = shapiro(normal_group2)
print(f"Нормальные данные - p1: {p1:.4f}, p2: {p2:.4f}")
if p1 > 0.05 and p2 > 0.05:
print("Данные нормальны → используй t-тест")
t_stat, t_p = stats.ttest_ind(normal_group1, normal_group2)
print(f"t-тест: t={t_stat:.4f}, p={t_p:.4f}")
else:
print("Данные не нормальны → используй Манна-Уитни")
# Пример 2: Ненормальные данные (с выбросами)
outlier_group1 = np.concatenate([np.random.normal(100, 10, 48), [500, 510]]) # два выброса
outlier_group2 = np.random.normal(110, 10, 50)
stat1, p1 = shapiro(outlier_group1)
stat2, p2 = shapiro(outlier_group2)
print(f"\nДанные с выбросами - p1: {p1:.6f}, p2: {p2:.4f}")
print(f"Средние: {np.mean(outlier_group1):.1f} vs {np.mean(outlier_group2):.1f}")
print(f"Медианы: {np.median(outlier_group1):.1f} vs {np.median(outlier_group2):.1f}")
# t-тест пострадает от выбросов
t_stat, t_p = stats.ttest_ind(outlier_group1, outlier_group2)
print(f"t-тест: t={t_stat:.4f}, p={t_p:.4f}")
# Манна-Уитни более робустен
u_stat, u_p = stats.mannwhitneyu(outlier_group1, outlier_group2)
print(f"Манна-Уитни: u={u_stat:.4f}, p={u_p:.4f}")
Варианты t-теста
1. Independent samples t-test
Для независимых групп (разные люди):
stats.ttest_ind(group1, group2)
2. Paired samples t-test
Для зависимых групп (один и тот же человек до и после):
before = np.array([10, 20, 30, 40, 50])
after = np.array([12, 22, 32, 42, 52])
stats.ttest_rel(before, after) # rel = related/paired
3. Welch's t-test
Для независимых групп с неравными дисперсиями:
stats.ttest_ind(group1, group2, equal_var=False) # Welch's t-test
Проверка предположений перед выбором теста
from scipy.stats import shapiro, levene
def choose_test(group1, group2):
# 1. Проверка нормальности (Shapiro-Wilk)
_, p_norm1 = shapiro(group1)
_, p_norm2 = shapiro(group2)
normal = p_norm1 > 0.05 and p_norm2 > 0.05
# 2. Проверка равности дисперсий (Levene's test)
_, p_var = levene(group1, group2)
equal_var = p_var > 0.05
print(f"Нормальность: {normal}, Равные дисперсии: {equal_var}")
if normal and equal_var:
print("→ Используй t-тест (Independent samples)")
t_stat, p_val = stats.ttest_ind(group1, group2)
elif normal and not equal_var:
print("→ Используй Welch's t-тест")
t_stat, p_val = stats.ttest_ind(group1, group2, equal_var=False)
else:
print("→ Используй Манна-Уитни (более робустен)")
t_stat, p_val = stats.mannwhitneyu(group1, group2)
return t_stat, p_val
Effect Size
P-value показывает значимость, но не величину эффекта. Используй Cohen's d:
def cohens_d(group1, group2):
n1, n2 = len(group1), len(group2)
var1, var2 = np.var(group1, ddof=1), np.var(group2, ddof=1)
pooled_std = np.sqrt(((n1-1)*var1 + (n2-1)*var2) / (n1+n2-2))
return (np.mean(group1) - np.mean(group2)) / pooled_std
effect = cohens_d(group1, group2)
print(f"Cohen's d: {effect:.3f}")
# Интерпретация: 0.2 (малый), 0.5 (средний), 0.8 (большой)
Практический совет для Data Scientist
- Всегда проверяй предположения перед выбором теста
- На маленьких выборках (n<30) предпочтитай Манна-Уитни
- С выбросами в данных используй Манна-Уитни
- На нормальных данных больших размеров t-тест имеет большую мощность
- Всегда репортируй effect size, не только p-value
- Визуализируй данные перед тестированием
import matplotlib.pyplot as plt
fig, axes = plt.subplots(1, 3, figsize=(12, 4))
# Box plot
axes[0].boxplot([group1, group2])
axes[0].set_title('Distribution')
# Histogram
axes[1].hist(group1, alpha=0.5, label='Group 1')
axes[1].hist(group2, alpha=0.5, label='Group 2')
axes[1].legend()
axes[1].set_title('Histograms')
# Q-Q plot (для проверки нормальности)
from scipy.stats import probplot
probplot(group1, dist="norm", plot=axes[2])
axes[2].set_title('Q-Q Plot (Group 1)')
plt.tight_layout()
plt.show()
Выбор между t-тестом и Манна-Уитни — это выбор между мощностью (t-тест при нормальности) и робустностью (Манна-Уитни при любых распределениях). Правильный выбор обеспечивает корректные статистические выводы.