Narysuj macierz korelacji za pomocą pand

212

Mam zestaw danych z ogromną liczbą funkcji, więc analiza macierzy korelacji stała się bardzo trudna. Chcę wykreślić macierz korelacji, którą otrzymujemy za pomocą dataframe.corr()funkcji z biblioteki pand. Czy biblioteka pand udostępnia jakąś wbudowaną funkcję do kreślenia tej macierzy?

Gaurav Singh
źródło
Powiązane odpowiedzi można znaleźć tutaj Tworzenie mapy
cieplnej

Odpowiedzi:

292

Możesz używać pyplot.matshow() z matplotlib:

import matplotlib.pyplot as plt

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

Edytować:

W komentarzach pojawiło się żądanie zmiany etykiet zaznaczenia osi. Oto wersja deluxe, która jest rysowana na większym rozmiarze figury, ma etykiety osi pasujące do ramki danych i legendę paska kolorów do interpretacji skali kolorów.

Obejmuję sposób dostosowania rozmiaru i obrotu etykiet oraz używam współczynnika kształtu, który sprawia, że ​​pasek koloru i główna postać mają tę samą wysokość.

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);

przykład wykresu korelacji

jrjc
źródło
1
Coś mi brakuje:AttributeError: 'module' object has no attribute 'matshow'
Tom Russell
1
@TomRussell Czy zrobiłeś import matplotlib.pyplot as plt?
joelostblom
1
Chciałbym tak myśleć! :-)
Tom Russell
7
Czy wiesz, jak wyświetlić rzeczywiste nazwy kolumn na wykresie?
WebQube,
2
@Cecilia Rozwiązałem tę sprawę, zmieniając parametr obrotu na 90
ikbel benabdessamad
182

Jeśli Twoim głównym celem jest wizualizacja matrycy korelacji, a nie tworzenie wykresu per se, wygodne pandas opcje stylizacji to realne wbudowane rozwiązanie:

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

wprowadź opis zdjęcia tutaj

Zauważ, że musi to być backend obsługujący renderowanie HTML, taki jak Notatnik JupyterLab. (Automatyczny jasny tekst na ciemnym tle pochodzi z istniejącego PR, a nie z najnowszej wydanej wersji, pandas0.23).


Stylizacja

Możesz łatwo ograniczyć precyzję cyfr:

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

wprowadź opis zdjęcia tutaj

Lub pozbądź się cyfr, jeśli wolisz matrycę bez adnotacji:

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

wprowadź opis zdjęcia tutaj

Dokumentacja stylów zawiera także instrukcje dotyczące bardziej zaawansowanych stylów, takich jak zmiana sposobu wyświetlania komórki, nad którą wskaźnik myszy najeżdża. Aby zapisać wynik, możesz zwrócić kod HTML, dodając render()metodę, a następnie zapisując go do pliku (lub po prostu zrób zrzut ekranu dla mniej formalnych celów).


Porównanie czasu

W moich testach style.background_gradient()był 4x szybszy plt.matshow()i 120x szybszy niż sns.heatmap()przy matrycy 10x10. Niestety nie skaluje się tak dobrze, jak plt.matshow(): oba zajmują mniej więcej tyle samo czasu dla matrycy 100 plt.matshow()x 100 i są 10 razy szybsze dla matrycy 1000 x 1000.


Oszczędność

Istnieje kilka możliwych sposobów zapisania stylizowanej ramki danych:

  • Zwróć kod HTML, dodając render()metodę, a następnie zapisz wynik w pliku.
  • Zapisz jako .xslxplik z formatowaniem warunkowym, dodając to_excel()metodę.
  • Połącz z imgkit, aby zapisać bitmapę
  • Zrób zrzut ekranu (do mniej formalnych celów).

Aktualizacja dla pand> = 0,24

Po ustawieniu axis=Nonemożliwe jest teraz obliczanie kolorów na podstawie całej macierzy, a nie według kolumny lub wiersza:

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

wprowadź opis zdjęcia tutaj

joelostblom
źródło
2
Gdyby istniał sposób na eksport jako obraz, byłoby świetnie!
Kristada673
1
Dzięki! Zdecydowanie potrzebujesz rozbieżnej paletyimport 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)
Jeden
1
@stallingOne Dobra uwaga, nie powinienem uwzględniać wartości ujemnych w przykładzie, mógłbym to zmienić później. Tylko dla odniesienia dla osób czytających to, nie musisz tworzyć niestandardowej rozbieżnej cmapy z dnem morskim (chociaż ta w komentarzu powyżej wygląda dość gładko), możesz również użyć wbudowanych rozbieżnych cmap z matplotlib, np corr.style.background_gradient(cmap='coolwarm'). Obecnie nie ma możliwości wyśrodkowania cmap na określonej wartości, co może być dobrym pomysłem w przypadku rozbieżnych cmap.
joelostblom
1
@rovyko Czy jesteś na pandach> = 0.24.0?
joelostblom
2
Te wykresy są świetne wizualnie, ale pytanie @ Kristada673 jest dość istotne, jak je wyeksportujesz?
Erfan
89

Wypróbuj tę funkcję, która wyświetla również nazwy zmiennych dla macierzy korelacji:

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);
Apogentus
źródło
6
plt.xticks(range(len(corr.columns)), corr.columns, rotation='vertical')jeśli chcesz orientację pionową nazw kolumn na osi X
nishant
Kolejna rzecz graficzna, ale dodanie plt.tight_layout()może być również przydatne w przypadku długich nazw kolumn.
user3017048
86

Wersja mapy termicznej Seaborn:

import seaborn as sns
corr = dataframe.corr()
sns.heatmap(corr, 
            xticklabels=corr.columns.values,
            yticklabels=corr.columns.values)
rafaelvalle
źródło
9
Mapa termiczna Seaborn jest fantazyjna, ale działa słabo na dużych matrycach. Metoda matshow programu matplotlib jest znacznie szybsza.
anilbey
3
Seaborn może automatycznie wywnioskować etykiety z nazw kolumn.
Tulio Casagrande
80

Zależność między obiektami można zaobserwować, rysując mapę cieplną z dna morskiego lub matrycę rozpraszającą z pand.

Matryca rozproszenia:

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

Jeśli chcesz również wizualizować skośność każdej cechy - użyj wykresów par morskich.

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)

Wynikiem będzie mapa korelacji cech. tj. patrz poniższy przykład.

wprowadź opis zdjęcia tutaj

Korelacja między sklepem spożywczym a detergentami jest wysoka. Podobnie:

Pdoducts o wysokiej korelacji:
  1. Artykuły spożywcze i detergenty.
Produkty o średniej korelacji:
  1. Mleko i artykuły spożywcze
  2. Mleko i detergenty_Papier
Produkty o niskiej korelacji:
  1. Milk and Deli
  2. Mrożone i świeże.
  3. Mrożone i delikatesowe.

Z wykresów par: Możesz obserwować ten sam zestaw relacji ze wykresów par lub macierzy rozproszenia. Ale z nich możemy powiedzieć, czy dane są zwykle dystrybuowane, czy nie.

wprowadź opis zdjęcia tutaj

Uwaga: powyższy wykres jest taki sam, jak dane zaczerpnięte z danych, które służą do rysowania mapy cieplnej.

phanindravarma
źródło
3
Myślę, że powinien to być .plt nie .pl (jeśli dotyczy to matplotlib)
ghukill
2
@ghukill Niepotrzebnie. Mógłby to from matplotlib import pyplot as pl
nazwać
jak ustawić granicę korelacji od -1 do +1 zawsze, na wykresie korelacji
debaonline4u
7

Możesz użyć metody imshow () z 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()
Khandelwal-manik
źródło
5

Jeśli masz ramkę danych df, możesz po prostu użyć:

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(15, 10))
sns.heatmap(df.corr(), annot=True)
Harvey
źródło
3

Grafika statmodels daje również ładny widok matrycy korelacji

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

corr = dataframe.corr()
sm.graphics.plot_corr(corr, xnames=list(corr.columns))
plt.show()
Shahriar Miraj
źródło
3

Dla kompletności najprostsze rozwiązanie, jakie znam z dnem morskim pod koniec 2019 r., Jeśli używasz Jupyter :

import seaborn as sns
sns.heatmap(dataframe.corr())
Marcin
źródło
1

Oprócz innych metod dobrze jest mieć również wykres parowania, który da wykres rozproszenia dla wszystkich przypadków -

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)
Nishant Tyagi
źródło
0

Formularz macierzy korelacji, w moim przypadku zdf to ramka danych, której potrzebuję wykonać macierz korelacji.

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)

Następnie możemy zrobić zrzut ekranu. lub przekonwertować HTML na plik obrazu.

smsivaprakaash
źródło