Z-score — стандартизация данных для аналитика
Коротко
Z-score (стандартное отклонение от среднего) показывает, на сколько стандартных отклонений значение отличается от среднего. Формула: z = (x − μ) / σ. Z-score = 0 — значение равно среднему. Z-score = 2 — на 2σ выше среднего. Аналитику z-score нужен для поиска выбросов, стандартизации данных перед сравнением и z-теста. На собеседованиях спрашивают формулу, правило 68-95-99.7 и применение.
Формула
z = (x − μ) / σ- x — значение
- μ (мю) — среднее генеральной совокупности (или выборочное среднее)
- σ (сигма) — стандартное отклонение
# Пример
x = 85 # оценка студента
mu = 70 # средняя по группе
sigma = 10 # стандартное отклонение
z = (x - mu) / sigma # (85 - 70) / 10 = 1.5
# Студент на 1.5 стандартных отклонения выше среднегоПравило 68-95-99.7
Для нормального распределения:
- 68% данных в пределах ±1σ (z от −1 до +1)
- 95% данных в пределах ±2σ (z от −2 до +2)
- 99.7% данных в пределах ±3σ (z от −3 до +3)
99.7% (±3σ)
┌──────────────────┐
│ 95% (±2σ) │
│ ┌──────────────┐ │
│ │ 68% (±1σ) │ │
│ │ ┌──────────┐ │ │
───────┼─┼─┤ μ = 0 ├─┼─┼───────
-3σ -2σ -1σ 0 +1σ +2σ +3σЗначение с |z| > 2 — необычное (5% случаев). |z| > 3 — экстремальное (0.3%). Это основа для определения выбросов.
Расчёт в Python
NumPy / SciPy
import numpy as np
from scipy import stats
data = [45, 50, 55, 60, 65, 70, 75, 80, 85, 90]
# Вручную
mu = np.mean(data)
sigma = np.std(data, ddof=0) # ddof=0 для генеральной совокупности
z_scores = [(x - mu) / sigma for x in data]
# Через scipy
z_scores = stats.zscore(data)
print(z_scores)
# [-1.57, -1.22, -0.87, -0.52, -0.17, 0.17, 0.52, 0.87, 1.22, 1.57]Pandas
import pandas as pd
df = pd.DataFrame({
'user_id': range(1, 11),
'revenue': [100, 200, 300, 5000, 150, 250, 180, 220, 350, 280]
})
# Z-score
df['z_score'] = (df['revenue'] - df['revenue'].mean()) / df['revenue'].std()
# Выбросы (|z| > 2)
outliers = df[df['z_score'].abs() > 2]
print(outliers)
# user_id revenue z_score
# 3 4 5000 3.12 ← выброс!Расчёт в SQL
-- Z-score в PostgreSQL
SELECT
user_id,
revenue,
(revenue - AVG(revenue) OVER ()) / STDDEV(revenue) OVER () AS z_score
FROM user_revenue;
-- Найти выбросы (|z| > 2)
WITH z AS (
SELECT
user_id,
revenue,
(revenue - AVG(revenue) OVER ()) / STDDEV(revenue) OVER () AS z_score
FROM user_revenue
)
SELECT * FROM z WHERE ABS(z_score) > 2;Применение
1. Поиск выбросов
# Правило: |z| > 2 — потенциальный выброс, |z| > 3 — точно выброс
df['is_outlier'] = df['z_score'].abs() > 2Альтернатива методу IQR. Z-score лучше для нормально распределённых данных, IQR — для скошенных.
2. Стандартизация перед сравнением
# Разные шкалы — нельзя сравнивать напрямую
df['salary'] = [50000, 80000, 120000] # рубли
df['experience'] = [1, 3, 8] # годы
# Стандартизация
for col in ['salary', 'experience']:
df[f'{col}_z'] = (df[col] - df[col].mean()) / df[col].std()
# Теперь обе переменные в одной шкале (среднее=0, σ=1)Стандартизация необходима перед кластеризацией, PCA и другими ML-алгоритмами, чувствительными к масштабу.
3. Аномалии в метриках
# DAU каждого дня: z-score относительно скользящего среднего
df['dau_ma30'] = df['dau'].rolling(30).mean()
df['dau_std30'] = df['dau'].rolling(30).std()
df['dau_z'] = (df['dau'] - df['dau_ma30']) / df['dau_std30']
# Алерт если |z| > 3
alerts = df[df['dau_z'].abs() > 3]4. Z-тест
Z-score — основа z-теста для проверки гипотез:
from scipy import stats
# Средняя конверсия сайта 5%. Сегодня 60 из 1000 (6%). Значимо?
z = (0.06 - 0.05) / (0.05 * 0.95 / 1000) ** 0.5
p_value = 2 * (1 - stats.norm.cdf(abs(z)))
print(f'z = {z:.2f}, p-value = {p_value:.4f}')
# z = 1.45, p-value = 0.1471 — не значимоZ-score vs Min-Max нормализация
| Метод | Формула | Результат | Когда |
|---|---|---|---|
| Z-score | (x − μ) / σ | Среднее = 0, σ = 1 | Нормальные данные, выбросы |
| Min-Max | (x − min) / (max − min) | От 0 до 1 | Фиксированный диапазон |
Z-score сохраняет информацию о выбросах. Min-Max сжимает все данные в [0, 1] — выброс «сплющит» остальные значения.
Типичные ошибки
Z-score для ненормальных данных. Если распределение сильно скошенное, правило 68-95-99.7 не работает. Выбросы лучше искать через IQR.
ddof: 0 vs 1. np.std(data, ddof=0) — σ генеральной совокупности. np.std(data, ddof=1) — выборочное s. Для z-score обычно ddof=0, для статистических тестов — ddof=1. pandas .std() по умолчанию ddof=1.
Z-score как причина действия. Z-score > 2 — сигнал для расследования, не для автоматического действия. Всегда проверяйте контекст: может быть акция, праздник, баг в логировании.
Вопросы с собеседований
-- Что такое z-score? -- Количество стандартных отклонений от среднего. Формула: z = (x − μ) / σ. Z = 0 — среднее, z = 2 — на 2σ выше, z = −1 — на 1σ ниже.
-- Как найти выбросы через z-score? -- Вычислить z-score для каждого значения. |z| > 2 — подозрительное значение (5% случаев). |z| > 3 — вероятный выброс (0.3%). Работает для нормальных данных.
-- Что значит «правило 68-95-99.7»? -- Для нормального распределения: 68% данных в ±1σ, 95% в ±2σ, 99.7% в ±3σ от среднего.
-- Когда стандартизация обязательна? -- Перед алгоритмами, чувствительными к масштабу: k-means, PCA, KNN, регрессия с регуляризацией. Если переменные в разных шкалах (рубли vs годы) — стандартизируйте.
Потренируйтесь решать задачи — откройте тренажёр с 1500+ вопросами для подготовки к собеседованиям аналитиков.
FAQ
Z-score отрицательный — это нормально?
Да. Отрицательный z-score — значение ниже среднего. Z = −1.5 означает «на 1.5 стандартных отклонения ниже среднего». Это не «плохо» — зависит от контекста.
Z-score и p-value — как связаны?
Z-score преобразуется в p-value через таблицу нормального распределения. z = 1.96 → p = 0.05 (двусторонний). z = 2.58 → p = 0.01. Чем больше |z|, тем меньше p-value.
Как тренироваться
Z-score — базовая тема статистики для аналитика. Задачи на статистику — в тренажёре Карьерник. Больше вопросов — в разделе с примерами.