Как оценить репрезентативность выборки?

«Как оценить репрезентативность выборки?» — вопрос из категории Статистика и теория вероятностей, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Оценка репрезентативности — это проверка, насколько хорошо выборка отражает генеральную совокупность. Я делаю это по нескольким направлениям.

1. Сравнение ключевых статистик Сравниваю основные метрики (среднее, медиану, стандартное отклонение) между выборкой и популяцией (или между обучающей и тестовой выборками).

import pandas as pd
import numpy as np

# Допустим, у нас есть данные о популяции и выборке
print("Сравнение средних:")
for col in ['age', 'income', 'score']:
    pop_mean = population[col].mean()
    samp_mean = sample[col].mean()
    diff_pct = abs((pop_mean - samp_mean) / pop_mean) * 100
    print(f"  {col}: Популяция={pop_mean:.2f}, Выборка={samp_mean:.2f}, Отклонение={diff_pct:.1f}%")

2. Проверка распределений с помощью визуализации и статистических тестов

  • Визуализация: Строю гистограммы или ECDF (Empirical Cumulative Distribution Function) для наглядного сравнения.
import matplotlib.pyplot as plt
import seaborn as sns

fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# Гистограммы
sns.histplot(population['age'], label='Population', kde=True, ax=axes[0], color='blue', alpha=0.5)
sns.histplot(sample['age'], label='Sample', kde=True, ax=axes[0], color='orange', alpha=0.5)
axes[0].legend()
axes[0].set_title('Distribution of Age')

# Boxplot для сравнения
sns.boxplot(data=[population['income'], sample['income']], ax=axes[1])
axes[1].set_xticklabels(['Population', 'Sample'])
axes[1].set_title('Comparison of Income')
plt.tight_layout()
  • Статистические тесты:
    • t-тест (для средних) или Mann-Whitney U test (для медиан) — проверяют, различаются ли центральные тенденции.
    • Тест Колмогорова-Смирнова (KS-test) — проверяет, различаются ли распределения в целом.
from scipy import stats

# KS-тест для возраста
ks_stat, ks_pvalue = stats.ks_2samp(population['age'], sample['age'])
print(f"KS-test p-value for age: {ks_pvalue:.4f}")
# p-value > 0.05 обычно говорит об отсутствии значимых различий в распределениях.

3. Проверка пропорций категориальных признаков (Стратификация) Убеждаюсь, что в выборке сохранены пропорции ключевых категорий (например, пол, регион, тариф).

# Сравнение долей по полу
pop_gender_ratio = population['gender'].value_counts(normalize=True)
samp_gender_ratio = sample['gender'].value_counts(normalize=True)
comparison = pd.DataFrame({'Population': pop_gender_ratio, 'Sample': samp_gender_ratio})
print(comparison)

4. Использование Bootstrap для оценки устойчивости Генерирую множество псевдовыборок из исходной выборки (bootstrap) и смотрю, насколько стабильны оцениваемые статистики (например, среднее). Большой разброс bootstrap-оценок может указывать на проблему с репрезентативностью.

Вывод: Я считаю выборку репрезентативной, если:

  • Ключевые статистики (средние, медианы) отличаются незначительно (например, <5%).
  • Статистические тесты (t-test, KS-test) не показывают значимых различий (p-value > 0.05).
  • Визуально распределения выглядят схоже.
  • Пропорции важных категориальных признаков сохранены.