Мир аналитика данных


Гео и язык канала: Россия, Русский
Категория: Карьера


Пишу о рабочих буднях аналитика. Тут много рабочего кода, прохождение собеседований и еще много всего полезного.
https://www.linkedin.com/in/valeriashuvaeva
Автор канала: @Valeria_Shuvaeva

Связанные каналы  |  Похожие каналы

Гео и язык канала
Россия, Русский
Категория
Карьера
Статистика
Фильтр публикаций


Вне выборки

Обычно здесь про SQL, Python и AB-тесты. Но не всё, что важно, попадает в выборку.

🌿 Сад, дорожка из старого кирпича, вкусный чай и мороженое - иду и никуда не тороплюсь. Редкое состояние.

🌅 Закат, который останавливает. Ты просто стоишь и смотришь, как солнце уходит за горизонт - и на пару минут ничего больше не важно.

🤸‍♀️ Батут. Оказывается, в 30+ (и больше 😉 ) это работает так же, как в детстве - смех сам вырывается.

🌊 Озеро в тишине. Обожаю плавать - ни одной мысли, и это лучшая часть.

🍎 Яблоки, собранные своими руками. Простое удовольствие, которое ничем не заменить.

🌸 И один цветок - просто потому что он красивый, и этого достаточно.

Это лето на удалёнке я снова провела на даче. Дети - на воздухе, я - за ноутбуком, а вечером - на батуте. Хотя если честно, прыгать хотелось не так уж часто - чаще просто сидеть с чаем и смотреть на закат.

Лето почти закончилось. И это лето точно было - вне выборки, вне метрик, просто моё. Наше.


Fuckup Night от создателей Trisigma, Ares и karpov.courses

Согласитесь, ивенты, где все делятся только своими успехами, уже поднадоели. Хочется реальных историй, где что-то пошло не по плану, но в итоге ошибка стала ценным опытом.

Поэтому команда Trisigma собирает Fuckup Night 26 августа — без записи и красивых цифр. Истории расскажут:
🔸 Виталий Черемисинов (Trisigma)
🔸 Роман Нестер (Ares, Arteus LLM и Segmento)
🔸 Валерий Бабушкин (British Petroleum)
🔸 Беслан Курашов (plevako.ai и karpov.courses)

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

⚡️ Важно! Записи не будет, поэтому приходите на эфир. Главное — не забудьте зарегистрироваться.


📊 A/B-тест: что делаем после окончания эксперимента? Считаем итоги! 🚀

Как вы можете заметить у меня в канале реально много полезного кода. Что ж продолжим эту тенденцию! 😄

В прошлом посте я показала, как до запуска теста рассчитать минимальный детектируемый эффект (MDE) для бинарной метрики (конверсии).
Мы выяснили, что при базовой конверсии ~4.94% и выборке 50 000 пользователей мы сможем «увидеть» только изменения больше 10.99% относительного прироста.
А теперь давайте смоделируем реальный тест – сгенерируем данные, где в тестовой группе конверсия реально выше, и посмотрим, что получится.
Спойлер: наш фактический эффект окажется достаточно большим, чтобы его обнаружить при таком размере выборки. А статистическую значимость мы проверим отдельно. 😉

🎯 Настройки эксперимента

Общий размер выборки: 51 500 пользователей (разбивка 50/50)
Базовая конверсия в контроле: 4,9% (control_conversion = 0.049)
Ожидаемая конверсия в тесте: 5,5% (test_conversion = 0.055)
Относительный прирост: (0,055 – 0,049) / 0,049 ≈ 12,2%

Это тот эффект, который мы хотим обнаружить. Но сможет ли тест его увидеть? Давайте проверим!


🧬 Генерируем синтетические данные
Фиксируем seed=42 для воспроизводимости.
import numpy as np
import pandas as pd
from scipy.stats import chisquare, norm
from statsmodels.stats.proportion import proportions_ztest
import math

n = 51500
control_conversion = 0.049
test_conversion = 0.055
np.random.seed(42)

# Генерируем ID и метку группы (50/50)
active_user_id = np.arange(1, n + 1)
test_id = np.random.binomial(1, 0.5, size=n)

df = pd.DataFrame({'active_user_id': active_user_id, 'test_id': test_id})

# Генерируем конверсии отдельно для каждой группы
df['is_converted'] = 0
df.loc[df['test_id'] == 0, 'is_converted'] = np.random.binomial(1, control_conversion,
size=(df['test_id'] == 0).sum())
df.loc[df['test_id'] == 1, 'is_converted'] = np.random.binomial(1, test_conversion,
size=(df['test_id'] == 1).sum())

df.head()
🔍 Шаг 1. Проверяем разбивку на группы (SRM)
Перед тем как смотреть на конверсию, сначала проверяем, правильно ли пользователи распределились между группами.
Почему это важно?
Если вместо ожидаемых 50/50 мы получили, например, 60/40, результат эксперимента уже вызывает вопросы.
Ожидаем, что в каждой группе будет примерно по 25 750 пользователей.
from scipy.stats import chisquare

control = df[df['test_id']==0]['active_user_id'].nunique()
test = df[df['test_id']==1]['active_user_id'].nunique()

