Корреляция Пирсона vs Спирмена — когда что использовать

Коротко

Корреляция Пирсона измеряет линейную связь между переменными. Корреляция Спирмена — монотонную (не обязательно линейную). Обе дают значение от −1 до +1. Пирсон чувствителен к выбросам и требует нормальности. Спирмен устойчивее — работает с рангами. Правило: данные нормальные и без выбросов → Пирсон. Ненормальные, порядковые или с выбросами → Спирмен. На собеседованиях аналитиков спрашивают разницу и когда что применять.

Быстрое сравнение

Критерий Пирсон (r) Спирмен (ρ)
Что измеряет Линейную связь Монотонную связь
Данные Непрерывные, нормальные Любые (в т.ч. порядковые)
Выбросы Чувствителен Устойчив
Формула По значениям По рангам
Когда r ≈ ρ Линейная зависимость, нет выбросов
Когда r ≠ ρ Нелинейная монотонная зависимость или выбросы

Корреляция Пирсона

Измеряет силу и направление линейной связи:

import numpy as np
from scipy import stats

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2.1, 4.0, 5.8, 8.2, 10.1, 11.9, 14.0, 16.2, 18.0, 19.8]

r, p_value = stats.pearsonr(x, y)
print(f'Пирсон r = {r:.4f}, p-value = {p_value:.6f}')
# Пирсон r = 0.9998, p-value = 0.000000

r = +1 — идеальная положительная линейная связь. r = 0 — нет линейной связи. r = −1 — идеальная отрицательная.

Интерпретация

| |r| | Сила связи | |-----|------------| | 0.9–1.0 | Очень сильная | | 0.7–0.9 | Сильная | | 0.5–0.7 | Средняя | | 0.3–0.5 | Слабая | | 0.0–0.3 | Очень слабая |

Корреляция Спирмена

Измеряет монотонную связь — через ранги значений:

rho, p_value = stats.spearmanr(x, y)
print(f'Спирмен ρ = {rho:.4f}, p-value = {p_value:.6f}')
# Спирмен ρ = 1.0000, p-value = 0.000000

Спирмен = Пирсон, применённый к рангам. Если x растёт и y растёт (монотонно), ρ близок к 1, даже если связь нелинейная.

Когда Спирмен ≠ Пирсон

# Нелинейная, но монотонная зависимость (экспоненциальная)
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]  # y = 2^x

r, _ = stats.pearsonr(x, y)       # 0.8892 — «сильная», но не идеальная
rho, _ = stats.spearmanr(x, y)    # 1.0000 — идеальная монотонная связь

Пирсон видит, что связь не линейная (r < 1). Спирмен видит, что связь идеально монотонная (ρ = 1). Для экспоненциальных и логарифмических зависимостей Спирмен информативнее.

Влияние выбросов

# Без выброса
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

r, _ = stats.pearsonr(x, y)     # 1.0000
rho, _ = stats.spearmanr(x, y)  # 1.0000

# С выбросом
y_outlier = [10, 20, 30, 40, 50, 60, 70, 80, 90, 500]

r, _ = stats.pearsonr(x, y_outlier)     # 0.8957 — упал
rho, _ = stats.spearmanr(x, y_outlier)  # 1.0000 — не изменился

Один выброс (500 вместо 100) сильно повлиял на Пирсона, но не на Спирмена. Спирмен работает с рангами — выброс остаётся на своём месте (последний ранг).

Расчёт в pandas

import pandas as pd

df = pd.DataFrame({
    'sessions': [10, 25, 50, 100, 200],
    'revenue': [500, 1200, 2800, 5500, 12000]
})

# Пирсон
df['sessions'].corr(df['revenue'], method='pearson')    # 0.9976

# Спирмен
df['sessions'].corr(df['revenue'], method='spearman')   # 1.0000

# Матрица корреляций
df.corr(method='pearson')
df.corr(method='spearman')

Визуализация матрицы корреляций

import seaborn as sns
import matplotlib.pyplot as plt

corr = df.corr(method='spearman')
sns.heatmap(corr, annot=True, cmap='coolwarm', center=0)
plt.title('Матрица корреляций (Спирмен)')
plt.show()

Расчёт в SQL

-- Корреляция Пирсона (PostgreSQL)
SELECT CORR(sessions, revenue) AS pearson_r
FROM user_metrics;

-- Спирмена в SQL нет встроенной — через ранги
WITH ranked AS (
    SELECT
        RANK() OVER (ORDER BY sessions) AS rank_sessions,
        RANK() OVER (ORDER BY revenue) AS rank_revenue
    FROM user_metrics
)
SELECT CORR(rank_sessions, rank_revenue) AS spearman_rho
FROM ranked;

PostgreSQL имеет встроенную CORR() для Пирсона. Для Спирмена — вычисляем ранги через оконные функции, потом Пирсона от рангов.

Когда что использовать

Пирсон

  • Данные непрерывные и примерно нормальные
  • Ожидаем линейную связь (revenue vs hours_worked)
  • Нет значимых выбросов
  • Нужна чувствительность к силе линейной зависимости

Спирмен

  • Данные порядковые (рейтинги, оценки от 1 до 5)
  • Есть выбросы
  • Зависимость монотонная, но не линейная
  • Распределение ненормальное (скошенное)
  • Не уверены — Спирмен безопаснее

Корреляция ≠ причинность

Высокая корреляция не означает причинно-следственную связь. Подробнее — в статье про корреляцию и причинность.

# Пример: продажи мороженого коррелируют с количеством утоплений
# Корреляция высокая, но причина — жаркая погода (confounding variable)

Типичные ошибки

Пирсон для нелинейной связи. Если y = x², Пирсон покажет 0, хотя связь очевидна. Проверяйте scatter plot перед расчётом.

Корреляция как причинность. r = 0.9 не значит, что X вызывает Y. Может быть обратная причинность (Y → X) или общий фактор.

Игнорирование p-value. r = 0.5 при n = 5 — не значимо. r = 0.1 при n = 10000 — значимо. Всегда смотрите на p-value вместе с r.

Вопросы с собеседований

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

-- Корреляция 0 — значит связи нет? -- Нет линейной (Пирсон) или монотонной (Спирмен) связи. Может быть нелинейная связь (параболическая). Всегда проверяйте scatter plot.

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

-- Как посчитать корреляцию в SQL? -- CORR(x, y) в PostgreSQL — корреляция Пирсона. Для Спирмена: вычислить ранги через RANK(), затем CORR() от рангов.


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

FAQ

Есть ли другие виды корреляции?

Кендалл (τ) — альтернатива Спирмену, более робастная при малых выборках. Точечно-бисериальная — связь бинарной и непрерывной переменных. Для большинства задач аналитика достаточно Пирсона и Спирмена.

Корреляция в pandas: какой метод по умолчанию?

df.corr() по умолчанию — Пирсон. Для Спирмена: df.corr(method='spearman'). Для Кендалла: df.corr(method='kendall').

Как тренироваться

Корреляция — обязательная тема на собеседованиях аналитика. Задачи на статистику — в тренажёре Карьерник. Больше вопросов — в разделе с примерами.