Все материалы
Продуктовая аналитикаматериалсредний

Репрезентативность выборки: что это и как её проверить

Репрезентативная выборка — та, чей способ отбора не искажает ответ на ваш вопрос. Виды смещений, проверка на SQL и хи-квадратом, взвешивание и когда без репрезентативности можно обойтись.

КейсПрактика25 сентября 2026 г.10 мин

Команда запустила опрос о пользе отчётов прямо в разделе отчётов. Ответов много, вывод напрашивается: «37% пользователей делают экспорт, значит, он нужен больше чем каждому третьему». Но опрос видят только те, кто хотя бы раз создал отчёт. Можно ли переносить их ответы на всех пользователей? Это и есть вопрос о репрезентативности. Разберём, что она значит, какие бывают смещения, как проверить выборку на известных признаках с помощью SQL и хи-квадрата, как взвешивание исправляет часть перекоса и почему не исправляет остальное. Все числа — из учебной базы SQL-курса, где ответ заранее известен.

Что такое репрезентативная выборка

Репрезентативная выборка — это выборка, по которой можно без систематического сдвига оценить нужный показатель генеральной совокупности. Проще: способ отбора не связан с тем, что вы измеряете, настолько, чтобы исказить ответ.

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

Поэтому вопрос «репрезентативна ли выборка вообще» не имеет ответа. Рабочая формулировка звучит так: «можно ли по этой выборке оценить вот этот показатель для вот этой совокупности».

  • Репрезентативность зависит от того, как отбирали, а не от того, сколько отобрали.
  • Проверить её напрямую нельзя: можно только сравнить выборку с совокупностью по признакам, которые известны для всех.
  • Совпадение по известным признакам — необходимое, но не достаточное условие.
  • Взвешивание исправляет перекос по тем признакам, по которым взвешивали, и по всему, что с ними связано. Остальное остаётся.

Почему большая выборка не гарантирует репрезентативность

Рост выборки уменьшает случайную ошибку, но не трогает систематическую. Если отбор перекошен, миллион ответов даст очень узкий интервал вокруг неверного числа.

Классический пример — выборы в США 1936 года. Журнал Literary Digest разослал около 10 миллионов анкет, получил примерно 2,4 миллиона ответов и предсказал победу Альфа Лэндона; Рузвельт выиграл с большим отрывом. Адреса брали в основном из списков подписчиков, телефонных книг и регистраций автомобилей, а отвечали охотнее противники действующего президента.

На учебной базе эффект виден так же ясно. Среди 1 775 пользователей, создавших хотя бы один отчёт, экспорт делали 37,01%. Во всей базе из 4 613 человек — 21,42%. Опрос в разделе отчётов почти вдвое завысил бы долю пользователей экспорта, и собрать ещё тысячу ответов в том же месте ничего бы не изменило.

Какие бывают смещения выборки

Смещения различаются тем, на каком шаге люди выпадают из выборки. Название помогает понять, где искать причину и что с ней можно сделать.

Основные виды смещения и как они выглядят в продукте
СмещениеЧто происходитПример в продукте
Ошибка отбора (selection bias)Правило отбора связано с измеряемым показателемОпрос в разделе отчётов про использование экспорта
Неполный охват (coverage)Часть совокупности вообще не может попасть в выборкуОпрос в вебе, а треть аудитории пользуется только приложением
Неответы (non-response)Приглашены все, но ответили не все, и ответившие отличаютсяПисьмо с опросом открывают в основном активные клиенты
Самоотбор (self-selection)Человек сам решает, участвовать лиNPS заполняют самые вовлечённые и самые недовольные
Ошибка выжившего (survivorship)В данных остались только те, кто «дожил» до момента измеренияАнализ удовлетворённости по текущим клиентам без ушедших
Ошибка выжившего в отчётах

Если изучать удовлетворённость только по текущим клиентам, недовольные, которые уже ушли, в расчёт не попадут. Оценка выйдет выше реальной, а причины оттока останутся невидимыми.

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

Прямой проверки нет: ответов тех, кто в выборку не попал, вы не знаете. Косвенная проверка — сравнить выборку с совокупностью по признакам, которые известны для всех: канал привлечения, устройство, страна, месяц регистрации, тариф. Если выборка расходится с базой по ним, это сигнал, что она может расходиться и по тому, что вы спрашиваете.

Сделаем это для «респондентов» — 1 775 пользователей, у которых есть событие report_created. Запрос собирает доли каналов в базе и среди респондентов одной таблицей; для месяца регистрации и устройства меняется только поле группировки.

Перекос заметен сразу. Пользователи из paid_search составляют 22,0% базы и только 13,4% респондентов. Органика и рефералы, наоборот, представлены сильнее. По месяцу регистрации и устройству расхождения мягче, около 3 п.п.: июньских пользователей и десктопа среди респондентов чуть больше.

Все пользователи против создавших отчёт: учебная база SQL-курса, DuckDB
ПризнакЗначениеВо всей базе (4 613)Среди респондентов (1 775)Разница, п.п.
Каналorganic37,9%43,4%+5,5
Каналpaid_search22,0%13,4%−8,6
Каналpartner17,6%15,8%−1,8
Каналreferral22,5%27,4%+4,9
Месяц регистрациииюнь22,6%25,6%+3,0
Месяц регистрациииюль36,3%34,5%−1,8
Месяц регистрацииавгуст41,1%39,9%−1,2
Устройствоdesktop51,7%54,7%+3,0
Устройствоmobile48,3%45,3%−3,0
Доля каналов привлечения во всей базе и среди создавших отчёт, %

Учебная база SQL-курса: 4 613 пользователей, из них 1 775 создали хотя бы один отчёт.

Вся базаСоздали отчёт
Доли каналов во всей базе и среди создавших отчёт
with respondents as (
  select distinct user_id
  from events
  where event_name = 'report_created'
)
select u.channel,
       count(*) as population,
       count(r.user_id) as respondents,
       round(100.0 * count(*) / sum(count(*)) over (), 1) as population_pct,
       round(100.0 * count(r.user_id) / sum(count(r.user_id)) over (), 1) as respondents_pct
from users u
left join respondents r on r.user_id = u.user_id
group by u.channel
order by u.channel;

Как отличить перекос от случайного расхождения: хи-квадрат

Даже честная случайная выборка не совпадёт с базой до десятой доли процента. Чтобы понять, укладывается ли расхождение в случайный разброс, подходит критерий согласия хи-квадрат: он сравнивает наблюдаемые числа в выборке с теми, что ожидались бы при долях как в совокупности. В SciPy это scipy.stats.chisquare.

Для респондентов по каналу статистика равна 96,1, p ≈ 1,1·10⁻²⁰: такой перекос случайностью не объяснить. По месяцу регистрации p = 0,0098, по устройству p = 0,011 — расхождения небольшие, но на 1 775 наблюдениях уже заметные.

Для контраста проверим десять систематических выборок user_id % 10 = 0 … 9, примерно по 461 человеку. Восемь проходят проверку, две получают p = 0,029 и 0,041. При пороге 0,05 честная выборка ошибочно «проваливается» примерно в одном случае из двадцати, так что два из десяти — неудача, но не аномалия. Отсюда практическое правило: смотрите на размер расхождений в п.п., а не только на p. На большой выборке значимым станет и расхождение в полпроцента, которое ни на что не влияет.

Тот же тест лежит в основе проверки SRM в A/B-тестах: там сравнивают фактическое деление трафика между вариантами с запланированным.

pythonКритерий согласия хи-квадрат: выборка против известных долей совокупности
import numpy as np
from scipy.stats import chisquare

def check(population, observed):
    population, observed = np.array(population), np.array(observed)
    expected = population / population.sum() * observed.sum()
    return chisquare(observed, f_exp=expected)

# Кто создал хотя бы один отчёт (1775 человек) против всех 4613
checks = {
    "канал":  ([1747, 1015, 814, 1037], [770, 238, 281, 486]),  # organic, paid_search, partner, referral
    "месяц":  ([1042, 1676, 1895], [454, 612, 709]),            # июнь, июль, август
    "устройство": ([2384, 2229], [971, 804]),                   # desktop, mobile
}
for name, (population, observed) in checks.items():
    stat, p = check(population, observed)
    print(f"{name}: хи-квадрат = {stat:.1f}, p = {p:.2g}")

# Десять систематических выборок user_id % 10 = 0 … 9, распределение по каналам
channels = [1747, 1015, 814, 1037]
systematic = [
    [182, 99, 90, 90], [173, 99, 82, 108], [169, 104, 103, 86],
    [192, 114, 64, 92], [174, 98, 77, 112], [164, 111, 74, 112],
    [167, 100, 80, 114], [173, 84, 80, 124], [166, 110, 80, 105],
    [187, 96, 84, 94],
]
for k, observed in enumerate(systematic):
    stat, p = check(channels, observed)
    print(f"user_id % 10 = {k}: хи-квадрат = {stat:.2f}, p = {p:.3f}")

# канал: хи-квадрат = 96.1, p = 1.1e-20
# месяц: хи-квадрат = 9.3, p = 0.0098
# устройство: хи-квадрат = 6.5, p = 0.011
# user_id % 10 = 0: хи-квадрат = 3.09, p = 0.378
# user_id % 10 = 1: хи-квадрат = 0.26, p = 0.967
# user_id % 10 = 2: хи-квадрат = 8.99, p = 0.029
# user_id % 10 = 3: хи-квадрат = 8.28, p = 0.041
# user_id % 10 = 4: хи-квадрат = 1.03, p = 0.795
# user_id % 10 = 5: хи-квадрат = 2.88, p = 0.410
# user_id % 10 = 6: хи-квадрат = 1.41, p = 0.703
# user_id % 10 = 7: хи-квадрат = 7.04, p = 0.071
# user_id % 10 = 8: хи-квадрат = 1.19, p = 0.756
# user_id % 10 = 9: хи-квадрат = 2.16, p = 0.541

Как сделать выборку репрезентативной: стратификация, квоты, взвешивание

Лучше всего исправлять перекос до сбора данных. Стратифицированная выборка делит совокупность на группы — например, по каналу — и отбирает из каждой случайно, в нужной пропорции. Квоты работают похоже, но внутри группы отбор уже не случайный: «набрать 220 ответов из paid_search» можно и за счёт самых активных. Квоты выравнивают состав, но не гарантируют честность внутри квоты.

Если данные уже собраны, остаётся пост-стратификация: взвешивание ответов так, чтобы доли групп совпали с совокупностью. Вес группы равен её доле в базе, делённой на долю в выборке. У paid_search вес 22,0% / 13,4% ≈ 1,64: каждый ответ из этого канала считается за 1,64 ответа. У органики вес 0,873, у рефералов 0,821, у партнёров 1,115.

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

Доля платящих среди респондентов — 21,24%, во всей базе 19,77%. После взвешивания по каналу получаем 19,99%: почти вся ошибка ушла. Так вышло потому, что внутри каждого канала респонденты платят примерно так же часто, как все: в органике 23,25% против 23,47%, в рефералах 24,69% против 26,81%. Перекос по оплатам объяснялся составом каналов.

С экспортом не так. Среди респондентов его делали 37,01%, после взвешивания — 36,96%, а правда — 21,42%. Внутри каждого канала респонденты делают экспорт намного чаще остальных: в paid_search 35,71% против 12,71% по каналу в целом. Отбор шёл по вовлечённости, а не по каналу, и вес по каналу её не видит.

Пост-стратификация
вес группы = доля в совокупности / доля в выборке p̂_взв = Σ (доля группы в совокупности · p̂ группы)

Взвешивание работает, если внутри каждой группы ответившие похожи на неответивших по изучаемому признаку.

Оценка по респондентам до и после взвешивания по каналу и правда по всей базе, %

Для оплат взвешивание почти убирает ошибку, для экспорта — нет: отбор связан с вовлечённостью, а не с каналом.

Среди респондентовПосле взвешиванияВся база
pythonВзвешивание ответов по каналу и сравнение с известной правдой
# Пост-стратификация по каналу: вес = доля канала в базе / доля в выборке
channels   = ["organic", "paid_search", "partner", "referral"]
population = [1747, 1015, 814, 1037]   # все пользователи
sample     = [770, 238, 281, 486]      # создали отчёт
payers     = [179, 25, 53, 120]        # из них платили
exporters  = [288, 85, 109, 175]       # из них делали экспорт

N, n = sum(population), sum(sample)
for ch, P_c, n_c in zip(channels, population, sample):
    print(f"{ch:12} вес = {(P_c / N) / (n_c / n):.3f}")

def raw_and_weighted(hits):
    raw = sum(hits) / n
    weighted = sum(P_c / N * h / n_c for P_c, h, n_c in zip(population, hits, sample))
    return raw, weighted

for name, hits, truth in [("платили", payers, 912 / N), ("экспорт", exporters, 988 / N)]:
    raw, w = raw_and_weighted(hits)
    print(f"{name}: в выборке {raw:.2%}, после взвешивания {w:.2%}, во всей базе {truth:.2%}")

# organic      вес = 0.873
# paid_search  вес = 1.641
# partner      вес = 1.115
# referral     вес = 0.821
# платили: в выборке 21.24%, после взвешивания 19.99%, во всей базе 19.77%
# экспорт: в выборке 37.01%, после взвешивания 36.96%, во всей базе 21.42%

Почему совпадение по известным признакам ничего не доказывает

Пример с экспортом показывает границу метода. Можно взвесить выборку так, что каналы, месяцы и устройства совпадут с базой до десятой доли процента, и всё равно ошибиться вдвое. Сравнение по известным признакам ловит перекос, но не подтверждает его отсутствие.

Практический вывод — думать о механизме. Спросите: почему эти люди оказались в выборке и может ли эта причина быть связана с ответом? Опрос в разделе отчётов отбирает тех, кто уже пользуется отчётами. Значит, любой вопрос про использование функций будет завышен, какие бы веса вы ни подобрали.

Если признак, от которого зависит отбор, есть в данных, взвешивайте по нему. Здесь это могла бы быть активность: число событий за первую неделю или факт создания отчёта. Если такого признака нет, честнее переформулировать вопрос: «среди пользователей отчётов 37% делают экспорт» — верное и полезное утверждение.

Когда нерепрезентативная выборка — не проблема

В A/B-тесте участники почти никогда не репрезентативны для всей аудитории: туда попадает трафик конкретных двух недель, конкретного сезона, часто одной платформы. Но сравнение вариантов всё равно честное, потому что внутри теста пользователей распределяют между группами случайно. Рандомизация даёт внутреннюю валидность: разница между A и B вызвана изменением, а не составом групп.

Вопрос о переносе результата — внешняя валидность — остаётся отдельным. Эффект, измеренный в августе на новых пользователях из России, может не повториться в декабре или в другой стране. Поэтому в описании теста фиксируют, на ком он шёл, а основную метрику и ограничители выбирают до запуска.

Второй случай — качественные исследования. Если цель интервью — найти, где пользователи спотыкаются, а не измерить, как часто это случается, нужны разнообразные собеседники, а не пропорциональные. Проблемы стоит искать у тех, кто с ними сталкивается, а доли — считать на данных о поведении.

Чек-лист перед тем, как переносить выводы на всех

Короткий список вопросов, которые стоит задать до того, как число из опроса или сегмента попадёт в презентацию.

  • О какой совокупности вывод? Назовите её одной фразой.
  • Кто мог попасть в выборку, а кто не мог в принципе?
  • Кто из приглашённых ответил и чем ответившие могут отличаться?
  • Совпадает ли выборка с базой по каналу, устройству, стране, возрасту аккаунта? Смотрите на разницу в п.п.
  • Связан ли механизм отбора с измеряемым показателем? Если да, взвешивание не поможет.
  • Если взвешивали — сравните оценку до и после. Сильный сдвиг говорит о большом перекосе, а значит, и о риске по невидимым признакам.

Что почитать дальше и где потренироваться

Базовые понятия — генеральная совокупность, выборка, параметр и погрешность — разобраны в отдельном материале. Повторить запросы из статьи и проверить свои выборки можно в песочнице SQL-курса: там та же учебная база.

Продолжить чтение
Вся библиотека
Продуктовая аналитика26 июля 2026 г.20 мин

Какой статистический метод выбрать: t-тест, хи-квадрат, бутстреп, Байес или регрессия

Навигатор по методам для аналитика: когда сравнивать средние t-тестом, доли и категории хи-квадратом, где нужен бутстреп, байесовский апдейт, линейная или логистическая регрессия — и что каждый из них не скажет.

Читать материал
Продуктовая аналитика2 августа 2026 г.23 мин

Почему метрика обманывает: состав, календарь, база и декомпозиция

Как честно посчитанная метрика приводит к неверному выводу: парадокс Симпсона, регрессия к среднему, сезонность, аномалии и декомпозиция роста по вкладам сегментов.

Читать материал