# Ожидаемое распределение (50/50)
total = control + test
print('В тесте присвоены номера групп для:',total,'устройств')
expected = total / 2

# Критерий хи-квадрат
chi2_stat, p_value = chisquare([control, test], f_exp=[expected, expected])

print(f"Хи-квадрат статистика: {chi2_stat:.4f}")
print(f"P-value: {p_value:.6f}")

# Вывод решения
alpha = 0.05
if p_value < alpha:
print("SRM обнаружен — тест ненадёжен.")
else:
print("SRM не обнаружено. Разбивка на группы правильная.")
Результат:
Контроль: 25767, Тест: 25733
Хи-квадрат: 0.0224, p-value: 0.8809
✅ Разбивка корректна – можно продолжать.

📈 Шаг 2. Фактические конверсии – и вот сюрприз!

Считаем реальные доли (в жизни то, что получилось после двух-трех недель томительного ожидания, у нас - то что нагенерировалось после np.random.binomial:
control_users = len(df[df['test_id'] == 0])
test_users = len(df[df['test_id'] == 1])

control_conv = df[df['test_id'] == 0]['is_converted'].sum()
test_conv = df[df['test_id'] == 1]['is_converted'].sum()

cr_control = control_conv / control_users
cr_test = test_conv / test_users

uplift = (cr_test / cr_control - 1) * 100
effect_pp = (cr_test - cr_control) * 100

print(f'Control users: {control_users}')
print(f'Control conversions: {control_conv}')
print(f'CR control: {cr_control:.2%}')
print('==============================')
print(f'Test users: {test_users}')
print(f'Test conversions: {test_conv}')
print(f'Test control: {cr_test:.2%}')
print('==============================')
print(f'Effect: +{effect_pp:.2f} п.п.')
print(f'uplift: {uplift:.2f}%')
Вывод (примерный, при seed=42):
Control users: 25767
Control conversions: 1176
CR control: 4.56%
===================================
Test users: 25733
Test conversions: 1407
Test control: 5.47%
===================================
Effect: +0.90 п.п.
📈 uplift: 19.8%

Почему контроль не 4,9%, а 4,56%? Это нормально. Когда мы задаём: control_conversion = 0.049 мы не говорим: «В контроле будет ровно 4,9% конверсий». Мы говорим: «Каждый пользователь имеет вероятность 4,9% сконвертироваться».
А np.random.binomial() генерирует случайную выборку из этого распределения.
Поэтому фактическая конверсия в конечной выборке может немного отличаться от заданной.
Это ровно то, что происходит и в реальном эксперименте: ожидаемый baseline и фактический baseline — не обязательно одно и то же!

И здесь у нас: ожидали: 4,9% получили: 4,56%
А в тесте: ожидали: 5,5% получили: 5,47%

Именно с фактическими значениями мы дальше и работаем.

🧮 Шаг 3. Считаем фактический эффект. Проводим z‑тест для двух пропорций

Теперь главный вопрос:
Можем ли мы считать разницу между 4,56% и 5,47% статистически значимой?

Для двух независимых конверсий используем z-тест для двух пропорций.
stat, p_value = proportions_ztest(count=[test_conv, control_conv],
nobs=[test_users, control_users], alternative='two-sided')
print(f'z-stat: {stat:.4f}')
print(f'p-value: {p_value:.10f}')

z-stat: 4.6981
p-value: 0.0000026

p_value < 0.05 поэтому отвергаем нулевую гипотезу.🎉 Тест прокрасился! Эффект статистически значим.

🔁 Шаг 4. Сравниваем с MDE, пересчитанным после теста на фактическом baseline и размере выборки
И вот здесь возвращаемся к тому, с чего начали.
MDE показывает, какой минимальный эффект способен обнаружить наш тест при заданных параметрах.
После завершения эксперимента мы можем дополнительно пересчитать его, используя:
- фактический baseline - 4,56%;
- фактический общий размер выборки - 51 500.
Это не «новый правильный MDE», а дополнительная оценка чувствительности теста на фактических данных.

n_total = control_users + test_users
mde_abs, mde_rel, lower, upper = mde_for_conversion(cr_control, n_total)

# Фактический эффект в процентных пунктах
effect_pp = (cr_test - cr_control) * 100

print(f"Конверсия в контроле: {cr_control:.2%}")
print(f"Конверсия в тесте: {cr_test:.2%}")
print(f"Фактический эффект: +{effect_pp:.2f} п.п.")

print("MDE: ±", round(mde_abs*100, 2), "п.п. - абсолютный (", round(mde_rel, 2), "% - относительный)")

print(f'uplift: {uplift:.2f}%')
if uplift > mde_rel:
print("✅ Наш эффект превышает MDE")
else:
print("❌ Эффект меньше MDE")
Получим:
Конверсия в контроле: 4.56%
Конверсия в тесте: 5.47%

Фактический эффект: +0.90 п.п.

MDE: ± 0.52 п.п. - абсолютный ( 11.29 % - относительный)

uplift: 19.80%

✅ Наш фактический эффект (19.80%) превышает MDE(11,29%)
Это означает, что эффект такого масштаба находится в пределах чувствительности теста.

🏁 Итого

Мы прошли полный путь от сырых данных до вывода:
1️⃣ Проверили SRM → разбивка 50/50 корректна
2️⃣ Посчитали фактический CR → 4,56% vs 5,47%
3️⃣ Посчитали эффект+0,9 п.п. / +19,80%
4️⃣ Проверили статистическую значимость → p-value < 0,05
5️⃣ Сравнили эффект с MDE19,80% > 11,29%

И чтобы не путаться, еще раз: MDE и статистическая значимость отвечают на разные вопросы.
MDE:
Насколько большим должен быть эффект, чтобы наш тест имел достаточную чувствительность его обнаружить?

p-value:
Достаточно ли данных, чтобы считать наблюдаемую разницу статистически значимой?

📎 Вот ноутбук, чтобы Вы смогли поэкспериментировать.


📊 А/Б-тесты. Считаем MDE до того, как запустим тест.

Хочу показать вам рабочий код для расчета минимального детектируемого эффекта (MDE) - это самый маленький истинный эффект, который тест сможет признать значимым.

🎯 На каком примере будем считать?

Покажу на примере конверсии (бинарная метрика). Её часто ставят как приемочную метрику. Она просто считается и легко интерпретируется.

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

⭐Пусть наша приемочная метрика - конверсия пользователей в заказ.
Нам нужны два простых поля на каждого активного пользователя:
● active_user_id - кто заходил в приложение за последние 2 недели;
● order_flg - совершил ли он целевое действие (1 - да, 0 - нет).
✅ Генерируем синтетический датасет на 50 000 пользователей с базовой конверсией 5%:
n = 50000                  
baseline_conversion = 0.05
np.random.seed(42)
active_user_id = np.arange(1, n + 1)
order_flg = np.random.binomial(1, baseline_conversion, size=n)
df = pd.DataFrame({'active_user_id': active_user_id,'order_flg': order_flg})
df.head()
Смотрим на фактические цифры:
active_users = df['active_user_id'].nunique()
users_with_order = df[df['order_flg']==1]['active_user_id'].nunique()

share_users_with_order = users_with_order / active_users

print('Активные клиенты:', active_users)
print('Клиенты с заказом:', users_with_order)
print('Конверсия в заказ:', round(share_users_with_order * 100, 2), '%')
Формула расчёта MDE
Я использую стандартный подход на основе z-критерия для двух пропорций
Это означает, что мы предполагаем: при больших выборках распределение разности конверсий между тестом и контролем стремится к нормальному (ЦПТ).
В функции n_total — это суммарное количество пользователей в обеих группах. То есть при n_total = 50 000 в каждой группе будет по 25 000 человек.
def mde_for_conversion(baseline, n_total, alpha=0.05, power=0.80, two_sided=True):
    """
    baseline - конверсия в контроле
    n_per_group - размер каждой группы
    """
    n_per_group = n_total / 2
    p = baseline
    # Квантили нормального распределения
    if two_sided:  z_alpha = norm.ppf(1 - alpha/2)
    else: z_alpha = norm.ppf(1 - alpha)
    z_beta = norm.ppf(power)
   
    se = math.sqrt(p * (1 - p) / n_per_group + p * (1 - p) / n_per_group)
    mde_abs = (z_alpha + z_beta) * se
    mde_rel = mde_abs / baseline * 100
    lower = baseline - mde_abs
    upper = baseline + mde_abs
    return mde_abs, mde_rel, lower, upper
Считаем mde
n_total = int(active_users) #всего пользователей для обеих групп
baseline_conversion =share_users_with_order
 
mde_abs, mde_rel, lower, upper = mde_for_conversion(baseline_conversion, n_total)
print("\n" + "=" * 60)
print("MDE ДЛЯ КОНВЕРСИИ (n_total=" + format(n_total, ",") + "):")
print("=" * 60)
print("Baseline:", round(baseline_conversion*100, 2), "%")
print("MDE: ±", round(mde_abs*100, 2), "п.п. (", round(mde_rel, 2), "% )")
print("Диапазон:", round(lower*100, 2), "% –", round(upper*100, 2), "%")
📈 Смотрим на вывод и делаем выводы 😀

MDE ДЛЯ КОНВЕРСИИ (n_total=50,000):
Baseline: 4.94 %
MDE: ± 0.54 п.п. ( 10.99 % )
Диапазон: 4.4 % – 5.48 %

Как это читать?
1️⃣ Сейчас базовая конверсия - 4.94%.

2️⃣ Мы сможем статистически значимо зафиксировать изменение, только если конверсия в тесте выйдет за пределы коридора 4.4% – 5.48%.

3️⃣Это означает, что тест «увидит» только прирост от 10.99% относительно базового значения.

Если ваше дизайн-решение даёт +5% к конверсии (а это очень даже неплохо!), то при 50 000 пользователях тест не сможет это доказать. 😭 Вы получите p-value > 0.05 и решите, что эффекта нет, хотя он есть. Но чтобы «поймать» +5%, нужно кратно увеличивать выборку, например держать тест не две недели, а три.

📎 Вот ноутбук, чтобы Вы смогли поэкспериментировать.

Если нравятся такие посты с реальным кодом и разбором A/B, то ставьте огонечки 🔥😀

787 0 31 15 31

Ребята, привет! 👋

Хочу рассказать вам про штуку, которая Вам понравится. У Паши Бухтика (No Data No Growth) через 2 дня стартует новый поток по A/B. И формат в этот раз необычный 👀

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

Потому что в реальной работе A/B – это всегда общая ответственность продакта и аналитика. И чем хуже они понимают друг друга, тем чаще тест превращается в формальность, а не в инструмент решений. Знакомо, да? 😄

🎯 Что заберут продакты:

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

📊 Что заберут аналитики:

Программа шире – кроме общей части есть отдельные занятия:

✔️ сплитование;
✔️ симуляции Монте-Карло;
✔️ ratio-метрики и стат. критерии;
✔️ множественное тестирование;
✔️ A/B без A/B, ускорение, сетевой эффект.

И то, чему почти нигде не учат – объяснять выводы A/B нетехническим людям и видеть, как продакт реально использует их в решениях. Часто именно это и отделяет мидла от сеньора 👍

🔥 А самое интересное – практики:

Они проходят вместе в мини-группах:

➡️ Продакты начинают понимать, как думают аналитики;
➡️ Аналитики – как устроена продуктовая логика.

Редкий случай, когда обе стороны учатся друг у друга прямо в процессе, а не после ✨

🎓 А если вы уже были на прошлых потоках. Можно прийти снова: досдать домашки, освежить материал, попробовать новый формат. Паша обещал спецусловия.

Старт уже 5 июня. Заявку можно оставить тут:

👉 Для аналитиков: https://nodatanogrowth.com/product-analyst-ab-testing
👉 Для продактов: https://nodatanogrowth.com/product-manager-ab-testing

На аналитическом треке осталось всего 4 места. Так что лучше написать сегодня, чем в июле жалеть, что не успел 😉


📚 Посмотрела хэндбук по A/B-тестированию от команды Trisigma (платформа экспериментов от Авито). Он оказался прям очень неплохим.

Там внутри собрана хорошая база, которую полезно освежить даже тем, кто уже давно работает с экспериментами и метриками 👀
И конечно можно повторить основы статистики: что такое дисперсия, стандартное отклонение, стандартная ошибка, типы распределения данных. Там прям хорошо разобрано. А то нет, нет, да и забывается какая-то формула или информация если это что-то прям не часто используется.

Что конкретно есть внутри:
🟢основы A/B-тестов и типы экспериментов
🟢как формулировать гипотезы
🟢классификация метрик: goal / proxy / guardrail / debug
🟢OEC и закон Кэмпбелла
🟢ошибки в экспериментах и как не словить ложные выводы
🟢атомарный дизайн метрик
🟢ну и введение в матстат: дисперсия, стандартное отклонение, распределения, ЦПТ и т.д. (расчеты на примерах)

Понравилось, что всё объясняется на нормальных продуктовых примерах, даже расчеты внутри есть 🧮
Забрать можно в боте @trisigma_avito_bot за подписку на их канал.

Реклама. ООО "Авито Тех".


🔥 Вчера побывала в офисе Яндекса на Digital day!

Главная тема вечера - Яндекс Метрика. Поделюсь сухими фактами сначала:

✅ Что нового:
- ИИ-помощник (уже в бета-версии - можно тестить 👀)
- Можно смотреть средние показатели продаж по рынку, нужно только поставить галочку в настройках "Получить доступ к ответу по рынку"

✅ Ключевые инсайты (и где деньги 💰):

- Как меняется аналитика под разные индустрии
- Глубина разметки - куда копать, чтобы не тонуть в данных - Какие отчёты смотрят лидеры рынка в Метрике
- Как измеряют вовлечённость
- Где искать потери в данных и как их чинить

✅ Огонь-фишка, которую полезно изучить:
В Метрику можно передавать данные e-commerce по client_id

📌 Это значит - отслеживать офлайн-выручку и связывать её с действиями на сайте. Кейс из METRO - рабочий и успешный 🔥

В общем, было объемно и интересно🔥
А еще получилось пообщаться с разными людьми - нетворкинг в силе 🤝

И да, несколько человек зашли в канал после встречи - спасибо, что вы здесь! 👏
А чтобы быть на связи плотнее, я добавила LinkedIn в описание. Жду в контактах!

🍕🍽 Ну и, конечно, вкусно покормили - тоже важная метрика мероприятия!

📎Спикеры обещали прислать презу со всеми ссылками и темами. Как пришлют - прикреплю здесь!


Свежее исследование рынка аналитиков 2025 от NEWHR.
7 главных трендов рынка:

📈1️⃣ Зарплаты у многих выросли, но рынок уже не летит вверх
Две трети аналитиков получили рост дохода, но чаще это было не из-за смены работы, а из-за индексации или повышения грейда. В целом рост по рынку - меньше 10%, тогда как раньше это скорее были 15–20% в год. То есть история «перешёл в новую компанию и сразу +30%» уже не выглядит нормой.

💸 2️⃣Деньги стали главным фактором
Интересные задачи и развитие всё ещё важны, но зарплата впервые вышла на первое место и для удержания, и при выборе нового оффера. Очень показательный сдвиг: рынок стал более прагматичным.

🌍 3️⃣Российский и международный рынки всё сильнее расходятся
Привлекательность зарубежных компаний для аналитиков из РФ за два года упала на 31%. Плюс снижается интерес к переезду: люди чаще ориентируются на тот рынок, где уже работают.

4️⃣ Искать работу стало дольше
77% аналитиков находят работу за 3 месяца, но год назад таких было 81%. А доля тех, кто ищет до 6 месяцев, выросла с 53% до 61%. То есть рынок не рухнул, но стал плотнее: конкуренция выше, а найм медленнее.

🏆5️⃣Авито - лидер по привлекательности в качестве возможного работодателя. Хуже всех репутация у VK и Сбера.

🤖 6️⃣AI и ML уже не “бонус”, а новый must-have
За год доля аналитиков, которые работают с ML-сервисами, выросла с 14% до 22%. А развивать этот навык хотят 41,5% респондентов. Похоже, для аналитиков это уже не «что-то дополнительное», а всё больше часть профессии.

🏢 7️⃣Грейд влияет не только на зарплату
От него зависят ещё и скорость поиска работы, свобода выбора локации и компании. Сеньоры, принципалы и тимлиды в целом чувствуют себя на рынке увереннее.

Ну и еще разное:
✔️ Какие задачи решают аналитики сегодня
✔️ Локации и планы аналитиков на переезд
✔️ На какие компании и в каком формате работают
✔️ Как менялись зарплаты аналитиков в течение 2025 года
✔️ Сколько они получают сегодня в зависимости от специализации и грейда
✔️ Откуда пришли в профессию и как планируют развиваться дальше
✔️ ТОП и Анти-ТОП российских компаний по мнению аналитиков
✔️ Что ценят в аналитической культуре
✔️ На какие конференции ходят и за кем из экспертов следят

▶️ Вот Сайт с полными результатами


Я про вас не забыла и вот принесла кое-что интересное. Телегу замедляют, но я остаюсь тут и не хочу предлагать вам куда-то переходить. Поддержите огонечками, что вы тут и вам это по прежнему нужно!

Сегодня хочу показать удобный SQL-прием для A/B тестов: как смотреть метрику сразу по нескольким двухнедельным периодам и не размечать каждый интервал руками. Так легче заметить, метрика стабильна или скачет от периода к периоду.

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

Сгенерировала df_product_events(event_ts, user_id, event_name, event_payload).
import duckdb
import pandas as pd

query = """
with events as (
select
date_add(
date '2026-02-02',
INTERVAL (cast(14 * floor(date_diff('day', date '2026-02-02', cast(event_ts as date)) / 14.0) as integer)) DAY) as period_start,
user_id,
json_extract_string(event_payload, '$.source_block') as source_block
from df_product_events
where event_ts >= timestamp '2026-02-02 00:00:00'
and event_ts < timestamp '2026-03-16 00:00:00'
and event_name = 'product_card_open'
and nullif(trim(user_id), '') is not null
)
select
period_start,
period_start + INTERVAL 13 DAY as period_end,
count(distinct user_id) as users_total,
count(distinct case when source_block = 'Подборка для вас' then user_id end) as users_from_target_block,
round(
100.0 * count(distinct case when source_block = 'Подборка для вас' then user_id end)
/ count(distinct user_id),
2
) as share_from_target_block
from events
group by 1, 2
order by 1
"""
result = duckdb.query(query).to_df()

Самая важная часть здесь - это расчет period_start (каждому событию назначается начало его двухнедельного периода)

Что здесь происходит:
1️⃣Берем опорную дату, с которой хотим начать нарезку периодов
2️⃣Через date_diff считаем, сколько дней прошло от нее до события
3️⃣ Делим это число на 14.0, чтобы понять, в какой двухнедельный интервал попало событие.
4️⃣Через floor округляем вниз, чтобы получить номер двухнедельного интервала
5️⃣ потом умножаем на 14 и прибавляем к опорной дате через date_add
В итоге каждое событие автоматически попадает в нужное окно.

Например, если опорная дата - 2026-02-02, то:
событие от 2026-02-03 попадет в период с началом 2026-02-02
событие от 2026-02-14 тоже попадет туда же
а событие от 2026-02-16 уже уйдет в следующий период

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

Мне нравится этот способ тем, что он очень легко масштабируется. Не нужно руками прописывать периоды через case when, не нужно собирать отдельные запросы под каждое окно. Один раз задали опорную дату и длину периода - и дальше запрос сам аккуратно раскладывает события как надо.👍

Если нужно смотреть метрику не по 14 дням, а, например, по трем неделям, меняется одно число и все. Удобно же!

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

896 0 19 4 64

Поздравляю всех девушек с 8 марта! 🌷

Пусть будет больше радости, сил, интересных задач и чтобы жизнь почаще радовала хорошими результатами… желательно со статистической значимостью 😄✨

Я тут немного выпала из канала. Но у меня есть сразу несколько поводов для радости:

Закончился испытательный срок на работе 🎉
Три месяца пролетели очень быстро! Задачи интересные, команда отличная! Работаем над улучшением приложения Азбуки Вкуса! 📱Кто ещё не скачал (Москвичи и Питерцы) - обязательно скачивайте. Там реально много прикольного и вкусного!
А если найдете там какие-то проблемы... - ну вы теперь знаете кому писать 😜

✅ 🎤 Ещё сходила на стендап (уже второй раз)
Очень необычный опыт: сидишь прямо возле сцены, атмосфера супер живая. Поняла, почему люди туда ходят не один раз 😄

Ну и сам праздник! Три дня отдыха - это вам не шутки. Тут отдыхать надо со всей ответственностью 😄

А вы как проводите длинные выходные? 😊 Фото приветствуются.
Да, знаю, телега уже не та… но фоточки всё ещё поднимают метрики настроения 📈

И вот вам A/B-тест на выходные(ну две недели такой тест не дали пока держать 😂:
🅰️ Группа A (контроль) - отдых 😄
👍 - жмём, если вы за этот вариант

🅱️ Группа B - ещё больше отдыха 😎
🔥 - если считаете, что отдыхаете ещё сильнее чем обычно.

Посмотрим, кто победит 📊


Ребята, привет! 👋

У Паши Бухтика (No Data No Growth) 2 марта стартует пятый поток по A/B-тестированию!
📣 Вот его пост с подробностями: https://t.me/nodatanogrowth/1038

Я проходила этот курс в том году - было круто и очень полезно! 👍
Следующий поток будет только осенью.

Короче, очень рекомендую🚀🚀🚀 Учеба - это вложение в себя, которое окупается!
Ссылка на его сайт


Удобная функция UNNEST в PostgreSQL для работы

Всем привет! Решила поделиться тут с вами одной полезной функцией, которую как раз недавно использовала на работе.

У нас есть массив устройств у пользователей. Но если мы хотим:
✔️посчитать устройства
✔️сделать join
✔️агрегировать
✔️считать DISTINCT
то массив нужно разложить в строки.

Представим, что у нас есть данные, где у пользователя несколько устройств лежат в массиве.
Было: 1 строка = массив устройств
Должно быть: несколько строк с пользователем = одно устройство в строке

Сначала создадим это прямо в Python
import duckdb
import pandas as pd

df = pd.DataFrame({
"user_id": [1, 2, 3],
"device_ids": [
["dev_a", "dev_b"],
["dev_c"],
["dev_d", "dev_e", "dev_f"]
]
})

И вот тут-то мы разворачиваем массив через UNNEST
query = """
SELECT user_id, d AS device_id
FROM df
CROSS JOIN UNNEST(device_ids) AS t(d)
ORDER BY 1, 2
"""
result = duckdb.query(query).to_df()

Разберем необычную конструкцию CROSS JOIN UNNEST(device_ids) AS t(d)
Что вообще означает AS t(d)?
🟢UNNEST(device_ids) - разворачивает массив
🟢t - имя временной таблицы
🟢d - имя колонки внутри неё

После этого d — обычная колонка, с которой можно работать как с любой другой.

Главное потом случайно не задвоить метрику когда будем соединять таблицу с таблицей заказов, например.
orders = pd.DataFrame({
"user_id": [1, 2],
"revenue": [100, 200]
})

Теперь делаем join после UNNEST:
query = """
SELECT df.user_id, d AS device_id, o.revenue
FROM df
CROSS JOIN UNNEST(device_ids) AS t(d)
LEFT JOIN orders o
ON df.user_id = o.user_id
ORDER BY 1, 2
"""
result2 = duckdb.query(query).to_df()
User 1 имел revenue = 100
Но теперь эта сотка появилась два раза! 😱

Поэтому нужно быть внимательным и понимать для чего мы это делаем.

❌ Нельзя после этого просто делать SUM(revenue) по этой таблице - выручка продублируется на каждое устройство и итог “раздуется”.

✅ Но зато расшив девайсы и приджойнив user-level выручку мы можем посмотреть её рядом на строках устройств.
💡 Зачем это может быть нужно?

Например:
сколько устройств у платящих пользователей
есть ли различия между single-device и multi-device users
сколько выручки приходится на пользователей с 3+ устройствами

Мы не делим revenue по устройствам. Мы просто используем её как атрибут пользователя.

P.S Кстати, я перешла на VS Code - мне нравится. Красивый же черный фон, да? Ну и удобно видеть в структуре файлы проекта.

1.4k 0 10 10 17

🔬Тут прислали исследование. Смотрим, изучаем. Я тоже где-то там есть 😄🔬

📁 300+ экспертов и каналов, за которыми следят аналитики

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

Сейчас мы обрабатываем результаты, и уже готовы поделиться с вами первыми инсайтами. А именно — рейтингом экспертов отрасли и каналами, которые читают и смотрят наши респонденты-аналитики. Выборка респондентов в этом году — 1493 человека!

🔗 Полный список экспертов-аналитиков

Что вы найдёте на лендинге:

Рейтинги ТОП-15 экспертов и ТОП-30 Telegram-каналов, интересных аналитикам

Они разделены специализациям: отдельно для продуктовых, маркетинговых, дата-, веб- и BI-аналитиков и отдельно для системных и бизнес-аналитиков — потому что предпочтения отличаются.

Полные списки экспертов (100+), Telegram-каналов (130+), подкастов и YouTube-каналов которые аналитики находят интересными

Telegram-каналы для удобства разделены по темам: аналитика, обучение и карьера, BI/UX/Data Viz, Data Engineering и разработка, ML/DS, Product Managment, продуктовая и HR аналитика.

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


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


✨ Ещё пару дней - и каникулы пролетят

Мы семьёй успели всё:
✔️две дачи - к родным и к себе 🏡
✔️фейерверки 🎆
✔️квадроциклы по заснеженному озеру ❄️
✔️банька 🔥
✔️много оливье 🥗
✔️встречи с друзьями 🧡
✔️застолья 🍽
✔️и ещё раз застолья 🍽😄

И пока мы отдыхали, нашлись упорные смельчаки 💪📚, которые совершили 195 переходов по ссылке на мой бесплатный курс 🎓. Вот это я понимаю - тяга к знаниям. Уважаю 🙌

Я правда верю: мы строим свою жизнь только своими действиями и устремлениями. Можно сколько угодно мечтать и ждать знаков, но без движения ничего не случается.

И да, я могу повторять это из года в год: важно учиться, ставить цели и кайфовать от процесса, от того, как шаг за шагом идём по своему пути.

Пусть он извилистый.
Пусть не самый быстрый.
Зато наш. Особенный.

А вселенная нас точно слышит.
И правда помогает - когда мы чего-то искренне хотим. 🎁

А вообще - впереди ещё целых два дня выходных (если считать сегодняшнее утро) 😌✨ Наслаждаемся!


🎁🎄 Новогодний подарок подписчикам канала🎁

Конец года - хорошее время взять паузу, оглянуться назад и честно спросить себя:
а что вообще со мной произошло за этот год?

Для меня этот год был очень важным.
Я перешла в новую компанию, в новые задачи. Много учусь, много думаю, по-новому смотрю на аналитику и на свою роль в продукте. Чувствую, что впереди - новые свершения и более масштабные вещи, к которым я постепенно подхожу.

Меня периодически спрашивают в личке, не менторю ли я сейчас.
Когда-то я делала курс по SQL и Python (pandas).

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

Поэтому я решила:
➡️➡️➡️ сделать этот курс бесплатным и доступным для подписчиков канала.

Что важно понимать:
✔️ это базовый курс
✔️ без поддержки и обновлений
✔️ можно проходить в своём темпе
✔️ он отлично подойдёт, если вы:
• начинаете путь в аналитике
• хотите закрыть пробелы
• устали от разрозненных туториалов

📎 Ссылка на мой курс для Вас: SQL&PANDAS

Пусть он станет точкой опоры для тех, кому сейчас нужна база.

Спасибо вам за этот год! 🧡
За то, что читаете, сохраняете, задаёте вопросы и иногда пишете "спасибо, было полезно".
Это правда очень мотивирует продолжать.

И да - рекламные интеграции тоже мотивируют 😎
Потому что благодаря им этот канал может жить, расти и оставаться полезным. Спасибо, что относитесь к этому с пониманием!

С наступающим Новым годом 🎄🎄🎄
Пусть в 2026 будет больше ясности, роста и данных, которым можно доверять!!! ✨


В последние дни ко мне в личку пришло немало вопросов в духе: "Вдохновила история! Но как конкретно начать? Есть ли смысл переходить сейчас?" Есть. Иногда эффект приходит не сразу, но он приходит.

Я всегда рекомендую сначала немного покопаться в sql и питоне, чтобы "пощупать аналитику", а потом уже выбирать курс.
У меня тут часто рекламируется Simulative, потому что мне не стыдно за качество продукта.

И если вы:

✔️Смотрите в сторону аналитики, но не решаетесь,

✔️Уже работаете с цифрами и хотите большего, то это ваш формат.

Тем более сейчас у них скидка 35%
!!!! Под новый год скидки мы любим!

Короче, держите Курс-симулятор «Аналитик данных» от Simulative

Что внутри:
➖12 модулей с нормальной, системной базой: SQL, Python, BI, статистика, продуктовые метрики
➖Практика на реальных кейсах, чтобы в итоге было не «я что-то смотрел», а портфолио
➖Формат без истерики и гонки: видео, тексты, конспекты, домашки — учишься в своём темпе
➖Наставники, которые реально проверяют и помогают, а не просто висят для галочки
➖Возможность получить оффер сразу после курса


Вот тот самый момент, когда ваше «потом» должно стать «сейчас».

🔗 Скорее записывайтесь на курс со скидкой: simulative.ru/data-analyst


✨ Я сменила работу!!! И это тот самый случай, когда все «пазлы» сошлись. ✨

Друзья, у меня оффер, который я с радостью приняла - Азбука вкуса 🧡
Теперь я Senior Product Analyst.

Я уже неделю в новой роли - и мне правда очень в кайф.
Погружаюсь в продукт, читаю документацию, разбираю метрики, графики, смотрю базу по A/B-тестам - и ловлю себя на мысли: «Вот это да, как же интересно».

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

У Азбуки шикарный офис и (ожидаемо 😄) невероятно вкусные обеды.
Я работаю удалённо, но уже успела съездить к ним за техникой и документами - атмосфера 🔥

И да, если вдруг не знали:
📱 у Азбуки есть мобильное приложение, где можно заказывать продукты на дом!

И ещё одна мысль, которой хочется поделиться.

📌 Учёба реально меняет карьеру. Проверено на себе.
В разные моменты жизни:

✔️получила международный сертификат по английскому (BEC) ➡️ устроилась в иностранный холдинг
✔️изучала Data Science ➡️ сменила профессию
✔️весной прошла курс по A/B-тестированию ➡️ сменила компанию

Ничего «случайного». Только шаги, которые со временем складываются в результат.

Если вы сейчас учитесь, сомневаетесь, устали или думаете «а есть ли смысл?» -
есть. Иногда эффект приходит не сразу, но он приходит.

Спасибо, что читаете и идёте рядом ❤️
Буду рада вашим реакциям - мне правда сейчас очень радостно ✨

1.6k 0 20 15 156

⚡️Пошаговый план: как получить оффер на аналитика в 2026 году?

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

Simulative продолджают серию вебинаров про то как стать Аналитиком и теперь речь пойдет про 2026 год.

Это прям 100% классное событие для тех кто только зашел в аналитику и для тех, кто хочет в нее зайти в ближайшее время. Особенно если вы не понимаете, какие навыки действительно важны или боитесь, что без опыта вас не возьмут на работу. Кстати тут разберут и возрастной аспект: как стать аналитиком в 30/40/50 лет и т.д.

На вебинаре будет:
🟠Разберем полный роадмап: что учить, в каком порядке, до какого уровня;
🟠Структура хорошего портфолио с примерами;
🟠Что говорят реальные наниматели - какие у них сейчас требования:
— Покажем реальные примеры, как оформить резюме и портфолио, чтобы привлекать внимание;
— Обсудим какие отклики работают, а какие сразу отправляют в корзину;
— Изнанка найма: инсайдерский взгляд на процессы отбора

🟠 Практические техники для новичков: разберём, как компенсировать недостаток опыта и быстро закрывать пробелы в знаниях.

🕗 По классике для ребят - в конце будет новый бонус, который поможет бустануть вашу карьеру, так что смотрите до конца!

😶Зарегистрироваться на бесплатный вебинар


Как я собрала мини-бэкенд за два вечера - и теперь могу считать клики по ссылкам лучше, чем рекламодатели.
Cloudflare Workers
❤️

Решила собрать себе маленький сервис, который считает количество переходов по ссылкам.
Почему? Во-первых руки зачесались что-то такое навайбкодить. Ну и потому что рекламодатели дают свою ссылку, по которой я не вижу статистику. А хотелось бы понимать: сколько людей реально переходит.

Никаких сторонних платформ, никаких сложных интеграций, все в облаке, без серверов - только GPT и https://dash.cloudflare.com/

Я залипла в Cloudflare Workers - и поняла, что это какой-то магический портал, где можно за вечер (ну ладно, за два вечера) собрать рабочий сервис, не поднимая сервера, не ковыряясь с Docker и вообще не страдая (ну, почти) 😅Ощущение, будто подарили маленький бекенд без боли 😌

Всё бесплатно, очень быстро, и разворачивается в один клик. Там есть какие-то лимиты.
Ну и конечно GPT написал на javascript код по моему запросу. Все таки не заменит он пока программистов. Я с ним больше намучилась, он менял переменные с ничего, пытался постоянно что-то "улучшить", но старое еще не работало. Жаль, что на питоне, к сожалению, вроде как нельзя там писать. Интересный, конечно, опыт. Но все равно - это прорыв, я считаю.

⭐️ Что получилось в итоге
✅ Своё админ-окно c красивым интерфейсом (я прям кайфую), где можно:
- создавать короткие ссылки
- указывать целевой URL
- смотреть количество переходов
- удалять ненужные ссылки

✅ Счётчик работает мгновенно
Каждый раз, когда человек переходит по короткой ссылке, в которой завернута целевая ссылка, переходы увеличиваются.
Допустим, я ввела в поле короткую ссылку id01 и в поле с "http://" саму ссылку на сам счетчик. Жму кнопку [Создать ссылку]. Появилась новая строка.

Все кто перейдет вот сюда: на https://fire-fb34.lera844.workers.dev/id01 увеличат счетчик. В конце адреса стоит /id01
У вас будет свой id, который придумаете.

✅ Идеальный формат для пет-проектов
Ничего не нужно держать на хостинге, платить за сервер, обновлять пакеты.
Ты просто пишешь JS-функцию — и она живёт в облаке.

✅ Можно реализовать свои творческие задумки даже если ты не фулстек разработчик.
Если у вас есть идея маленькой утилиты, мини-сервиса или просто интересный эксперимент - это идеальная площадка, чтобы попробовать.

🎁Ну и самое главное - вы тоже можете пользоваться этим счетчиком. Давайте договоримся - чужие ссылки не удалять, только свои. Поигрались, стало не нужно - удалите. А то кто знает какие там лимиты? 😜
Если кто заинтересуется, могу скинуть сам файл с работающим js кодом.

Показано 19 последних публикаций.