Аналитика данных Сначала вопрос: какое решение изменится от ответа
0%

Сначала вопрос: какое решение изменится от ответа

Сначала вопрос: какое решение изменится от ответа

Продакт написал в чат: «посмотри, пожалуйста, что там с оттоком». Аналитик потратил три дня, собрал витрину, вывел четырнадцать графиков на дашборд и отправил ссылку. Через полгода в логах BI-системы у этого дашборда было одиннадцать открытий, девять из них — самим аналитиком.

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

Есть и вторая, более опасная разновидность того же провала. Цифру всё-таки посмотрели, и по ней приняли решение. Отток мобильных пользователей — 12 %, веб — 7 %, вывод: «мобильный онбординг плохой, переделываем». Через квартал переделанный онбординг не изменил ничего, потому что в мобильном приложении просто больше доля пользователей из платного трафика, а платный трафик уходит быстрее везде. Данные не врали. Врал вывод, который они не выдерживали.

Джон Тьюки, статистик, придумавший ящик с усами и термин «разведочный анализ данных», сформулировал это в 1962 году в статье «The Future of Data Analysis»: гораздо лучше приблизительный ответ на правильный вопрос, который часто расплывчат, чем точный ответ на неправильный вопрос, который всегда можно сделать чётким.

Эта глава — про то, как получить правильный вопрос. Не про мотивационное «думайте о бизнесе», а про конкретную процедуру: какие поля должны быть заполнены, какой порог назван, что проверить до того, как открыть редактор SQL, и в какой момент честный ответ звучит «эти данные на такой вопрос не отвечают».

Тест на бесполезный вопрос

Возьмите вопрос, на который собираетесь потратить время, и заполните две строки:

  • если ответ окажется A, мы сделаем ______;
  • если ответ окажется B, мы сделаем ______.

Если в обеих строках написано одно и то же — считать не нужно. Ответ не изменит поведение, значит, его ценность равна нулю независимо от того, насколько красив будет график.

Это не риторический приём, а рабочая проверка, и она отсекает больше половины входящих запросов. Формально она опирается на понятие ценности информации: информация имеет ценность ровно настолько, насколько она способна изменить выбор действия. Дуглас Хаббард в «How to Measure Anything» строит на этом всю методику: сначала измеряется, какое решение стоит на кону и сколько стоит ошибка в нём, и только потом — сама величина.

Три типичных ответа на тест и что с ними делать.

  1. «Просто хочу понимать, как у нас дела». Это не решение, а привычка. Иногда законная — мониторинг существует, чтобы заметить аномалию. Тогда вопрос переформулируется в пороговый: «при каком значении мы забьём тревогу и что сделаем». Без порога получится не мониторинг, а обои.
  2. «Решение уже принято, нужна цифра для презентации». Честный запрос, если назвать вещи своими именами. Опасен тем, что аналитик начинает подбирать разрез, где цифра выглядит нужным образом, — про этот механизм и его последствия подробно в главе про проверку гипотез.
  3. «От этого зависит, вкладываем ли мы спринт в X». Годный запрос. С него начинается работа.

Ответ → действие, записанное заранее

Развитие теста — маленькая таблица, которую заполняют до запуска запроса. Заказчик заранее фиксирует, что сделает при каждом исходе.

Ответ Действие Кто делает
Удержание D7 у мобильных ниже веба более чем на 5 п.п. Спринт команды роста в мобильный онбординг Продакт мобильного направления
Разница в пределах 5 п.п. Не трогаем онбординг, идём в блок оплаты Тот же
Данных не хватает, чтобы отличить Ставим счётчики и возвращаемся через две недели Аналитик

Ценность таблицы в третьей строке. Она легализует ответ «не знаю» как валидный исход. Без неё аналитик под социальным давлением выдаст точечную оценку без интервала, а заказчик прочитает её как факт. Предварительная фиксация действий — это тот же приём, что предрегистрация в науке, и работает он по той же причине: убирает свободу интерпретации задним числом.

Пять минут перед SQL

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

