Урок курса

Абсолютное и относительное изменение: проценты и процентные пункты

Практическая аналитика данных

В предыдущем уроке вы получили два числа: 82 оплаченных заказа в январе 2024 и 89 — в феврале. Сами по себе эти цифры мало что говорят руководителю: разница в 7 заказов выглядит иначе, если база была 10, и совсем иначе, если база была 1000. Чтобы из двух чисел получить аналитическое утверждение, нужно ответить на два разных вопроса — на сколько единиц изменился показатель и на сколько процентов от исходного уровня.

Абсолютное и относительное изменение: формулы и единицы

Любое сравнение двух периодов даёт два принципиально разных ответа, и оба нужны.

Абсолютное изменение — это просто разность:

Δ = значение_текущего − значение_базового

Результат выражается в тех же единицах, что и сам показатель. Если считаем заказы — получаем заказы. Если считаем рубли — получаем рубли. Для оплаченных заказов «Маяка» за январь и февраль 2024:

Δ = 89 − 82 = +7 заказов

Знак показывает направление: плюс — рост, минус — падение. Абсолютное изменение определено всегда, в том числе когда базовое значение равно нулю.

Относительное изменение (темп прироста) отвечает на вопрос «насколько это много относительно того, с чего начинали»:

Δ% = (значение_текущего − значение_базового) / значение_базового × 100

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

Δ% = (89 − 82) / 82 × 100 ≈ +8,54%

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

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

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

Процент vs. процентный пункт: правило и диагностика ошибки

Правило выбора единицы для абсолютного изменения зависит от природы самого показателя.

Если показатель — натуральная величина (заказы, рубли, клиенты), его абсолютное изменение выражается в тех же единицах: «+7 заказов», «−15 000 рублей». Относительное изменение — в процентах.

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

Разберём на конкретном примере. Доля отменённых заказов выросла с 10% до 13%.

  • Абсолютное изменение: 13% − 10% = +3 п. п.
  • Относительное изменение: 3 / 10 × 100 = +30%

Это два разных числа, и они отвечают на разные вопросы. Если написать «доля отмен выросла на 3%» — это технически означает 3% от 10%, то есть прирост 0,3 п. п. Именно так читает эту фразу статистически грамотный получатель. Аналитик при этом имел в виду совсем другое.

Диагностика: посмотрите на единицу измерения показателя. Если в строке стоит «%» — абсолютная разница пишется в «п. п.». Если «%» нет — разница пишется в исходных единицах.

Корректная формулировка для примера выше:

«Доля отменённых заказов выросла на 3 п. п. — с 10% до 13%, что соответствует относительному росту на 30%.»

Для числа оплаченных заказов:

«Число оплаченных заказов выросло на 7 (≈ +8,54%).»

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

Разница между 10% и 13% — 3 процентных пункта. Относительно прежних 10% это рост на 30%. Условный пример из теории.

Разница между 10% и 13% — 3 процентных пункта. Относительно прежних 10% это рост на 30%. Условный пример из теории.

Вычисление изменения в SQL: CTE и вещественное деление

Чтобы получить все четыре столбца результата в одном запросе, нужно свести данные двух периодов в одну строку. В SQLite удобнее всего сделать это через два CTE с последующим соединением.

WITH base AS (
  SELECT COUNT(*) AS orders
  FROM orders
  WHERE status = 'paid'
    AND order_date >= '2024-01-01'
    AND order_date < '2024-02-01'
),
curr AS (
  SELECT COUNT(*) AS orders
  FROM orders
  WHERE status = 'paid'
    AND order_date >= '2024-02-01'
    AND order_date < '2024-03-01'
)
SELECT
  base.orders AS jan_orders,
  curr.orders AS feb_orders,
  curr.orders - base.orders AS abs_change,
  ROUND((curr.orders - base.orders) * 100.0 / base.orders, 2) AS rel_change_pct
FROM base, curr;

Каждый CTE (base и curr) считает COUNT(*) по фильтру status = 'paid' и диапазону дат своего месяца. Диапазоны заданы через >= нижней границы и < первого дня следующего месяца — это стандартный способ выбрать полный календарный месяц без риска захватить лишнее.

Строка FROM base, curr — декартово произведение двух таблиц по одной строке в каждой. Никакого ON-условия не нужно: результат всегда ровно одна строка с полями обоих CTE.

В расчёте rel_change_pct критично умножение на 100.0, а не на 100. В SQLite операторы * и / имеют одинаковый приоритет и выполняются слева направо. Если написать * 100 / base.orders, вычисление идёт так: 7 * 100 = 700, затем целочисленное 700 / 82 = 8 — дробная часть теряется, и вместо 8.54 получится 8. Если же порядок другой — / base.orders * 100 — ситуация хуже: 7 / 82 = 0 (целочисленное деление), затем 0 * 100 = 0. Умножение на 100.0 (литерал с десятичной точкой) переводит выражение в вещественную арифметику до деления: 7 * 100.0 = 700.0, затем 700.0 / 82 ≈ 8.536... — и ROUND даёт правильные 8.54.

