Автор оригинала: Mehreen Saeed.
Вычисление коэффициента корреляции Пирсона в Python с помощью Numpy
Вступление
Эта статья представляет собой введение в коэффициент корреляции Пирсона , его ручное вычисление и вычисление с помощью модуля Python numpy .
Коэффициент корреляции Пирсона измеряет линейную связь между переменными. Его значение можно интерпретировать следующим образом:
- +1 – Полная положительная корреляция
- +0.8 – Сильная положительная корреляция
- +0.6 – Умеренная положительная корреляция
- 0 – никакой корреляции вообще
- -0,6 – Умеренная отрицательная корреляция
- -0,8 – Сильная отрицательная корреляция
- -1 – Полная отрицательная корреляция
Проиллюстрируем, как изменяется коэффициент корреляции при различных типах ассоциаций. В этой статье мы также покажем, что нулевая корреляция не всегда означает нулевые ассоциации . Нелинейно связанные переменные могут иметь коэффициенты корреляции, близкие к нулю.
Что такое Коэффициент Корреляции Пирсона?
Коэффициент корреляции Пирсона также известен как Коэффициент корреляции Произведение Пирсона-Момент . Это мера линейной зависимости между двумя случайными величинами – X и Y . Математически, если ( σXY ) – ковариация между X и Y , а ( σX ) – стандартное отклонение X , то коэффициент корреляции Пирсона ρ задается формулой:
$$ \rho_{X,Y} = \frac{\sigma_{XY}}{\sigma_X \sigma_Y} $$
Поскольку ковариация всегда меньше произведения индивидуальных стандартных отклонений, значение ρ изменяется между -1 и +1 . Из вышесказанного видно также, что корреляция переменной с самой собой равна единице:
$$ \rho_{X,X} = \frac{\sigma_{XX}}{\sigma_X $$ Прежде чем мы начнем писать код, давайте сделаем короткий пример, чтобы увидеть, как вычисляется этот коэффициент.
Как вычисляется коэффициент корреляции Пирсона?
Предположим, что нам даны некоторые наблюдения случайных величин X и Y . Если вы планируете реализовать все с нуля или сделать некоторые ручные вычисления, то вам нужно следующее, когда заданы X и Y :
Давайте воспользуемся вышеизложенным для вычисления корреляции. Мы будем использовать предвзятую оценку ковариации и стандартных отклонений. Это не повлияет на значение вычисляемого коэффициента корреляции, так как количество наблюдений отменяется в числителе и знаменателе:
Коэффициент корреляции Пирсона в Python с использованием Numpy
Коэффициент корреляции Пирсона можно вычислить в Python с помощью метода corrcoef()
из Numpy.
Входными данными для этой функции обычно является матрица, скажем, размера mxn
, где:
- Каждый столбец представляет значения случайной величины
- Каждая строка представляет собой одну выборку
n
случайных величин n
представляет общее число различных случайных величинm
представляет общее количество выборок для каждой переменной
Для n
случайных величин он возвращает nxn
квадратную матрицу M
, причем M(i,j)
указывает коэффициент корреляции между случайной величиной i
и j
. Поскольку коэффициент корреляции между переменной и самой собой равен 1, все диагональные записи (i,i)
равны единице.
Короче говоря:
Во-первых, давайте импортируем модуль numpy
вместе с модулем pyplot
из Matplotlib. Позже мы будем использовать Matplotlib для визуализации корреляции:
import numpy as np import matplotlib.pyplot as plt
Мы будем использовать те же значения из предыдущего ручного примера. Давайте сохраним это в x_simple
и вычислим корреляционную матрицу:
x_simple = np.array([-2, -1, 0, 1, 2]) y_simple = np.array([4, 1, 3, 2, 0]) my_rho = np.corrcoef(x_simple, y_simple) print(my_rho)
Ниже приведена выходная корреляционная матрица. Обратите внимание на диагонали, указывающие на то, что коэффициент корреляции переменной с самой собой равен единице:
[[ 1. -0.7] [-0.7 1. ]]
Примеры положительной и отрицательной корреляции
Давайте визуализируем коэффициенты корреляции для нескольких взаимосвязей. Во-первых, у нас будет полная положительная (+1) и полная отрицательная (-1) корреляция между двумя переменными. Затем мы сгенерируем две случайные величины, так что коэффициент корреляции непременно должен быть близок к нулю, если только случайность случайно не имеет какой-то корреляции, что крайне маловероятно.
Мы будем использовать seed
, чтобы этот пример можно было повторить при вызове Random State
из Numpy:
seed = 13 rand = np.random.RandomState(seed) x = rand.uniform(0,1,100) x = np.vstack((x,x*2+1)) x = np.vstack((x,-x[0,]*2+1)) x = np.vstack((x,rand.normal(1,3,100)))
Первый вызов rand.uniform()
генерирует случайное равномерное распределение:
[7.77702411e-01 2.37541220e-01 8.24278533e-01 9.65749198e-01 9.72601114e-01 4.53449247e-01 6.09042463e-01 7.75526515e-01 6.41613345e-01 7.22018230e-01 3.50365241e-02 2.98449471e-01 5.85124919e-02 8.57060943e-01 3.72854028e-01 6.79847952e-01 2.56279949e-01 3.47581215e-01 9.41277008e-03 3.58333783e-01 9.49094182e-01 2.17899009e-01 3.19391366e-01 9.17772386e-01 3.19036664e-02 6.50845370e-02 6.29828999e-01 8.73813443e-01 8.71573230e-03 7.46577237e-01 8.12841171e-01 7.57174462e-02 6.56455335e-01 5.09262200e-01 4.79883391e-01 9.55574145e-01 1.20335695e-05 2.46978701e-01 7.12232678e-01 3.24582050e-01 2.76996356e-01 6.95445453e-01 9.18551748e-01 2.44475702e-01 4.58085817e-01 2.52992683e-01 3.79333291e-01 6.04538829e-01 7.72378760e-01 6.79174968e-02 6.86085079e-01 5.48260097e-01 1.37986053e-01 9.87532192e-02 2.45559105e-01 1.51786663e-01 9.25994479e-01 6.80105016e-01 2.37658922e-01 5.68885253e-01 5.56632051e-01 7.27372109e-02 8.39708510e-01 4.05319493e-01 1.44870989e-01 1.90920059e-01 4.90640137e-01 7.12024374e-01 9.84938458e-01 8.74786502e-01 4.99041684e-01 1.06779994e-01 9.13212807e-01 3.64915961e-01 2.26587877e-01 8.72431862e-01 1.36358352e-01 2.36380160e-01 5.95399245e-01 5.63922609e-01 9.58934732e-01 4.53239333e-01 1.28958075e-01 7.60567677e-01 2.01634075e-01 1.75729863e-01 4.37118013e-01 3.40260803e-01 9.67253109e-01 1.43026077e-01 8.44558533e-01 6.69406140e-01 1.09304908e-01 8.82535400e-02 9.66462041e-01 1.94297485e-01 8.19000600e-02 2.69384695e-01 6.50130518e-01 5.46777245e-01]
Затем мы можем вызвать vstack ()
, чтобы вертикально сложить в него другие массивы. Таким образом, мы можем сложить кучу переменных, подобных приведенным выше, в одну и ту же ссылку x
и обращаться к ним последовательно.
После первого равномерного распределения мы сложили несколько наборов переменных вертикально – второй имеет полную положительную корреляцию с первым, третий имеет полную отрицательную корреляцию с первым, а четвертый полностью случайный, поэтому он должен иметь корреляцию ~0.
Когда у нас есть одна ссылка x
, подобная этой, мы можем вычислить корреляцию для каждого из элементов в вертикальном стеке, передав ее отдельно в np.corrcoef()
:
rho = np.corrcoef(x) fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(12, 3)) for i in [0,1,2]: ax[i].scatter(x[0,],x[1+i,]) ax[i].title.set_text('Correlation = ' + "{:.2f}".format(rho[0,i+1])) ax[i].set(xlabel='x',ylabel='y') fig.subplots_adjust(wspace=.4) plt.show()
Понимание изменений коэффициента корреляции Пирсона
Просто чтобы увидеть, как изменяется коэффициент корреляции с изменением отношения между двумя переменными, давайте добавим некоторый случайный шум к матрице x
, сгенерированной в предыдущем разделе, и повторно запустим код.
В этом примере мы будем медленно добавлять различные степени шума к корреляционным диаграммам и вычислять коэффициенты корреляции на каждом шаге:
fig, ax = plt.subplots(nrows=2, ncols=4, figsize=(15, 8)) for noise, i in zip([0.05,0.2,0.8,2],[0,1,2,3]): # Add noise x_with_noise = x+rand.normal(0,noise,x.shape) # Compute correlation rho_noise = np.corrcoef(x_with_noise) # Plot column wise. Positive correlation in row 0 and negative in row 1 ax[0,i].scatter(x_with_noise[0,],x_with_noise[1,],color='magenta') ax[1,i].scatter(x_with_noise[0,],x_with_noise[2,],color='green') ax[0,i].title.set_text('Correlation = ' + "{:.2f}".format(rho_noise[0,1]) + '\n Noise = ' + "{:.2f}".format(noise) ) ax[1,i].title.set_text('Correlation = ' + "{:.2f}".format(rho_noise[0,2]) + '\n Noise = ' + "{:.2f}".format(noise)) ax[0,i].set(xlabel='x',ylabel='y') ax[1,i].set(xlabel='x',ylabel='y') fig.subplots_adjust(wspace=0.3,hspace=0.4) plt.show()
Общая ловушка: Ассоциации без корреляции
Существует распространенное заблуждение, что нулевая корреляция не подразумевает никакой ассоциации. Поясним, что корреляция строго измеряет линейную связь между двумя переменными.
Приведенные ниже примеры показывают переменные, которые нелинейно связаны друг с другом, но имеют нулевую корреляцию.
Последний пример x ) имеет коэффициент корреляции около 0,52, что опять же не является отражением истинной связи между двумя переменными:
# Create a data matrix x_nonlinear = np.linspace(-10,10,100) x_nonlinear = np.vstack((x_nonlinear,x_nonlinear*x_nonlinear)) x_nonlinear = np.vstack((x_nonlinear,-x_nonlinear[0,]**2)) x_nonlinear = np.vstack((x_nonlinear,x_nonlinear[0,]**4)) x_nonlinear = np.vstack((x_nonlinear,np.log(x_nonlinear[0,]**2+1))) x_nonlinear = np.vstack((x_nonlinear,np.exp(x_nonlinear[0,]))) # Compute the correlation rho_nonlinear = np.corrcoef(x_nonlinear) # Plot the data fig, ax = plt.subplots(nrows=1, ncols=5, figsize=(16, 3)) title = ['$y=x^2$','$y=-x^2$','$y=x^4$','$y=\log(x^2+1)$','$y=\exp(x)$'] for i in [0,1,2,3,4]: ax[i].scatter(x_nonlinear[0,],x_nonlinear[1+i,],color='cyan') ax[i].title.set_text(title[i] + '\n' + 'Correlation = ' + "{:.2f}".format(rho_nonlinear[0,i+1])) ax[i].set(xlabel='x',ylabel='y') fig.subplots_adjust(wspace=.4) plt.show()
Выводы
В этой статье мы обсуждали коэффициент корреляции Пирсона. Мы использовали метод corrcoef()
из модуля Python numpy
для вычисления его значения.
Если случайные величины имеют высокие линейные ассоциации, то их коэффициент корреляции близок к +1 или -1. С другой стороны, статистически независимые переменные имеют коэффициенты корреляции, близкие к нулю.
Мы также показали, что нелинейные ассоциации могут иметь коэффициент корреляции нулевой или близкий к нулю, подразумевая, что переменные, имеющие высокие ассоциации, могут не иметь высокого значения коэффициента корреляции Пирсона.