Обратите внимание на ветку F. Это единственный шаг, который требует технического знания, и именно он чаще всего пропускается. Заказчик спрашивает «почему упали продажи» — вопрос осмысленный, решение от ответа зависит, порог назвать можно. А способ сбора данных на «почему» не отвечает в принципе: в логах нет мира, в котором изменение не произошло. Об этом — глава про причинность, но отсекать такие вопросы нужно здесь, до того как потрачена неделя.

Четыре вида вопросов и почему их путают

Различие не академическое: от вида вопроса зависит, какой способ сбора данных вообще годится.

Вид Формулировка Что нужно от данных Типичная подмена
Описательный Сколько, каких, как распределено Полнота и корректный знаменатель Среднее вместо распределения
Диагностический Что изменилось и где именно Разрезы, сопоставимые периоды «Что изменилось» выдают за «почему»
Причинный Что произойдёт, если мы сделаем X Вариация, независимая от исхода Корреляция в наблюдательных данных
Прогнозный Какое значение будет в июле Устойчивая во времени структура Экстраполяция тренда через слом

Практический вывод один: вопрос «почему» почти никогда нельзя закрыть тем же способом сбора, которым закрывают «сколько». Логи продукта отвечают на «сколько» и частично на «что изменилось». На «почему» отвечает либо эксперимент, либо разговор с людьми (см. выявление требований), либо квазиэкспериментальный дизайн — и всё это стоит существенно дороже.

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

Лестница от вопроса к цифре

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

Лестница сужения от целевой величины к цифре в отчёте

Разберём на конкретном вопросе: «какая доля наших клиентов сталкивается со сбоем оплаты».

  • Уровень 1, целевая величина. Все клиенты, у которых оплата не проходит. Именно про них хочет знать заказчик.
  • Уровень 2. В телеметрию попадают только те, у кого исполняется наш код. Отваливаются старые версии приложения, пользователи с блокировщиками, корпоративные сети с урезанным трафиком. Отбор неслучайный: у старых версий сбоев оплаты, скорее всего, больше.
  • Уровень 3. Счётчик стоит на экране оплаты. Тот, кто не дошёл до экрана из-за подвисшей корзины, в знаменателе не окажется вовсе.
  • Уровень 4. Событие должно доехать до сервера. Клиент, у которого приложение упало в момент оплаты, не пришлёт событие об ошибке — то есть самый тяжёлый случай систематически невидим.
  • Уровень 5. Фильтры запроса: окно дат обрезает начатые в конце периода попытки, дедупликация схлопывает ретраи, внутренние аккаунты исключены.
  • Уровень 6. Одно число: 3,7 %.

Вывод «у 3,7 % клиентов не проходит оплата» — это перенос утверждения с уровня 6 на уровень 1 без всяких оснований. Корректная формулировка: «среди сессий, дошедших до экрана оплаты и приславших телеметрию, доля с ошибкой — 3,7 %; истинная доля по всем клиентам почти наверняка выше, и насколько — из этих данных не установить».

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

Порог решения: сколько точности вам действительно нужно

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

Пусть удержание D7 в когорте измерено как 40 % на выборке в 400 пользователей. Точечная оценка бесполезна сама по себе: важно, отличается ли она от порога. Доверительный интервал Вальда для доли:

$$\hat p \pm z_{1-\alpha/2}\sqrt{\frac{\hat p\,(1-\hat p)}{n}}$$

Подставляем: стандартная ошибка равна $\sqrt{0{,}4 \cdot 0{,}6 / 400} = \sqrt{0{,}0006} \approx 0{,}0245$, полуширина при $z = 1{,}96$ — примерно 4,8 п.п., интервал — примерно от 35,2 % до 44,8 %.

Дальше всё зависит от порога, и только от него:

  • порог 30 % — интервал целиком выше, решение принимается уверенно;
  • порог 35 % — интервал почти касается порога, решение формально проходит, но запас нулевой;
  • порог 38 % — интервал накрывает порог, данные не отличают «выше» от «ниже», и честный ответ здесь «пока не знаю».

Нужный размер выборки выводится из требуемой полуширины $\varepsilon$, а она — из расстояния до порога:

$$n \ge \frac{z^2\,\hat p\,(1-\hat p)}{\varepsilon^2}$$