На реальных данных «Маяка» запрос вернёт одну строку:

jan_orders feb_orders abs_change rel_change_pct
82 89 7 8.54

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

Вычисление изменения в pandas и экспорт to_csv(index=False)

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

import pandas as pd

df = pd.read_csv('orders.csv')
df['order_date'] = pd.to_datetime(df['order_date'])

paid = df[df['status'] == 'paid'].copy()

jan = paid[(paid['order_date'] >= '2024-01-01') & (paid['order_date'] < '2024-02-01')]
feb = paid[(paid['order_date'] >= '2024-02-01') & (paid['order_date'] < '2024-03-01')]

base_val = len(jan)   # 82
curr_val = len(feb)   # 89

abs_change = curr_val - base_val
rel_change = round((curr_val - base_val) / base_val * 100, 2)

result = pd.DataFrame({
    'period_base': ['2024-01'],
    'period_curr': ['2024-02'],
    'base_orders': [base_val],
    'curr_orders': [curr_val],
    'abs_change': [abs_change],
    'rel_change_pct': [rel_change]
})

result.to_csv('change_result.csv', index=False)

pd.to_datetime нужен, чтобы сравнение с датами через >= и < работало корректно: если столбец остаётся строковым, лексикографическое сравнение даст правильный результат только для ISO-формата YYYY-MM-DD, но явное приведение надёжнее.

len(jan) и len(feb) считают число строк в отфильтрованном DataFrame — то есть число заказов. Это эквивалент COUNT(*) из SQL.

Параметр index=False в to_csv убирает из файла автоматически генерируемый целочисленный индекс строк DataFrame. По умолчанию pandas добавляет его первым столбцом — в итоговом CSV он выглядит как безымянный столбец 0, 1, 2, ..., который не несёт смысловой нагрузки и мешает дальнейшей обработке файла. index=False не изменяет сам DataFrame в памяти: если вы после to_csv обращаетесь к result.index, индекс там остаётся, в файл просто не попадает.

Результирующий change_result.csv будет содержать одну строку данных и шесть именованных столбцов:

period_base,period_curr,base_orders,curr_orders,abs_change,rel_change_pct
2024-01,2024-02,82,89,7,8.54

Задача 1

В условном примере доля отменённых заказов в январе составила 10%, а в феврале — 13%. Аналитик написал в выводе: «Доля отменённых заказов выросла на 3%.» Что неверно в этой формулировке?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

Условный числовой пример (данные не связаны с реальным магазином или конкретным датасетом).

В некотором онлайн-магазине в первом месяце было 280 оплаченных заказов, во втором месяце — 350 оплаченных заказов.

Вычислите относительное изменение числа оплаченных заказов от первого месяца ко второму. Округлите до одного знака после запятой.

Введите ответ в процентах (только число, например: 14.3 или −5.2).

Без регистрации · результат не сохраняется

Задача 3

Сопоставьте каждый вид изменения с единицей измерения. Запишите ответ в формате «1-X, 2-X, 3-X, 4-X», где X — буква варианта.

Виды изменения:

  1. Относительное изменение выручки при росте с 500 000 до 575 000 руб.
  2. Абсолютное изменение конверсии при снижении с 40% до 34%.
  3. Абсолютное изменение числа заказов при снижении со 180 до 162.
  4. Относительное изменение доли мобильных заказов при росте с 25% до 31%.

Варианты единиц:
A — процентные пункты (п. п.)
B — проценты (%)
C — исходные натуральные единицы (рубли, заказы)

Один вариант может использоваться несколько раз.

Без регистрации · результат не сохраняется

Задача 4

Вы анализируете оплаченные заказы интернет-магазина за два полных месяца: ноябрь 2024 (базовый период) и декабрь 2024 (текущий период). Выбранным маршрутом (SQL в браузерном раннере или pandas в Jupyter) выполните следующие шаги:

  1. Отфильтруйте заказы со статусом paid за каждый месяц.
  2. Подсчитайте количество оплаченных заказов в ноябре и декабре.
  3. Вычислите абсолютное изменение (декабрь − ноябрь) и относительное изменение по формуле: (декабрь − ноябрь) / ноябрь × 100, округлите до 2 знаков.
  4. Соберите результат в строку с полями period_base, period_curr, base_orders, curr_orders, abs_change, rel_change_pct и экспортируйте в CSV.

Введите значение rel_change_pct (число до 2 десятичных знаков, без знака %).

Без регистрации · результат не сохраняется

Задача 5

Аналитик изучил данные условного интернет-магазина за два месяца. Оплаченных заказов: январь — 280, февраль — 322. Доля отменённых заказов: январь — 12%, февраль — 15%.

Какой из вариантов содержит корректные формулировки обоих выводов для нетехнического руководителя?

Выберите один вариант
Без регистрации · результат не сохраняется

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку