Plotar matriz de correlação usando pandas


211

Eu tenho um conjunto de dados com um grande número de recursos, portanto, analisar a matriz de correlação se tornou muito difícil. Eu quero traçar uma matriz de correlação que obtemos usando a dataframe.corr()função da biblioteca de pandas. Existe alguma função interna fornecida pela biblioteca do pandas para plotar essa matriz?


Respostas relacionadas podem ser encontrados aqui Fazendo heatmap de pandas trama de dados
joelostblom

Respostas:


291

Você pode usar pyplot.matshow() em matplotlib:

import matplotlib.pyplot as plt

plt.matshow(dataframe.corr())
plt.show()

Editar:

Nos comentários, havia uma solicitação de como alterar os rótulos dos marcadores do eixo. Aqui está uma versão de luxo desenhada em um tamanho de figura maior, com rótulos de eixo para corresponder ao quadro de dados e uma legenda da barra de cores para interpretar a escala de cores.

Estou incluindo como ajustar o tamanho e a rotação dos rótulos e estou usando uma proporção de figura que faz com que a barra de cores e a figura principal tenham a mesma altura.

f = plt.figure(figsize=(19, 15))
plt.matshow(df.corr(), fignum=f.number)
plt.xticks(range(df.shape[1]), df.columns, fontsize=14, rotation=45)
plt.yticks(range(df.shape[1]), df.columns, fontsize=14)
cb = plt.colorbar()
cb.ax.tick_params(labelsize=14)
plt.title('Correlation Matrix', fontsize=16);

exemplo de plotagem de correlação


1
Devo estar faltando alguma coisa:AttributeError: 'module' object has no attribute 'matshow'
Tom Russell

1
@TomRussell Você fez import matplotlib.pyplot as plt?
Joelostblom 5/06

1
Eu gostaria de pensar que sim! :-)
Tom Russell

7
você sabe como exibir os nomes das colunas reais no gráfico?
WebQube

2
@Cecilia eu tinha resolvido esta questão, alterando a rotação parâmetro para 90
ikbel benabdessamad

182

Se seu objetivo principal é visualizar a matriz de correlação, em vez de criar um gráfico propriamente dito, as convenientes pandas opções de estilo são uma solução interna viável:

import pandas as pd
import numpy as np

rs = np.random.RandomState(0)
df = pd.DataFrame(rs.rand(10, 10))
corr = df.corr()
corr.style.background_gradient(cmap='coolwarm')
# 'RdBu_r' & 'BrBG' are other good diverging colormaps

insira a descrição da imagem aqui

Observe que isso precisa estar em um back-end que suporte a renderização HTML, como o Notebook JupyterLab. (O texto claro automático em fundos escuros é de um PR existente e não da versão mais recente lançada, pandas0,23).


Styling

Você pode limitar facilmente a precisão dos dígitos:

corr.style.background_gradient(cmap='coolwarm').set_precision(2)

insira a descrição da imagem aqui

Ou se livrar dos dígitos completamente, se você preferir a matriz sem anotações:

corr.style.background_gradient(cmap='coolwarm').set_properties(**{'font-size': '0pt'})

insira a descrição da imagem aqui

A documentação de estilo também inclui instruções de estilos mais avançados, como alterar a exibição da célula sobre a qual o ponteiro do mouse está passando o mouse. Para salvar a saída, você pode retornar o HTML anexando o render()método e depois gravá-lo em um arquivo (ou apenas fazer uma captura de tela para fins menos formais).


Comparação de tempo

Nos meus testes, style.background_gradient()foi 4x mais rápido que plt.matshow()e 120x mais rápido que sns.heatmap()com uma matriz 10x10. Infelizmente, não é tão dimensionável quanto plt.matshow(): os dois demoram quase o mesmo tempo para uma matriz 100x100 e plt.matshow()são 10x mais rápidos para uma matriz 1000x1000.


Salvando

Existem algumas maneiras possíveis de salvar o quadro de dados estilizado:

  • Retorne o HTML anexando o render() método e, em seguida, grave a saída em um arquivo.
  • Salve como um .xslxarquivo com formatação condicional anexando o to_excel()método
  • Combine com imgkit para salvar um bitmap
  • Faça uma captura de tela (para fins menos formais).

Atualização para pandas> = 0,24

Ao definir axis=None, agora é possível calcular as cores com base em toda a matriz, e não por coluna ou linha:

corr.style.background_gradient(cmap='coolwarm', axis=None)

insira a descrição da imagem aqui


2
Se houvesse uma maneira de exportar é como uma imagem, isso seria ótimo!
Kristada673

1
Obrigado! Você definitivamente precisa de uma paleta divergenteimport seaborn as sns corr = df.corr() cm = sns.light_palette("green", as_cmap=True) cm = sns.diverging_palette(220, 20, sep=20, as_cmap=True) corr.style.background_gradient(cmap=cm).set_precision(2)
stallingOne

1
@stallingOne Bom ponto, eu não deveria ter incluído valores negativos no exemplo, posso mudar isso mais tarde. Apenas para referência para as pessoas que estão lendo isso, não é necessário criar um cmap divergente personalizado com o seaborn (embora o comentado acima pareça bastante liso), você também pode usar os cmaps divergentes integrados do matplotlib, por exemplo corr.style.background_gradient(cmap='coolwarm'). Atualmente, não há como centralizar o cmap em um valor específico, o que pode ser uma boa ideia com cmaps divergentes.
Joelostblom 5/07

1
@rovyko Você está em pandas> = 0.24.0?
Joelostblom 6/03/19

2
Esses gráficos são visualmente ótimos, mas a pergunta @ Kristada673 é bastante relevante, como você os exportaria?
Erfan

89

Experimente esta função, que também exibe nomes de variáveis ​​para a matriz de correlação:

def plot_corr(df,size=10):
    '''Function plots a graphical correlation matrix for each pair of columns in the dataframe.

    Input:
        df: pandas DataFrame
        size: vertical and horizontal size of the plot'''

    corr = df.corr()
    fig, ax = plt.subplots(figsize=(size, size))
    ax.matshow(corr)
    plt.xticks(range(len(corr.columns)), corr.columns);
    plt.yticks(range(len(corr.columns)), corr.columns);

6
plt.xticks(range(len(corr.columns)), corr.columns, rotation='vertical')se você quiser orientação vertical de nomes de colunas em x-axis
nishant

Outra coisa gráfica, mas adicionar um plt.tight_layout()também pode ser útil para nomes longos de colunas.
User3017048 28/05/19

86

Versão do mapa de calor do Seaborn:

import seaborn as sns
corr = dataframe.corr()
sns.heatmap(corr, 
            xticklabels=corr.columns.values,
            yticklabels=corr.columns.values)

9
O mapa de calor marítimo é sofisticado, mas apresenta baixo desempenho em matrizes grandes. O método mattshow do matplotlib é muito mais rápido.
Anilbey

3
O Seaborn pode inferir automaticamente os rótulos dos nomes das colunas.
Tulio Casagrande

80

Você pode observar a relação entre os recursos desenhando um mapa de calor do mar ou a matriz de dispersão dos pandas.

Matriz de dispersão:

pd.scatter_matrix(dataframe, alpha = 0.3, figsize = (14,8), diagonal = 'kde');

Se você deseja visualizar a assimetria de cada recurso também - use gráficos de pares marítimos.

sns.pairplot(dataframe)

Sns Heatmap:

import seaborn as sns

f, ax = pl.subplots(figsize=(10, 8))
corr = dataframe.corr()
sns.heatmap(corr, mask=np.zeros_like(corr, dtype=np.bool), cmap=sns.diverging_palette(220, 10, as_cmap=True),
            square=True, ax=ax)

A saída será um mapa de correlação dos recursos. ou seja, veja o exemplo abaixo.

insira a descrição da imagem aqui

A correlação entre mercearia e detergentes é alta. Similarmente:

Pdodutos com alta correlação:
  1. Mercearia e detergentes.
Produtos com correlação média:
  1. Leite e Mercearia
  2. Leite e Detergentes_ Papel
Produtos com baixa correlação:
  1. Milk and Deli
  2. Congelado e Fresco.
  3. Congelado e Deli.

Dos gráficos em pares: é possível observar o mesmo conjunto de relações dos gráficos em pares ou da matriz de dispersão. Mas a partir disso, podemos dizer que, se os dados são normalmente distribuídos ou não.

insira a descrição da imagem aqui

Nota: O gráfico acima é o mesmo retirado dos dados, usado para desenhar o mapa de calor.


3
Eu acho que deveria ser .plt não .pl (se este está se referindo a matplotlib)
ghukill

2
@ghukill Não é necessário. Ele poderia ter referido como #from matplotlib import pyplot as pl
Jeru Luke 14/10

como para definir o limite da correlação entre -1 a +1 sempre, na curva de correlação
debaonline4u

7

Você pode usar o método imshow () no matplotlib

import pandas as pd
import matplotlib.pyplot as plt
plt.style.use('ggplot')

plt.imshow(X.corr(), cmap=plt.cm.Reds, interpolation='nearest')
plt.colorbar()
tick_marks = [i for i in range(len(X.columns))]
plt.xticks(tick_marks, X.columns, rotation='vertical')
plt.yticks(tick_marks, X.columns)
plt.show()

5

Se você é o dataframe, dfpode simplesmente usar:

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(15, 10))
sns.heatmap(df.corr(), annot=True)

3

Os gráficos statmodels também oferecem uma boa visão da matriz de correlação

import statsmodels.api as sm
import matplotlib.pyplot as plt

corr = dataframe.corr()
sm.graphics.plot_corr(corr, xnames=list(corr.columns))
plt.show()

2

Por uma questão de completude, a solução mais simples que conheço com os marinhos no final de 2019, se alguém estiver usando o Jupyter :

import seaborn as sns
sns.heatmap(dataframe.corr())

1

Juntamente com outros métodos, também é bom ter um gráfico de pares que fornecerá o gráfico de dispersão para todos os casos -

import pandas as pd
import numpy as np
import seaborn as sns
rs = np.random.RandomState(0)
df = pd.DataFrame(rs.rand(10, 10))
sns.pairplot(df)

0

Matriz de correlação de formulários, no meu caso, zdf é o quadro de dados que eu preciso para executar a matriz de correlação.

corrMatrix =zdf.corr()
corrMatrix.to_csv('sm_zscaled_correlation_matrix.csv');
html = corrMatrix.style.background_gradient(cmap='RdBu').set_precision(2).render()

# Writing the output to a html file.
with open('test.html', 'w') as f:
   print('<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-widthinitial-scale=1.0"><title>Document</title></head><style>table{word-break: break-all;}</style><body>' + html+'</body></html>', file=f)

Então podemos tirar uma captura de tela. ou converter html em um arquivo de imagem.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.