Чтобы отличить 40 % от порога 38 %, нужна полуширина не больше 2 п.п.: $n \ge 1{,}96^2 \cdot 0{,}24 / 0{,}02^2 \approx 2305$. То есть вместо 400 наблюдений нужно примерно 2300 — и об этом лучше узнать до, а не после того, как отчёт ушёл заказчику.

Тот же расчёт на Python, в форме, которую удобно вставлять в блокнот:

from math import sqrt, ceil
from statistics import NormalDist

Z95 = NormalDist().inv_cdf(0.975)  # 1.959963...


def wald_interval(k: int, n: int, z: float = Z95) -> tuple[float, float]:
    """Доверительный интервал Вальда для доли. Годится при k >= 10 и n - k >= 10."""
    p = k / n
    half = z * sqrt(p * (1 - p) / n)
    return p - half, p + half


def verdict(k: int, n: int, threshold: float) -> str:
    """Ответ в терминах решения, а не в терминах цифры."""
    lo, hi = wald_interval(k, n)
    if lo > threshold:
        return f"выше порога (интервал {lo:.3f}..{hi:.3f})"
    if hi < threshold:
        return f"ниже порога (интервал {lo:.3f}..{hi:.3f})"
    need = ceil(Z95 ** 2 * (k / n) * (1 - k / n) / (k / n - threshold) ** 2)
    return f"не различаем: интервал {lo:.3f}..{hi:.3f} накрывает {threshold}; нужно n ≈ {need}"


print(verdict(160, 400, 0.30))  # выше порога (интервал 0.352..0.448)
print(verdict(160, 400, 0.38))  # не различаем: ... нужно n ≈ 2305

Сложность здесь никакая — $O(1)$ по времени и памяти; ценность в том, что функция возвращает не число, а формулировку в терминах решения. Аналитик, у которого ответ выглядит так, физически не может отдать голую точечную оценку.

Интервал Вальда при малых k заметно врёт (при k = 0 он вырождается в нулевую ширину), поэтому в проде обычно берут интервал Уилсона:

$$\tilde p = \frac{\hat p + \dfrac{z^2}{2n}}{1 + \dfrac{z^2}{n}},\qquad \text{полуширина} = \frac{z}{1 + \dfrac{z^2}{n}}\sqrt{\frac{\hat p\,(1-\hat p)}{n} + \frac{z^2}{4n^2}}$$

Сравнение методов и границы применимости — в главе про неопределённость и в обзоре на Wikipedia: Binomial proportion confidence interval. Аппарат вероятностей, на который всё это опирается, разобран в математике.

Цена ответа: вопрос стоимостью в три недели

У каждого вопроса есть цена, и её нужно назвать заказчику до начала работы. Для эксперимента цена измеряется не в часах аналитика, а в трафике и календаре.

Размер одной группы для двусторонней проверки разности двух долей при заданной мощности:

$$n_{\text{на группу}} \ge \frac{\left(z_{1-\alpha/2} + z_{1-\beta}\right)^2 \left\lbrack p_1(1-p_1) + p_2(1-p_2) \right\rbrack}{(p_1 - p_2)^2}$$

def n_per_arm(p1: float, mde_abs: float, alpha: float = 0.05, power: float = 0.80) -> int:
    """Сколько наблюдений нужно в КАЖДОЙ группе, чтобы поймать эффект размера mde_abs."""
    p2 = p1 + mde_abs
    z_a = NormalDist().inv_cdf(1 - alpha / 2)  # 1.96 при alpha = 0.05
    z_b = NormalDist().inv_cdf(power)          # 0.84 при мощности 0.80
    var = p1 * (1 - p1) + p2 * (1 - p2)
    return ceil((z_a + z_b) ** 2 * var / mde_abs ** 2)


print(n_per_arm(0.10, 0.01))   # 14749 — поймать рост конверсии с 10 % до 11 %
print(n_per_arm(0.10, 0.02))   # 3839  — рост с 10 % до 12 %

Читается это так: чтобы отличить конверсию 11 % от 10 %, нужно около 14 750 пользователей в каждой группе, то есть примерно 29 500 всего. При потоке в 1000 попыток оплаты в день — месяц эксперимента. Уменьшение искомого эффекта вдвое учетверяет требуемую выборку, потому что $n$ обратно пропорционально квадрату эффекта.

Отсюда следует неприятный, но полезный вывод: вопрос «даст ли эта кнопка плюс полпроцента к конверсии» для большинства продуктов не имеет ответа. Не потому что кнопка не работает, а потому что трафика не хватит никогда. Правильная реакция — не запускать тест на три месяца, а сменить вопрос: искать эффекты, которые ваш поток данных способен различить. Механика экспериментов, мощность и подглядывание разобраны в главе про A/B-тесты; продуктовая сторона — в MVP и экспериментах.

Что брать в работу

Два измерения — влияние на решение и цена ответа — дают простую приоритизацию входящей очереди.

Квадрант 4 — самый коварный. Там живут запросы, которые выглядят серьёзной аналитической работой, съедают недели и не меняют ни одного решения: «выясни из логов, почему люди уходят», «сделай сквозную атрибуцию по всем каналам», «посчитай LTV по каждому источнику за три года». Общие принципы приоритизации — в product management.

От расплывчатой просьбы к отвечаемому вопросу

Уточнение — это диалог, а не анкета. Ниже — реальная по структуре последовательность, которая занимает семь минут и экономит три дня.

Ключевых реплик три. Шаг 2 переводит разговор с данных на решение. Шаг 6 вытаскивает порог — заказчик почти никогда не называет его сам, но почти всегда может назвать, если спросить в форме «хватит ли двух пунктов». Шаг 9 — заранее объявленное ограничение: этот способ сбора данных отвечает на «сколько», но не на «почему». Сказанное до работы, оно звучит как профессионализм; сказанное после — как оправдание.

О том, как вести такие разговоры с разными типами заказчиков, — в работе со стейкхолдерами.

Карточка вопроса

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

вопрос: "Уходят ли новые пользователи мобильного приложения чаще, чем новые пользователи веба?"
решение: "Вкладывать ли спринт команды роста в мобильный онбординг"
владелец_решения: "Продакт мобильного направления"
срок: "2026-06-20, планирование квартала"
порог: "Разница в удержании D7 больше 5 п.п. — вкладываемся"
единица_наблюдения: "Пользователь, впервые зарегистрировавшийся в окне наблюдения"
метрика: "Доля вернувшихся хотя бы раз на 7-й календарный день после регистрации"
источник: "events.registration, events.session_start; витрина dm_user_activity"
чего_не_узнаем:
  - "Почему уходят — причина требует интервью или эксперимента"
  - "Пользователей, у которых не работает телеметрия"
  - "Тех, кто зарегистрировался на вебе и вернулся в приложении под другим id"
что_дальше: "Если разница есть — A/B нового онбординга"

Поле чего_не_узнаем обязательное. Оно превращает ограничения способа сбора из умолчания в явный текст, который читает заказчик. Это то же самое, что раздел «допущения» в требованиях, и работает по той же причине.

Разбор: «почему конверсия упала на четверть»

Классический входящий запрос. Разберём его целиком — от формулировки до вывода.

Что известно. Конверсия сессии в покупку упала с 4,40 % в мае до 3,40 % в июне. Относительно это минус 23 %, и в чате это уже назвали «падением на четверть».

Что спрашивать первым. Не «почему упало», а «что в знаменателе и одинаково ли он устроен в мае и июне». Разложим по платформам.

Период Платформа Сессий Покупок Конверсия Доля трафика
Май Desktop 8000 400 5,00 % 80 %
Май Mobile 2000 40 2,00 % 20 %
Май Итого 10000 440 4,40 %
Июнь Desktop 4000 208 5,20 % 40 %
Июнь Mobile 6000 132 2,20 % 60 %
Июнь Итого 10000 340 3,40 %

Конверсия выросла на обеих платформах — с 5,00 % до 5,20 % и с 2,00 % до 2,20 %. Суммарная при этом упала на целый процентный пункт. Это не ошибка в арифметике, а парадокс Симпсона: изменилась структура трафика, и агрегат поехал за ней, а не за поведением пользователей.

Разложение изменения на вклад структуры и вклад самих ставок — точное тождество:

$$\Delta = \sum_i p_i^{\text{old}}\left(w_i^{\text{new}} - w_i^{\text{old}}\right) + \sum_i w_i^{\text{new}}\left(p_i^{\text{new}} - p_i^{\text{old}}\right)$$

где $p_i$ — конверсия сегмента, $w_i$ — его доля в трафике. Считаем:

  • вклад структуры: $0{,}05 \cdot (0{,}4 - 0{,}8) + 0{,}02 \cdot (0{,}6 - 0{,}2) = -0{,}020 + 0{,}008 = -0{,}012$;
  • вклад ставок: $0{,}4 \cdot 0{,}002 + 0{,}6 \cdot 0{,}002 = 0{,}0008 + 0{,}0012 = +0{,}002$;
  • сумма: $-0{,}012 + 0{,}002 = -0{,}010$, то есть ровно наблюдаемый минус один процентный пункт.

Сто двадцать процентов падения объясняется сдвигом трафика на мобильные, и ещё двадцать процентов противоположного знака добавляет реальное улучшение обеих платформ.

Вывод в терминах решения. Вопрос «почему упала конверсия» задан неверно: конверсия не падала ни в одном сегменте. Правильный следующий вопрос — «почему выросла доля мобильного трафика», и это вопрос к маркетингу, а не к продукту. Спринт по улучшению воронки не изменил бы ничего.

Тот же расчёт в SQL. Схема: таблица sessions(session_id, started_at, platform, purchased).

WITH monthly AS (
    SELECT date_trunc('month', started_at)::date       AS month,
           platform,
           count(*)                                    AS sessions,
           count(*) FILTER (WHERE purchased)           AS purchases
    FROM sessions
    WHERE started_at >= date '2026-05-01'
      AND started_at <  date '2026-07-01'
    GROUP BY 1, 2
),
shares AS (
    SELECT month,
           platform,
           purchases::numeric / sessions                               AS p,   -- конверсия сегмента
           sessions::numeric / sum(sessions) OVER (PARTITION BY month) AS w    -- доля трафика
    FROM monthly
),
paired AS (
    SELECT platform,
           max(p) FILTER (WHERE month = date '2026-05-01') AS p_old,
           max(w) FILTER (WHERE month = date '2026-05-01') AS w_old,
           max(p) FILTER (WHERE month = date '2026-06-01') AS p_new,
           max(w) FILTER (WHERE month = date '2026-06-01') AS w_new
    FROM shares
    GROUP BY platform
)
SELECT platform,
       round(p_old * (w_new - w_old), 5) AS mix_effect,   -- вклад сдвига структуры
       round(w_new * (p_new - p_old), 5) AS rate_effect   -- вклад изменения конверсии
FROM paired
ORDER BY platform;

Оконная функция sum(...) OVER (PARTITION BY month) даёт долю сегмента внутри месяца без второго прохода по таблице; max(...) FILTER (...) — стандартный приём разворота двух строк в одну. Подробнее про окна и такие развороты — SQL для анализа.

Правило, которое стоит унести из разбора: прежде чем объяснять движение агрегата, проверьте, не двигался ли состав. Любой агрегат по неоднородной совокупности — это средневзвешенное, и веса меняются сами по себе.

SQL: что именно вы посчитали

Между вопросом и запросом есть зазор, в который проваливаются даже опытные люди. Три ошибки дают львиную долю неверных цифр.

Ошибка первая: считать события вместо людей.

-- Так спрашивают чаще всего — и почти всегда получают не то
SELECT (count(*) FILTER (WHERE event_name = 'payment_success'))::numeric
     / nullif(count(*) FILTER (WHERE event_name = 'checkout_open'), 0) AS conversion
FROM events
WHERE occurred_at >= date '2026-06-01'
  AND occurred_at <  date '2026-07-01';

Запрос синтаксически корректен и семантически бессмысленен. Пользователь, открывший оплату пять раз и купивший один, даёт 1/5. Пользователь, открывший один раз и не купивший, даёт 0/1. Итоговая дробь — не «доля людей, которые купили», а отношение двух счётчиков событий, у которого нет содержательной интерпретации. Плюс краевой эффект: покупка 30 июня в 23:50 по попытке, начатой 30 июня в 23:40, попадёт в числитель, а начатая 30 июня в 23:59 и завершённая 1 июля — нет.

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

