Cálculo del coeficiente de correlación de rango de Spearman en Python con Pandas

En esta guía, veremos cómo calcular la correlación de rango de Spearman manualmente y usando Python a través de la biblioteca Pandas, así como también entenderemos cómo funciona la correlación.

Introducción

Esta guía es una introducción al coeficiente de correlación de rango de Spearman, su cálculo matemático y su cálculo a través de la biblioteca pandas de Python. Construiremos varios ejemplos para obtener una comprensión básica de este coeficiente y demostraremos cómo visualizar la matriz de correlación a través de mapas de calor.

¿Qué es el coeficiente de correlación de rangos de Spearman?

La correlación de rango de Spearman está estrechamente relacionada con la correlación de Pearson, y ambos son un valor acotado, de -1 a 1 que denota una correlación entre dos variables.

If you'd like to read more about the alternative correlation coefficient - read our Guía del coeficiente de correlación de Pearson en Python.

El coeficiente de correlación de Pearson se calcula utilizando valores de datos sin procesar, mientras que la correlación de Spearman se calcula a partir de los rangos de valores individuales. Mientras que el coeficiente de correlación de Pearson es una medida de la relación lineal entre dos variables, el coeficiente de correlación de rango de Spearman mide la relación monótona entre un par de variables. Para comprender la correlación de Spearman, necesitamos una comprensión básica de funciones monótonas.

Funciones monótonas

Hay funciones monótonamente crecientes, monótonamente decrecientes y no monónicas.

Para una función monótonamente creciente, a medida que X aumenta, Y también aumenta (y no tiene que ser lineal). Para una función monótonamente decreciente, a medida que una variable aumenta, la otra disminuye (tampoco tiene que ser lineal). Una función no monótona es aquella en la que el aumento en el valor de una variable a veces puede conducir a un aumento y otras veces a una disminución en el valor de la otra variable.

El coeficiente de correlación de rango de Spearman mide la relación monótona entre dos variables. Sus valores oscilan entre -1 y +1 y se pueden interpretar como:

  • +1: Relación perfectamente monótonamente creciente
  • +0.8: Fuerte relación monótonamente creciente
  • +0.2: Relación monotónicamente creciente débil
  • 0: Relación no monótona
  • -0.2: Relación monótonamente decreciente débil
  • -0.8: Fuerte relación monótonamente decreciente
  • -1: Relación perfectamente monótonamente decreciente

Expresión matemática

Supongamos que tenemos \(n\) observaciones de dos variables aleatorias, \(X\) y \(Y\). Primero clasificamos todos los valores de ambas variables como \(X_r\) y \(Y_r\) respectivamente. El coeficiente de correlación de rango de Spearman se denota por \(r_s\) y se calcula mediante:

$$
r_s = \rho_{X_r,Y_r} = \frac{\text{COV}(X_r,Y_r)}{\text{STD}(X_r)\text{STD}(Y_r)} = \frac{n\sum\limits_{x_r\in X_r, y_r \in Y_r} x_r y_r - \sum\limits_{x_r\in X_r}x_r\sum\ límites_{y_r\in Y_r}y_r}{\sqrt{\Big(n\sum\limits_{x_r \in X_r} x_r^2 -(\sum\limits\ _{x_r\in X_r}x_r)^2\Big)}\sqrt{\Big(n\sum\limits_{y_r \in Y_r} y_r^2 - (\ sum\limits_{y_r\in Y_r}y_r)^2 \Big)}}
$$

Aquí, COV() es la covarianza y STD() es la desviación estándar. Antes de ver las funciones de Python para calcular este coeficiente, hagamos un cálculo de ejemplo a mano para comprender la expresión y apreciarla.

Cálculo de ejemplo {#cálculo de ejemplo}

Supongamos que nos dan algunas observaciones de las variables aleatorias \(X\) y \(Y\). El primer paso es convertir \(X\) y \(Y\) en \(X_r\) y \(Y_r\), que representan sus rangos correspondientes. También se necesitarían algunos valores intermedios, que se muestran a continuación:

$$\begin{matriz} X & = & \lbrack & {- 2} & {- 1} & 0 & 1 & 2 & \rbrack^{T} \ Y & = & \lbrack & 4 & 1 & 3 & 2 & 0 & \rbrack^{T} \ X_{r} & = & \lbrack & 1 & 2 & 3 & 4 & 5 & \rbrack^{T} \ Y_{r} & = & \lbrack & 5 & 2 & 4 & 3 & 1 & \rbrack^{T} \ X_{r}^{2} & = & \lbrack & 1 & 4 & 9 & 16 & 25 & \rbrack^{T} \ Y_{r}^{2} & = & \lbrack & 25 & 4 & 16 & 9 & 1 & \rbrack^{T} \ {X_{r}Y_{r}} & = & \lbrack & 5 & 4 & 12 & 12 & 5 & \rbrack^{T} \ \end{matriz}$$

Usemos la fórmula anterior para calcular la correlación de Spearman:

$$r_{s} = \frac{5 \ast 38 - (15)(15)}{\sqrt{(5 \ast 55 - 15^{2})}\sqrt{(5 \ast 55 - 15^ {2})}} = \frac{181}{532} = - 0,7$$

¡Excelente! Sin embargo, calcular esto manualmente lleva mucho tiempo, y el mejor uso de las computadoras es, bueno, calcular cosas para nosotros. Calcular la correlación de Spearman es realmente fácil y directo con las funciones integradas en Pandas.

Cálculo del coeficiente de correlación de rango de Spearman usando Pandas {#cálculo del coeficiente de correlación de rango de Spearman usando pandas}

Los diversos coeficientes de correlación, incluido Spearman, se pueden calcular a través del método corr() de la biblioteca Pandas.

Como argumento de entrada, la función corr() acepta el método que se usará para calcular la correlación (spearman en nuestro caso). El método se llama en un DataFrame, digamos de tamaño mxn, donde cada columna representa los valores de una variable aleatoria y m representa las muestras totales de cada variable.

Para n variables aleatorias, devuelve una matriz cuadrada nxn R. R(i,j) indica el coeficiente de correlación de rango de Spearman entre la variable aleatoria i y j. Como el coeficiente de correlación entre una variable y ella misma es 1, todas las entradas diagonales (i,i) son iguales a la unidad. En breve:

$$R(i,j) = \left{ \begin{matriz} r_{i,j} & {\text{~si~}i \neq j} \ 1 & \text{de lo contrario} \ \end{matriz} \right.$$

Tenga en cuenta que la matriz de correlación es simétrica como la correlación es simétrica, es decir, M(i,j)=M(j,i). Tomemos nuestro ejemplo simple de la sección anterior y veamos cómo usar la función corr() de Pandas:

1
2
3
4
import numpy as np
import pandas as pd
import seaborn as sns # For pairplots and heatmaps
import matplotlib.pyplot as plt

Usaremos Pandas para el cálculo en sí, Matplotlib con Seaborn para la visualización y Numpy para operaciones adicionales en los datos.

El siguiente código calcula la matriz de correlación de Spearman en el marco de datos x_simple. Tenga en cuenta los unos en las diagonales, lo que indica que el coeficiente de correlación de una variable consigo misma es, naturalmente, uno:

1
2
3
4
x_simple = pd.DataFrame([(-2,4),(-1,1),(0,3),(1,2),(2,0)],
                        columns=["X","Y"])
my_r = x_simple.corr(method="spearman")
print(my_r)
1
2
3
     X    Y
X  1.0 -0.7
Y -0.7  1.0

Visualización del coeficiente de correlación

Dada la estructura similar a una tabla de intensidades limitadas, [-1, 1]: una forma natural y conveniente de visualizar el coeficiente de correlación es un mapa de calor.

If you'd like to read more about heatmaps in Seaborn, read our Guía definitiva de mapas de calor en Seaborn con Python!

Un mapa de calor es una cuadrícula de celdas, donde a cada celda se le asigna un color según su valor, y esta forma visual de interpretar las matrices de correlación es mucho más fácil para nosotros que analizar números. Para tablas pequeñas como la salida anterior, está perfectamente bien. Pero con muchas variables, es mucho más difícil interpretar realmente lo que está pasando.

Definamos una función display_correlation() que calcule el coeficiente de correlación y lo muestre como un mapa de calor:

1
2
3
4
5
6
7
def display_correlation(df):
    r = df.corr(method="spearman")
    plt.figure(figsize=(10,6))
    heatmap = sns.heatmap(df.corr(), vmin=-1, 
                      vmax=1, annot=True)
    plt.title("Spearman Correlation")
    return(r)

Llamemos a display_correlation() en nuestro marco de datos r_simple para visualizar la correlación de Spearman:

1
r_simple=display_correlation(x_simple)

correlation values

Comprender el coeficiente de correlación de Spearman en ejemplos sintéticos {#comprender el coeficiente de correlación de Spearman en ejemplos sintéticos}

Para comprender el coeficiente de correlación de Spearman, generemos algunos ejemplos sintéticos que acentúen cómo funciona el coeficiente, antes de sumergirnos en ejemplos más naturales. Estos ejemplos nos ayudarán a comprender para qué tipo de relaciones este coeficiente es +1, -1 o cercano a cero.

Antes de generar los ejemplos, crearemos una nueva función auxiliar, plot_data_corr(), que llama a display_correlation() y traza los datos contra la variable X:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def plot_data_corr(df,title,color="green"):    
    r = display_correlation(df)
    fig, ax = plt.subplots(nrows=1, ncols=len(df.columns)-1,figsize=(14,3))
    for i in range(1,len(df.columns)):
        ax[i-1].scatter(df["X"],df.values[:,i],color=color)
        ax[i-1].title.set_text(title[i] +'\n r = ' + 
                             "{:.2f}".format(r.values[0,i]))
        ax[i-1].set(xlabel=df.columns[0],ylabel=df.columns[i])
    fig.subplots_adjust(wspace=.7)    
    plt.show()

Funciones monótonamente crecientes {#funciones monótonamente crecientes}

Generemos algunas funciones que aumentan monótonamente, usando Numpy, y echemos un vistazo al DataFrame una vez que se haya llenado con los datos sintéticos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
seed = 11
rand = np.random.RandomState(seed)
# Create a data frame using various monotonically increasing functions
x_incr = pd.DataFrame({"X":rand.uniform(0,10,100)})
x_incr["Line+"] = x_incr.X*2+1
x_incr["Sq+"] = x_incr.X**2
x_incr["Exp+"] = np.exp(x_incr.X)
x_incr["Cube+"] = (x_incr.X-5)**3

print(x_incr.head())
  X          Line+       Sq+         Exp+          Cube+

0 1,802697 4,605394 3,249716 6,065985 -32,685221 1 0.194752 1.389505 0.037929 1.215010 -110.955110 2 4,632185 10,264371 21,457140 102,738329 -0,049761 3 7.249339 15.498679 52.552920 1407.174809 11.380593 4 4,202036 9,404072 17,657107 66,822246 -0,508101

Ahora veamos el mapa de calor de la correlación de Spearman y la gráfica de varias funciones contra X:

1
plot_data_corr(x_incr,["X","2X+1","$X^2$","$e^X$","$(X-5)^3$"])

correlation heatmap

monotonically increasing functions

Podemos ver que para todos estos ejemplos, existe una relación perfectamente monótonamente creciente entre las variables. La correlación de Spearman es +1, independientemente de si las variables tienen una relación lineal o no lineal.

Pearson habría producido resultados muy diferentes aquí, ya que se calcula en función de la relación lineal entre las variables.

Siempre que Y aumente a medida que aumenta X, sin excepción, el coeficiente de correlación de rangos de Spearman será 1.

Funciones monótonamente decrecientes {#funciones monótonamente decrecientes}

Repitamos los mismos ejemplos en funciones monótonamente decrecientes. Volveremos a generar datos sintéticos y calcularemos la correlación de rango de Spearman. Primero, veamos las primeras 4 filas del DataFrame:

1
2
3
4
5
6
7
# Create a data matrix
x_decr = pd.DataFrame({"X":rand.uniform(0,10,100)})
x_decr["Line-"] = -x_decr.X*2+1
x_decr["Sq-"] = -x_decr.X**2
x_decr["Exp-"] = np.exp(-x_decr.X)
x_decr["Cube-"] = -(x_decr.X-5)**3
x_decr.head()
  X          Line-        Sq-          Exp-       Cube-

0 3.181872 -5.363744 -10.124309 0.041508 6.009985 1 2.180034 -3.360068 -4.752547 0.113038 22.424963 2 8.449385 -15.898771 -71.392112 0.000214 -41.041680 3 3,021647 -5,043294 -9,130350 0,048721 7,743039 4 4,382207 -7,764413 -19,203736 0,012498 0,235792

El mapa de calor de la matriz de correlación y el gráfico de las variables se muestran a continuación:

1
plot_data_corr(x_decr,["X","-2X+1","$-X^2$","$-e^X$","$-(X-5)^3$"],"blue")

correlation heatmap

monotonically decreasing functions

Funciones no monótonas {#funciones no monotónicas}

Los ejemplos a continuación son para varias funciones no monótonas. La última columna agregada al DataFrame es la de una variable independiente Rand, que no tiene asociación con X.

Estos ejemplos también deberían aclarar que la correlación de Spearman es una medida de monotonicidad de una relación entre dos variables. Un coeficiente cero no indica necesariamente que no haya relación, pero sí indica que no hay monotonicidad entre ellos.

Antes de generar datos sintéticos, definiremos otra función de ayuda, display_corr_pairs(), que llama a display_correlation() para mostrar el mapa de calor de la matriz de correlación y luego traza todos los pares de variables en el DataFrame contra cada uno. otro utilizando la biblioteca Seaborn.

En las diagonales, mostraremos el histograma de cada variable en color amarillo usando map_diag(). Debajo de las diagonales, haremos un diagrama de dispersión de todos los pares de variables. Como la matriz de correlación es simétrica, no necesitamos las gráficas por encima de las diagonales.

Vamos a mostrar también el coeficiente de correlación de Pearson para comparar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def display_corr_pairs(df,color="cyan"):
    s = set_title = np.vectorize(lambda ax,r,rho: ax.title.set_text("r = " + 
                                        "{:.2f}".format(r) + 
                                        '\n $\\rho$ = ' + 
                                        "{:.2f}".format(rho)) if ax!=None else None
                            )      

    r = display_correlation(df)
    rho = df.corr(method="pearson")
    g = sns.PairGrid(df,corner=True)
    g.map_diag(plt.hist,color="yellow")
    g.map_lower(sns.scatterplot,color="magenta")
    set_title(g.axes,r,rho)
    plt.subplots_adjust(hspace = 0.6)
    plt.show()    

Crearemos un DataFrame no monótono, x_non, con estas funciones de X:

  • Parábola: \( (X-5)^2 \)

  • Sin: \( \sin (\frac{X}{10}2\pi) \)

  • Frac: \( \frac{X-5}{(X-5)^2+1} \)

  • Rand: Números aleatorios en el rango [-1,1]

A continuación se muestran las primeras 4 líneas de x_non:

1
2
3
4
5
6
7
x_non = pd.DataFrame({"X":rand.uniform(0,10,100)})
x_non["Parabola"] = (x_non.X-5)**2
x_non["Sin"] = np.sin(x_non.X/10*2*np.pi)
x_non["Frac"] = (x_non.X-5)/((x_non.X-5)**2+1)
x_non["Rand"] = rand.uniform(-1,1,100)

print(x_non.head())
  X          Parabola    Sin         Frac        Rand

0 0.654466 18.883667 0.399722 -0.218548 0.072827 1 5,746559 0,557351 -0,452063 0,479378 -0,818150 2 6,879362 3,532003 -0,924925 0,414687 -0,868501 3 5,683058 0,466569 -0,416124 0,465753 0,337066 4 6,037265 1,075920 -0,606565 0,499666 0,583229

El coeficiente de correlación de Spearman entre diferentes pares de datos se ilustra a continuación:

1
display_corr_pairs(x_non)

correlation heatmap

funciones no monotónicas

Estos ejemplos muestran para qué tipo de datos la correlación de Spearman es cercana a cero y dónde tiene valores intermedios. Otra cosa a tener en cuenta es que la correlación de Spearman y el coeficiente de correlación de Pearson no siempre están de acuerdo entre sí, por lo que la falta de uno no significa la falta de otro.

Se usan para probar la correlación de diferentes facetas de los datos y no se pueden usar indistintamente. Si bien estarán de acuerdo en algunos casos, no siempre lo estarán.

Coeficiente de correlación de Spearman en el conjunto de datos Linnerud

Apliquemos el coeficiente de correlación de Spearman en un conjunto de datos real. Hemos elegido el conjunto de datos de ejercicio físico simple llamado linnerud de la Paquete sklearn.datasets para demostración:

1
import sklearn.datasets.load_linnerud

El siguiente código carga el conjunto de datos y une las variables y atributos de destino en un DataFrame. Veamos las primeras 4 filas de los datos linnerud:

1
2
3
4
5
d=load_linnerud()

dat = pd.DataFrame(d.data,columns=d.feature_names)
alldat=dat.join(pd.DataFrame(d.target,columns=d.target_names) )
alldat.head()
  Chins   Situps   Jumps   Weight   Waist   Pulse

0 5,0 162,0 60,0 191,0 36,0 50,0 1 2,0 110,0 60,0 189,0 37,0 52,0 2 12,0 101,0 101,0 193,0 38,0 58,0 3 12,0 105,0 37,0 162,0 35,0 62,0 4 13,0 155,0 58,0 189,0 35,0 46,0

Ahora, mostremos los pares de correlación usando nuestra función display_corr_pairs():

1
display_corr_pairs(alldat)

correlation heatmap

physical exercise dataset correlation analysis

Mirando los valores de correlación de Spearman, podemos sacar conclusiones interesantes como:

  • Valores de cintura más altos implican valores de peso crecientes (desde r = 0.81)
  • Más abdominales tienen valores de cintura más bajos (desde r = -0.72)
  • Chins, situps y jumps no parecen tener una relación monótona con el pulso, ya que los valores de r correspondientes son cercanos a cero.

Yendo más lejos: proyecto de extremo a extremo portátil

¿Tu naturaleza inquisitiva te hace querer ir más allá? Recomendamos consultar nuestro Proyecto guiado: ["Predicción práctica del precio de la vivienda: aprendizaje automático en Python"](https://wikihtp.com/courses/hands-on-house- precio-predicción-aprendizaje-máquina-en-python/#cta){target="_blank"}.

[](https://wikihtp.com/ cursos/predicción-de-precio-de-la-casa-práctica-aprendizaje-de-máquina-en-python/#cta)

En este proyecto guiado, aprenderá a crear potentes modelos tradicionales de aprendizaje automático, así como modelos de aprendizaje profundo, utilizar Ensemble Learning y capacitar a los meta-aprendices para predecir los precios de la vivienda a partir de una bolsa de modelos Scikit-Learn y Keras.

Con Keras, la API de aprendizaje profundo creada sobre Tensorflow, experimentaremos con arquitecturas, crearemos un conjunto de modelos apilados y entrenaremos una red neuronal meta-aprendizaje (modelo de nivel 1) para averiguar el precio de un casa.

El aprendizaje profundo es sorprendente, pero antes de recurrir a él, se recomienda intentar resolver el problema con técnicas más simples, como los algoritmos de aprendizaje superficial. Nuestro rendimiento de referencia se basará en un algoritmo de Regresión de bosque aleatorio. Además, exploraremos la creación de conjuntos de modelos a través de Scikit-Learn a través de técnicas como embalaje y votación.

Este es un proyecto integral y, como todos los proyectos de aprendizaje automático, comenzaremos con Análisis exploratorio de datos, seguido de Preprocesamiento de datos y, finalmente, Creación de modelos de aprendizaje superficial y Profundo para ajustarse a los datos que hemos explorado y limpiado previamente.

Conclusiones

En esta guía, discutimos el coeficiente de correlación de rango de Spearman, su expresión matemática y su cálculo a través de la biblioteca pandas de Python.

Demostramos este coeficiente en varios ejemplos sintéticos y también en el conjunto de datos Linnerrud. El coeficiente de correlación de Spearman es una medida ideal para calcular la monotonicidad de la relación entre dos variables. Sin embargo, un valor cercano a cero no necesariamente indica que las variables no tengan asociación entre ellas.