Use .corr para obter a correlação entre duas colunas

127

Eu tenho o seguinte quadro de dados de pandas Top15: insira a descrição da imagem aqui

Crio uma coluna que estima o número de documentos citáveis ​​por pessoa:

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

Quero conhecer a correlação entre o número de documentos citáveis ​​per capita e o suprimento de energia per capita. Então, eu uso o .corr()método (correlação de Pearson):

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

Quero retornar um único número, mas o resultado é: insira a descrição da imagem aqui

tong zhu
fonte
Eu acho que você está certo. Mas você pode me dizer por que o 'data.corr (method =' pearson ')' retorna apenas a relação entre o suprimento de energia e o suprimento de energia?
precisa
1
Isso não. Ele deve retornar uma matriz 2x2; você mostra sua entrada superior esquerda. Se você aplicar .corrdiretamente ao seu quadro de dados, ele retornará todas as correlações aos pares; é por isso que você observa 1s na diagonal de sua matriz (cada coluna está perfeitamente correlacionada com ela mesma). Veja minha edição abaixo.
cleb
1
Por favor, considere aceitar uma resposta se você acha que tem respondido à sua pergunta
MaxU
1
Eu aceitei a sua resposta, obrigado
tong Zhu
28
Esta questão é diretamente do curso "Introdução à ciência de dados em Python" no Coursera. Especificamente, tarefa 3, pergunta 9. Quando o instrutor Chris Brooks incentiva os alunos a postar perguntas no Stack Overflow, não acho que ele quis dizer que eles deveriam postar problemas das tarefas literalmente.
LS

Respostas:

209

Sem dados reais, é difícil responder à pergunta, mas acho que você está procurando algo parecido com isto:

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

Isso calcula a correlação entre suas duas colunas 'Citable docs per Capita' e 'Energy Supply per Capita'.

Para dar um exemplo:

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

Então

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

1como esperado.

Agora, se você alterar um valor, por exemplo

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

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

o comando

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

retorna

0.99586

que ainda está próximo de 1, como esperado.

Se você aplicar .corrdiretamente ao seu quadro de dados, ele retornará todas as correlações aos pares entre suas colunas ; é por isso que você observa 1sna diagonal de sua matriz (cada coluna está perfeitamente correlacionada consigo mesma).

df.corr()

retornará, portanto,

          A         B
A  1.000000  0.995862
B  0.995862  1.000000

No gráfico que você mostra, apenas o canto superior esquerdo da matriz de correlação é representado (presumo).

Pode haver casos em que você obtém NaNs em sua solução - verifique este post como exemplo.

Se você deseja filtrar entradas acima / abaixo de um determinado limite, pode verificar esta pergunta . Se você deseja plotar um mapa de calor dos coeficientes de correlação, pode verificar esta resposta e, se encontrar o problema com rótulos de eixo sobrepostos, verifique a seguinte postagem .

Cleb
fonte
isso pode ser aplicado por linha?
precisa saber é o seguinte
1
@ Dr.DOOM: Sim, são necessárias apenas séries, por exemplo df.loc[1, :].corr(df.loc[2, :]), também funcionará bem. Para toda a trama de dados, você pode simplesmente transpor: df.T.corr().
cleb
Tentei sua sugestão, no entanto, o cálculo ainda retorna 1, mesmo após alterar o valor a na coluna B usando df.loc [2, 'B'] = 4.5. Talvez Im apenas confuso sobre a computação
Dr.DOOM
@ Dr.DOOM: Difícil ajudar, pois não conheço seu código. Entendi corretamente que meu exemplo acima retorna 1no seu caso em vez de 0.99586?
cleb
1
@ Cleb: Bem, no contexto em que estou trabalhando, todo índice de várias colunas de nível superior tem sub-camadas idênticas. Veja esta pergunta para o que estou tentando fazer: stackoverflow.com/questions/57513002/...
Adrian Keister
7

Eu tive o mesmo problema. Parecia Citable Documents per Personum float e o python o ignora de alguma forma por padrão. Todas as outras colunas do meu dataframe estavam em formatos numpy, então resolvi convertendo o columnt paranp.float64

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

Lembre-se de que é exatamente a coluna que você calculou

Gary
fonte
6

Minha solução seria depois da conversão de dados para o tipo numérico:

Top15[['Citable docs per Capita','Energy Supply per Capita']].corr()
ibozkurt79
fonte
seleccionando colunas e em seguida aplicando o método .corr () é uma boa opção como se pode calcular a correlação de pares entre mais do que 2 colunas
Sebastien Wieckowski
4

Se você deseja as correlações entre todos os pares de colunas, pode fazer algo assim:

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
fonte
3

Quando você chama isso:

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

Como a função DataFrame.corr () executa correlações entre pares, você tem quatro pares de duas variáveis. Então, basicamente, você está obtendo valores diagonais como correlação automática (correlação consigo mesma, dois valores desde que você tem duas variáveis) e outros dois valores como correlações cruzadas entre um e outro e vice-versa.

Execute a correlação entre duas séries para obter um único valor:

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)

ou, se você deseja um único valor da mesma função (corr do DataFrame):

single_value = correlation[0][1] 

Espero que isto ajude.

aumpen
fonte
3

Funciona assim:

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
fonte
1

Resolvi esse problema alterando o tipo de dados. Se você vir 'Fornecimento de energia per capita' é um tipo numérico, enquanto 'Documentos citáveis ​​per capita' é um tipo de objeto. Eu converti a coluna para flutuar usando astype. Eu tive o mesmo problema com algumas funções np: count_nonzeroe sumtrabalhou enquanto meane stdnão o fez.

LICITAÇÃO
fonte
0

alterar 'Documentos citáveis ​​per capita' para numérico antes que a correlação resolva o 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
fonte