WITH starts AS (                       -- единица наблюдения: пользователь, первая попытка в окне
    SELECT user_id, min(occurred_at) AS started_at
    FROM events
    WHERE event_name = 'checkout_open'
      AND occurred_at >= date '2026-06-01'
      AND occurred_at <  date '2026-07-01'
    GROUP BY user_id
),
wins AS (                              -- успех засчитываем в пределах 24 часов от попытки
    SELECT s.user_id
    FROM starts s
    JOIN events e
      ON e.user_id     = s.user_id
     AND e.event_name  = 'payment_success'
     AND e.occurred_at >= s.started_at
     AND e.occurred_at <  s.started_at + interval '24 hours'
    GROUP BY s.user_id
)
SELECT count(*)                                       AS n,       -- знаменатель
       count(w.user_id)                               AS k,       -- числитель
       round(count(w.user_id)::numeric / count(*), 4) AS p_hat
FROM starts s
LEFT JOIN wins w ON w.user_id = s.user_id;

GROUP BY в wins нужен, чтобы несколько успешных оплат не размножили строки при джойне, — иначе count(w.user_id) окажется больше числа пользователей и конверсия превысит единицу. Это вторая классическая ошибка: джойн, размножающий строки. Проверка простая: после каждого джойна убедитесь, что число строк не выросло, либо явной агрегацией, либо сравнением count(*) до и после.

Ошибка третья: цифра без знаменателя и без разброса. Любое число в отчёте должно сопровождаться n, иначе его нельзя нести в решение. Достаточно вынести предыдущий запрос в CTE с именем agg и обернуть его:

-- agg — предыдущий запрос целиком, вынесенный в CTE: колонки n, k, p_hat
SELECT n, k, p_hat,
       round(p_hat - 1.96 * sqrt(p_hat * (1 - p_hat) / n), 4) AS ci_lo,
       round(p_hat + 1.96 * sqrt(p_hat * (1 - p_hat) / n), 4) AS ci_hi
FROM agg;

Правило для отчётов, которое стоит сделать обязательным в команде: колонка с долей всегда идёт вместе с колонкой n. На витринах OLAP это ничего не стоит по производительности — count(*) считается тем же сканом (см. ClickHouse и OLAP), — зато отсекает целый класс выводов по трём наблюдениям.

Отдельно: определения событий в вашем трекере — часть контракта, а не деталь реализации. Если checkout_open шлётся при открытии модалки, а не при показе формы, все конверсии смещены, и никакой SQL это не чинит. Договорённости о смысле событий и их качество — источники данных и качество данных, а на стороне пайплайнов — data quality и governance.

Жизненный цикл вопроса

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

Два перехода в этой схеме обычно отсутствуют в реальных командах, и именно их отсутствие портит работу.

Первый — answered → more. Без него ответ «интервал накрывает порог» не имеет легального исхода, и аналитик под давлением выдаёт точечную оценку как факт. Второй — infeasible → draft. Без него запрос, на который данные не отвечают, всё равно уходит в работу и возвращается красивой картинкой с ложной уверенностью.

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

Почему дашборды никто не смотрит

Теперь можно назвать причину прямо. Большинство дашбордов не открывают не потому, что они плохо свёрстаны, а потому, что ни один график на них не отвечает на вопрос «какое решение изменится от этой цифры». Дашборд собирают из того, что есть в витрине, а не из решений, которые кто-то регулярно принимает.

Диагностика занимает пять минут: возьмите любой график с вашего дашборда и спросите автора, при каком значении этой линии кто-то что-то сделает. Если ответа нет — график декоративный. Обычно декоративны от 80 до 100 % площади.

Обратное устройство даёт живой инструмент: под каждое регулярное решение — свой блок, в котором есть текущее значение, порог, интервал и подпись, что делать при пересечении. Такой дашборд выглядит скучнее, зато его открывают. Подробно — в главе про дашборды; визуальная сторона, включая честные способы соврать графиком, — в главе про визуализацию; метрики интерфейса — в ux-design.

