Чему равно p-value для выбросов
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Чему равно p-value для выбросов
Это хороший вопрос, который проверяет понимание связи между статистикой и определением выбросов. Ответ: нет универсального значения p-value для выбросов, оно зависит от конкретного статистического теста, который вы используете.
Что такое p-value?
P-value — это вероятность наблюдать такое же или более экстремальное значение при условии, что нулевая гипотеза верна:
p-value = P(получить такие данные | H0 верна)
Типичные пороги:
- p-value < 0.05 → отклоняем H0 (это выброс/аномалия)
- p-value >= 0.05 → не отклоняем H0 (это нормально)
Примеры вычисления p-value для выбросов
1. Z-тест (для нормального распределения)
import numpy as np
from scipy.stats import norm
data = np.array([1, 2, 3, 4, 5, 100]) # 100 — явный выброс
mean = np.mean(data[:-1])
std = np.std(data[:-1], ddof=1)
# Z-score для последней точки
z_score = (100 - mean) / std
# P-value (двусторонний тест)
p_value = 2 * (1 - norm.cdf(abs(z_score)))
print(f"Z-score: {z_score:.2f}")
print(f"P-value: {p_value:.4e}") # Очень маленькое значение
# Результат: p-value << 0.05 → 100 — выброс
2. Тест Grubbs (для нормального распределения)
Тест Grubbs специально разработан для обнаружения одного выброса:
from scipy.stats import t
def grubbs_test(data, alpha=0.05):
"""Тест Grubbs для выбросов"""
n = len(data)
mean = np.mean(data)
std = np.std(data, ddof=1)
# Самая далёкая от среднего точка
z_scores = np.abs((data - mean) / std)
max_z_idx = np.argmax(z_scores)
max_z = z_scores[max_z_idx]
# Статистика Grubbs
t_stat = (n - 1) / np.sqrt(n) * np.sqrt(max_z**2 / (n - 2 + max_z**2))
# P-value из t-распределения
p_value = 2 * (1 - t.cdf(t_stat, n - 2))
return t_stat, p_value, max_z_idx
data = np.array([1, 2, 3, 4, 5, 100])
t_stat, p_val, idx = grubbs_test(data)
print(f"Grubbs test: p-value = {p_val:.4e}")
print(f"Выброс на индексе {idx}: {data[idx]}")
3. Modified Z-Score (более робастный)
Использует медиану и MAD (Median Absolute Deviation) вместо среднего и стд:
def modified_z_score(data, threshold=3.5):
"""Modified Z-score — более робастен к выбросам"""
median = np.median(data)
mad = np.median(np.abs(data - median))
if mad == 0:
modified_z = np.zeros_like(data, dtype=float)
else:
modified_z = 0.6745 * (data - median) / mad
outlier_indices = np.where(np.abs(modified_z) > threshold)[0]
p_values = 2 * (1 - norm.cdf(np.abs(modified_z[outlier_indices])))
return outlier_indices, p_values
data = np.array([1, 2, 3, 4, 5, 100])
idx, p_vals = modified_z_score(data)
print(f"Выбросы с p-values: {list(zip(data[idx], p_vals))}")
4. Тест Rosner (для нескольких выбросов)
from scipy.stats import t
def rosner_test(data, k=2, alpha=0.05):
"""Rosner test для обнаружения до k выбросов"""
outliers = []
data_copy = data.copy().astype(float)
n = len(data_copy)
for i in range(k):
mean = np.mean(data_copy)
std = np.std(data_copy, ddof=1)
z_scores = np.abs((data_copy - mean) / std)
max_idx = np.argmax(z_scores)
max_z = z_scores[max_idx]
# Rosner статистика
R = (n - i) / np.sqrt(n - i - 1) * np.sqrt(max_z**2 / (n - i - 2 + max_z**2))
# Критическое значение
t_crit = t.ppf(1 - alpha / (2 * (n - i)), n - i - 2)
if R > t_crit:
outliers.append((data[max_idx], R))
data_copy = np.delete(data_copy, max_idx)
return outliers
data = np.array([1, 2, 3, 4, 5, 100, 105])
outliers = rosner_test(data, k=2)
print(f"Найденные выбросы: {outliers}")
Практическое применение
from scipy.stats import zscore
def detect_outliers_by_pvalue(data, p_threshold=0.05):
"""Обнаружить выбросы, используя Z-тест"""
mean = np.mean(data)
std = np.std(data, ddof=1)
z_scores = (data - mean) / std
p_values = 2 * (1 - norm.cdf(np.abs(z_scores)))
outlier_mask = p_values < p_threshold
return outlier_mask, p_values
data = np.array([1, 2, 3, 4, 5, 100, 2.5, 3.5])
outliers, p_values = detect_outliers_by_pvalue(data, p_threshold=0.05)
print("Обнаружение выбросов (p-value < 0.05):")
for val, p_val, is_outlier in zip(data, p_values, outliers):
status = "ВЫБРОС" if is_outlier else "нормально"
print(f" {val:7.1f}: p-value = {p_val:.4e} [{status}]")
Связь между Z-score и p-value
Z-score | p-value (2-sided)
--------|------------------
1.96 | 0.0500 (5%)
2.58 | 0.0100 (1%)
3.00 | 0.0027 (0.3%)
3.29 | 0.0010 (0.1%)
На практике часто используют:
- Z-score > 3 (соответствует p-value ≈ 0.003)
- Z-score > 2.5 (соответствует p-value ≈ 0.012)
- p-value < 0.05 (95% уверенность)
- p-value < 0.01 (99% уверенность)
Выбор метода обнаружения выбросов
| Метод | P-value базис | Когда использовать | Преимущества |
|---|---|---|---|
| Z-score | Нормальное | Нормальные данные | Простой, быстрый |
| Grubbs | t-тест | Один выброс | Специализированный |
| Rosner | t-тест | Несколько выбросов | Лучше для множественных |
| Modified Z | Норм. + MAD | Асимметричные данные | Робастен к выбросам |
| IQR | Не требует | Быстро без расчётов | Простой, часто используется |
Ключевые выводы
-
Нет универсального p-value для выбросов — зависит от теста
-
Общие пороги:
- p-value < 0.05 → вероятно выброс (95% уверенность)
- p-value < 0.01 → скорее выброс (99% уверенность)
-
P-value показывает: Вероятность наблюдать такое значение при условии, что это нормальное число (не выброс)
-
На практике часто используют:
- Z-score > 3 (простой и распространённый подход)
- IQR метод (более робастен)
- Грубс-тест (если предполагаете нормальность)
-
Не путайте:
- P-value — это вероятность при H0, а не вероятность быть выбросом
- Разные методы могут давать разные p-values для одних и тех же данных