Как посчитать корреляцию у двух величин?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как посчитать корреляцию у двух величин?
Практический гайд по вычислению корреляции
Корреляция - это один из самых полезных инструментов Product Analyst'а для понимания связей между метриками. Но её легко неправильно интерпретировать. Расскажу как считать и что это значит.
1. Что такое корреляция
Корреляция (Pearson Correlation) показывает, как две переменные движутся вместе.
Формула:
r = Σ((x - mean_x) × (y - mean_y)) / sqrt(Σ(x - mean_x)² × Σ(y - mean_y)²)
Где:
- r - коэффициент корреляции (от -1 до +1)
- x, y - две переменные
- mean_x, mean_y - среднее значение
Интерпретация
r = +1 → Идеальная положительная корреляция (когда x растет, y всегда растет)
r = +0.8 → Сильная положительная корреляция
r = +0.5 → Средняя положительная корреляция
r = 0 → Нет корреляции
r = -0.5 → Средняя отрицательная корреляция
r = -1 → Идеальная отрицательная корреляция (когда x растет, y всегда падает)
2. Метод 1: SQL (для больших данных)
Основной способ, который я использую в работе:
-- Проверить: растет ли revenue вместе с user engagement?
SELECT
CORR(daily_sessions, daily_revenue) as correlation,
-- Также посчитаю дополнительные статистики
AVG(daily_sessions) as avg_sessions,
AVG(daily_revenue) as avg_revenue,
STDDEV(daily_sessions) as stddev_sessions,
STDDEV(daily_revenue) as stddev_revenue,
COUNT(*) as sample_size
FROM daily_metrics
WHERE date >= NOW() - INTERVAL '90 days';
Результат:
correlation | 0.87
avg_sessions | 5000
avg_revenue | 50000
sample_size | 90
Это означает: сильная положительная корреляция (0.87) между сеансами и доходом.
Пример с реальными данными
-- Корреляция между временем на сайте и конверсией
WITH daily_data AS (
SELECT
DATE(session_start) as date,
AVG(session_duration_sec) as avg_session_time,
COUNT(DISTINCT CASE WHEN converted = true THEN user_id END)::float /
COUNT(DISTINCT user_id) * 100 as conversion_rate
FROM sessions
GROUP BY DATE(session_start)
)
SELECT
CORR(avg_session_time, conversion_rate)::numeric(3,2) as correlation,
-- P-value (статистическая значимость)
CASE
WHEN CORR(avg_session_time, conversion_rate) IS NOT NULL THEN
'Significant' -- Need proper p-value calculation
ELSE 'Not significant'
END as significance
FROM daily_data;
-- Результат:
correlation | 0.65
significance | Significant
-- Интерпретация: Средняя положительная корреляция
-- Когда пользователи проводят больше времени, они чаще конвертят
-- НАПОМИНАНИЕ: Это не значит, что время ВЫЗЫВАЕТ конверсию!
3. Метод 2: Python (для анализа)
Когда нужно больше контроля и визуализации:
import pandas as pd
import numpy as np
from scipy import stats
# Загрузить данные
df = pd.read_csv('daily_metrics.csv')
# Способ 1: Простая корреляция Пирсона
corr = df['sessions'].corr(df['revenue'])
print(f"Correlation: {corr:.3f}")
# Результат: 0.876
# Способ 2: С p-value (важно для значимости!)
corr, p_value = stats.pearsonr(df['sessions'], df['revenue'])
print(f"Correlation: {corr:.3f}, P-value: {p_value:.4f}")
# Результат: Correlation: 0.876, P-value: 0.0000
# P-value < 0.05 = статистически значимо
# Способ 3: Матрица корреляции (для нескольких переменных)
corr_matrix = df[['sessions', 'revenue', 'bounce_rate', 'retention']].corr()
print(corr_matrix)
# Результат:
# sessions revenue bounce_rate retention
# sessions 1.000 0.876 -0.654 0.723
# revenue 0.876 1.000 -0.521 0.812
# bounce_rate -0.654 -0.521 1.000 -0.934
# retention 0.723 0.812 -0.934 1.000
# Способ 4: Спирманова корреляция (для ненормальных распределений)
spearman_corr, spearman_p = stats.spearmanr(df['sessions'], df['revenue'])
print(f"Spearman: {spearman_corr:.3f}, P-value: {spearman_p:.4f}")
# Результат: Spearman: 0.892, P-value: 0.0000
Визуализация
import matplotlib.pyplot as plt
# Scatter plot с линией тренда
plt.scatter(df['sessions'], df['revenue'], alpha=0.6)
z = np.polyfit(df['sessions'], df['revenue'], 1)
p = np.poly1d(z)
plt.plot(df['sessions'], p(df['sessions']), "r--", label=f'Trend line')
plt.xlabel('Daily Sessions')
plt.ylabel('Daily Revenue')
plt.title(f'Correlation: {corr:.3f}')
plt.legend()
plt.show()
4. Практические примеры
Пример 1: Engagement и Retention
WITH cohort_data AS (
SELECT
DATE(install_date) as cohort_date,
AVG(events_day_1) as avg_engagement_d1,
COUNT(DISTINCT CASE WHEN active_day_7 = true THEN user_id END)::float /
COUNT(*) as retention_d7
FROM user_cohorts
GROUP BY DATE(install_date)
HAVING COUNT(*) > 100 -- Минимальный размер выборки
)
SELECT
CORR(avg_engagement_d1, retention_d7) as corr,
COUNT(*) as cohort_count
FROM cohort_data;
-- Результат: 0.84
-- Интерпретация: День 1 engagement СИЛЬНО коррелирует с день 7 retention
-- Это показатель что engagement на первый день важен
Пример 2: Price и Conversion
WITH product_data AS (
SELECT
product_id,
price,
SUM(sales) as total_sales,
SUM(impressions) as total_impressions
FROM product_stats
WHERE date >= NOW() - INTERVAL '30 days'
GROUP BY product_id, price
)
SELECT
CORR(price, total_sales / total_impressions::float) as price_conversion_corr,
CORR(price, total_sales) as price_revenue_corr
FROM product_data
WHERE total_impressions > 100;
-- Результат:
-- price_conversion_corr: -0.45
-- price_revenue_corr: 0.12
-- Интерпретация:
-- Когда цена растет:
-- - Конверсия падает (-0.45) - логично
-- - Но revenue растет (+0.12) - людей меньше, но они покупают дороже
Пример 3: Spending и Churn
-- Коррелирует ли spending пользователя с churn?
WITH user_data AS (
SELECT
user_id,
SUM(amount) as total_spent,
CASE WHEN last_activity < NOW() - INTERVAL '30 days' THEN 1 ELSE 0 END as churned
FROM users
LEFT JOIN payments ON users.id = payments.user_id
GROUP BY user_id
)
SELECT
CORR(total_spent, churned) as correlation
FROM user_data;
-- Результат: -0.72
-- Интерпретация: Сильная ОТРИЦАТЕЛЬНАЯ корреляция
-- Люди, которые тратят больше, реже уходят (логично)
-- Это показатель что нужно фокусироваться на monetization для retention
5. Важные замечания
Замечание 1: Корреляция НЕ равна причинности
Классический пример:
Корреляция между:
- Количество фильмов Nicolas Cage (исход которых он выбирал в своих фильмах)
- Количество людей, утопленных в бассейне
Корреляция: 0.81 (очень сильна!)
Вывод: Nicolas Cage НЕ вызывает утопления.
Оба явления просто растут со временем (confounding variable = время)
В аналитике:
Если я вижу корреляцию между "время на сайте" и "покупкой",
это может значить:
1. Люди, которые проводят больше времени, покупают (причинность может быть)
2. Люди, которые ХОТЯТ купить, проводят больше времени (обратная причинность)
3. Оба вызваны третьим фактором:
- Новые пользователи (обучаются дольше, реже покупают)
- Мотивированные пользователи (активнее, часто покупают)
Для проверки причинности нужен A/B тест, не корреляция.
Замечание 2: P-value важен
Корреляция: 0.45
P-value: 0.04 (< 0.05)
= Статистически значимо
Корреляция: 0.45
P-value: 0.25 (> 0.05)
= НЕ статистически значимо (может быть случайность)
Замечание 3: Размер выборки
Малая выборка:
Только 5 дней данных
Корреляция: 0.95
Вывод: Эта корреляция не надежна (слишком мало данных)
Большая выборка:
2 года данных (730 дней)
Корреляция: 0.72
Вывод: Эта корреляция надежна
Замечание 4: Разные типы корреляции
Pearson Correlation
- Для линейных зависимостей
- Чувствительна к outliers
df['x'].corr(df['y'], method='pearson')
Spearman Correlation
- Для монотонных зависимостей (не обязательно линейных)
- Менее чувствительна к outliers
df['x'].corr(df['y'], method='spearman')
Kendall Correlation
- Еще более robust к outliers
- Используется реже
df['x'].corr(df['y'], method='kendall')
6. Лучшие практики
DO:
- Всегда проверяй p-value (нужно < 0.05)
- Используй достаточно данных (минимум 30 точек)
- Проверяй scatter plot визуально перед выводами
- Используй разные методы (Pearson + Spearman) если подозреваешь outliers
- Не забывай про confounding variables
DON'T:
- Не интерпретируй корреляцию как причинность
- Не сравнивай корреляции из выборок разного размера
- Не делай выводы на основе 5-10 точек данных
- Не забывай про selection bias (может быть выбор в данных)
- Не игнорируй extreme values (outliers могут исказить корреляцию)
7. Реальный рабочий workflow
-- 1. Быстрая проверка корреляции
SELECT CORR(metric_a, metric_b) FROM data;
-- 2. Если интересно:
-- Посчитай по периодам
SELECT
DATE_TRUNC('month', date) as month,
CORR(metric_a, metric_b) as monthly_corr
FROM data
GROUP BY DATE_TRUNC('month', date);
-- 3. Посчитай по сегментам
SELECT
segment,
CORR(metric_a, metric_b) as corr
FROM data
GROUP BY segment;
-- 4. Если корреляция интересная:
-- Посчитай лаг (может быть metric_b отстает на день?)
SELECT
CORR(metric_a, LAG(metric_b) OVER (ORDER BY date)) as corr_lag1
FROM data;
Заключение
Корреляция - это мощный инструмент для выявления связей между метриками. Но это только первый шаг:
- Найти корреляцию (SQL / Python)
- Проверить значимость (p-value > 0.05)
- Проверить визуально (scatter plot)
- Разобраться в причине (domain knowledge)
- Проверить причинность (A/B test, не корреляция)
Корреляция показывает что, причинность объясняет почему.