И сразу предупреждение на будущее: как только цифра становится целевой, она начинает менять поведение людей, которые на неё влияют, и перестаёт измерять то, что измеряла. Это закон Гудхарта, ему посвящены глава трека и материал про локальную оптимизацию. Поэтому вопрос «какое решение изменится» имеет продолжение: «и как изменится поведение, когда все узнают, что мы смотрим на эту цифру».

Антипаттерны постановки

  • «Дай выгрузку». Просьба о данных вместо вопроса. Ответ: «конечно, под какое решение». Выгрузка без вопроса почти всегда порождает вторую выгрузку.
  • Вопрос без порога. «Какое у нас удержание?» — ответ невозможно оценить как хороший или плохой, значит, он не изменит поведение.
  • Вопрос без срока. Ответ через три недели на решение, принятое во вторник, — потраченное время, а не аналитика.
  • Вопрос «почему» к наблюдательным данным. Логи фиксируют то, что случилось, а не то, что случилось бы. Либо эксперимент, либо квазиэксперимент, либо честное «причину отсюда не установить» — см. причинность.
  • Вопрос, подогнанный под найденный результат. Сначала посмотрели двадцать разрезов, потом сформулировали гипотезу про тот, где получилось красиво. Механику разбирают Гельман и Локен в «The Statistical Crisis in Science»: даже без сознательного жульничества свобода выбора разреза после просмотра данных обесценивает любые p-значения.
  • Метрика вместо вопроса. «Нам нужен NPS» — это ответ на невысказанный вопрос. Полезнее спросить, какое решение принимается по NPS и почему именно он.
  • Точность ради точности. Три знака после запятой при выборке в 40 наблюдений — сигнал, что автор не считал интервал.
  • Одно число там, где нужно распределение. Среднее время ответа 200 мс при p99 в 4 секунды описывает несуществующего пользователя. Про это — описательная статистика и распределения.

Мини-итог

  • Вопрос считается поставленным, когда названы решение, владелец, срок и порог. Отсутствие любого из четырёх — повод вернуться к заказчику, а не открывать редактор SQL.
  • Нужная точность не выбирается по вкусу: она выводится из расстояния до порога. Отсюда же берётся требуемый размер выборки, а значит — цена ответа в трафике и календаре.
  • Цифра описывает не мир, а результат вашего способа сбора данных. Между целевой величиной и числом в отчёте — лестница неслучайных сужений; переносить вывод с нижней ступени на верхнюю нельзя.
  • «Не различаем, нужно больше данных» — валидный ответ, и он должен быть заранее легализован в таблице «ответ → действие». Иначе его место займёт точечная оценка без интервала.
  • Прежде чем объяснять движение агрегата, проверьте, не менялся ли состав совокупности: разложение на вклад структуры и вклад ставок — точное тождество и делается одним запросом.
  • Каждое число в отчёте идёт вместе со своим n. Дашборд, где ни один график не привязан к порогу и решению, закономерно никто не открывает.

Материалы

  • John W. Tukey. The Future of Data Analysis (1962) — источник тезиса про приблизительный ответ на правильный вопрос.
  • Douglas W. Hubbard. How to Measure Anything — измерение как снижение неопределённости и ценность информации через решение.
  • Ronny Kohavi, Diane Tang, Ya Xu. Trustworthy Online Controlled Experiments — глава про постановку метрик и то, во что обходятся плохо заданные вопросы.
  • Andrew Gelman, Eric Loken. The Statistical Crisis in Science — «сад расходящихся тропок»: почему вопрос, сформулированный после просмотра данных, не считается.
  • Cassie Kozyrkov. Публикации по decision intelligence — практичный взгляд на аналитику как на обслуживание решений.
  • Richard Hamming. You and Your Research — классический текст про выбор задачи; применим к выбору вопроса напрямую.
  • Simpson’s Paradox, Stanford Encyclopedia of Philosophy — формальный разбор эффекта из примера с конверсией.

Что дальше

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

Откуда берутся данные: сбор, события, выживший источник

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов