Utilice .corr para obtener la correlación entre dos columnas

127

Tengo el siguiente marco de datos de pandas Top15: ingrese la descripción de la imagen aquí

Creo una columna que estima la cantidad de documentos citables por persona:

Top15['PopEst'] = Top15['Energy Supply'] / Top15['Energy Supply per Capita']
Top15['Citable docs per Capita'] = Top15['Citable documents'] / Top15['PopEst']

Quiero saber la correlación entre el número de documentos citables per cápita y el suministro de energía per cápita. Entonces utilizo el .corr()método (correlación de Pearson):

data = Top15[['Citable docs per Capita','Energy Supply per Capita']]
correlation = data.corr(method='pearson')

Quiero devolver un solo número, pero el resultado es: ingrese la descripción de la imagen aquí

tong zhu
fuente
Creo que tienes razón. Pero, ¿puede decirme por qué 'data.corr (method =' pearson ')' solo devuelve la relación entre el suministro de energía y el suministro de energía?
tong zhu
1
No es asi. Debería devolverle una matriz de 2x2; muestra su entrada superior izquierda. Si aplica .corrdirectamente a su marco de datos, devolverá todas las correlaciones por pares; es por eso que luego observa 1s en la diagonal de su matriz (cada columna está perfectamente correlacionada consigo misma). Vea mi edición a continuación.
Cleb
1
Considere aceptar una respuesta si cree que ha respondido a su pregunta
MaxU
1
He aceptado tu respuesta, gracias
tong zhu
29
Esta pregunta proviene directamente del curso "Introducción a la ciencia de datos en Python" en Coursera. Específicamente, tarea 3, pregunta 9. Cuando el instructor Chris Brooks anima a los estudiantes a publicar preguntas en Stack Overflow, no creo que quisiera decir que deberían publicar los problemas de las tareas textualmente.
LS

Respuestas:

210

Sin datos reales, es difícil responder la pregunta, pero supongo que está buscando algo como esto:

Top15['Citable docs per Capita'].corr(Top15['Energy Supply per Capita'])

Eso calcula la correlación entre sus dos columnas 'Citable docs per Capita' y 'Energy Supply per Capita'.

Para dar un ejemplo:

import pandas as pd

df = pd.DataFrame({'A': range(4), 'B': [2*i for i in range(4)]})

   A  B
0  0  0
1  1  2
2  2  4
3  3  6

Luego

df['A'].corr(df['B'])

da 1como se esperaba.

Ahora, si cambia un valor, p. Ej.

df.loc[2, 'B'] = 4.5

   A    B
0  0  0.0
1  1  2.0
2  2  4.5
3  3  6.0

El comando

df['A'].corr(df['B'])

devoluciones

0.99586

que todavía está cerca de 1, como se esperaba.

Si aplica .corrdirectamente a su marco de datos, devolverá todas las correlaciones por pares entre sus columnas ; es por eso que luego observa 1sen la diagonal de su matriz (cada columna está perfectamente correlacionada consigo misma).

df.corr()

por lo tanto volverá

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

En el gráfico que muestra, solo se representa la esquina superior izquierda de la matriz de correlación (supongo).

Puede haber casos en los que obtenga NaNs en su solución; consulte esta publicación para ver un ejemplo.

Si desea filtrar las entradas por encima o por debajo de un cierto umbral, puede marcar esta pregunta . Si desea trazar un mapa de calor de los coeficientes de correlación, puede verificar esta respuesta y si luego se encuentra con el problema de las etiquetas de eje superpuestas, consulte la siguiente publicación .

Cleb
fuente
¿Se puede aplicar esto por fila?
Dr.DOOM
1
@ Dr.DOOM: Sí, solo se necesitan series, por ejemplo df.loc[1, :].corr(df.loc[2, :]), también funcionará bien. Para toda la trama de datos, puede simplemente transponer: df.T.corr().
Cleb
Probé su sugerencia, sin embargo, el cálculo aún devuelve 1 incluso después de cambiar el valor a en la columna B usando df.loc [2, 'B'] = 4.5. tal vez estoy confundido en el cálculo
Dr.DOOM
@ Dr.DOOM: Es difícil ayudar porque no conozco su código. ¿Entendí correctamente que mi ejemplo anterior regresa 1en su caso en lugar de 0.99586?
Cleb
1
@Cleb: Bueno, en el contexto en el que estoy trabajando, cada índice de varias columnas de nivel superior tiene subcapas idénticas. Vea esta pregunta para lo que estoy tratando de hacer: stackoverflow.com/questions/57513002/…
Adrian Keister
7

Me encontré con el mismo problema. Parecía que Citable Documents per Personera un flotador y Python lo salta de alguna manera por defecto. Todas las otras columnas de mi marco de datos estaban en formatos numpy, así que lo resolví convirtiendo la columna anp.float64

Top15['Citable Documents per Person']=np.float64(Top15['Citable Documents per Person'])

Recuerde que es exactamente la columna que calculó usted mismo.

Gary
fuente
6

Mi solución sería después de convertir datos a tipo numérico:

Top15[['Citable docs per Capita','Energy Supply per Capita']].corr()
ibozkurt79
fuente
seleccionar columnas y luego aplicar el método .corr () es una buena opción ya que podemos calcular la correlación por pares entre más de 2 columnas
Sébastien Wieckowski
4

Si desea las correlaciones entre todos los pares de columnas, puede hacer algo como esto:

import pandas as pd
import numpy as np

def get_corrs(df):
    col_correlations = df.corr()
    col_correlations.loc[:, :] = np.tril(col_correlations, k=-1)
    cor_pairs = col_correlations.stack()
    return cor_pairs.to_dict()

my_corrs = get_corrs(df)
# and the following line to retrieve the single correlation
print(my_corrs[('Citable docs per Capita','Energy Supply per Capita')])
mgoldwasser
fuente
3

Cuando llamas a esto:

data = Top15[['Citable docs per Capita','Energy Supply per Capita']]
correlation = data.corr(method='pearson')

Dado que la función DataFrame.corr () realiza correlaciones por pares, tiene cuatro pares de dos variables. Entonces, básicamente está obteniendo valores diagonales como autocorrelación (correlación consigo mismo, dos valores ya que tiene dos variables), y otros dos valores como correlaciones cruzadas de uno contra otro y viceversa.

Realice la correlación entre dos series para obtener un valor único:

from scipy.stats.stats import pearsonr
docs_col = Top15['Citable docs per Capita'].values
energy_col = Top15['Energy Supply per Capita'].values
corr , _ = pearsonr(docs_col, energy_col)

o, si desea un solo valor de la misma función (corr. DataFrame):

single_value = correlation[0][1] 

Espero que esto ayude.

aumpen
fuente
3

Funciona así:

Top15['Citable docs per Capita']=np.float64(Top15['Citable docs per Capita'])

Top15['Energy Supply per Capita']=np.float64(Top15['Energy Supply per Capita'])

Top15['Energy Supply per Capita'].corr(Top15['Citable docs per Capita'])
Orca
fuente
1

Resolví este problema cambiando el tipo de datos. Si ve el 'Suministro de energía per cápita' es un tipo numérico, mientras que 'Documentos citables per cápita' es un tipo de objeto. Convertí la columna a flotar usando un tipo. Tuve el mismo problema con algunas funciones np: count_nonzeroy sumtrabajé mientras meany stdno lo hice.

OFERTA
fuente
0

cambiar 'Documentos citables per cápita' a numérico antes de la correlación resolverá el problema.

    Top15['Citable docs per Capita'] = pd.to_numeric(Top15['Citable docs per Capita'])
    data = Top15[['Citable docs per Capita','Energy Supply per Capita']]
    correlation = data.corr(method='pearson')
moinul hossain
fuente