Wykres macierzy korelacji za pomocą pand

Mam zbiór danych z ogromną liczbą funkcji, więc analiza macierzy korelacji stała się bardzo trudna. Chcę wykreślić macierz korelacji, którą otrzymamy za pomocą funkcji dataframe.corr() z biblioteki pandas. Czy jest jakaś wbudowana funkcja dostarczana przez Bibliotekę pandas do wykreślania tej macierzy?

Author: Fabian Rost, 2015-04-03

12 answers

Możesz użyć pyplot.matshow() from matplotlib:

import matplotlib.pyplot as plt

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

Edit:

W komentarzach pojawiła się prośba o zmianę etykiet Axis tick. Oto wersja deluxe, która jest rysowana na większym rozmiarze rysunku, ma etykiety osi pasujące do ramki danych i legendę paska kolorów do interpretacji skali kolorów.

Piszę o tym, jak dostosować rozmiar i obrót etykiet, i używam proporcji, która sprawia, że pasek kolorów i główna figura wychodzą tak samo wzrost.


Edycja 2: Jako df.metoda corr() ignoruje nie-numeryczne Kolumny, .select_dtypes(['number']) powinna być używana przy definiowaniu etykiet x i y, aby uniknąć niepożądanego przesunięcia etykiet (zawartych w kodzie poniżej).

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

przykład wykresu korelacji

 347
Author: jrjc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-08 19:10:08

Jeśli twoim głównym celem jest wizualizacja macierzy korelacji, a nie Tworzenie wykresu per se, wygodny pandas opcje stylizacji jest realnym rozwiązaniem wbudowanym:

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

Tutaj wpisz opis obrazka

Zauważ, że to musi być w backendzie obsługującym renderowanie HTML, takim jak Notatnik JupyterLab. (Automatyczny jasny tekst na ciemnym tle pochodzi z istniejącej PR, a nie najnowszej wersji, pandas 0.23).


Stylizacja

Można łatwo ograniczyć precyzję cyfr:

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

Tutaj wpisz opis obrazka

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

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

Tutaj wpisz opis obrazka

Dokumentacja stylów zawiera również instrukcje bardziej zaawansowanych stylów, na przykład jak zmienić wyświetlanie komórki, nad którą znajduje się wskaźnik myszy. Aby zapisać wyjście, możesz zwrócić kod HTML, dołączając render() metoda, a następnie zapisać go do pliku(lub po prostu zrobić zrzut ekranu dla mniej formalnych celów).


Porównanie czasu

W moich testach style.background_gradient() był 4x szybszy niż plt.matshow() i 120x szybszy niż sns.heatmap() z matrycą 10x10. Niestety nie skaluje się tak dobrze jak plt.matshow(): obie matryce zajmują mniej więcej ten sam czas dla matrycy 100x100, a plt.matshow() jest 10x Szybsze dla matrycy 1000x1000.


Zapisywanie

Istnieje kilka możliwych sposobów, aby zapisać stylizowane dataframe:

  • zwraca kod HTML, dołączając metodę render(), a następnie zapisuje wyjście do pliku.
  • Zapisz jako plik .xslx z formatowaniem warunkowym poprzez dodanie metody to_excel().
  • Połącz z imgkit, aby zapisać bitmapę
  • Zrób zrzut ekranu (dla mniej formalnych celów).

Aktualizacja dla pand >= 0.24

Ustawiając axis=None, można teraz obliczyć kolory na podstawie całej matrycy, a nie na kolumna lub w wierszu:

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

Tutaj wpisz opis obrazka

 227
Author: joelostblom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-20 05:28:21

Wersja heatmap Seaborna:

import seaborn as sns
corr = dataframe.corr()
sns.heatmap(corr, 
            xticklabels=corr.columns.values,
            yticklabels=corr.columns.values)
 102
Author: rafaelvalle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-24 22:45:06

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);
 93
Author: Apogentus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-13 13:16:16

Można zaobserwować zależność między cechami, rysując mapę ciepła z seaborna lub macierz rozproszenia z pand.

Macierz Rozpraszania:

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

Jeśli chcesz również wizualizować skośność każdej funkcji-Użyj pairplotów seaborn.

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)

Wyjściem będzie Mapa korelacji cech. czyli patrz poniższy przykład.

Tutaj wpisz opis obrazka

Korelacja między produktami spożywczymi i detergentami jest wysoka. Podobnie:

Pdodukty O Wysokiej Korelacji:
  1. Artykuły spożywcze i detergenty.
Produkty O Średniej Korelacji:
  1. mleko i produkty spożywcze
  2. mleko i Detergenty_papier
Produkty O Niskiej Korelacji:
  1. mleko i Delikatesy
  2. Mrożone i świeże. Mrożonki i Delikatesy.

From Pairplots: możesz obserwować ten sam zbiór relacji z pairplots lub macierzy rozproszonej. Ale z nich możemy powiedzieć, że czy dane są normalnie dystrybuowane lub nie.

Tutaj wpisz opis obrazka

Uwaga: powyższy wykres jest tym samym wykresem pobranym z danych, który jest używany do rysowania heatmap.

 86
Author: phanindravarma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-23 13:54:05

Dla kompletności, najprostsze rozwiązanie jakie znam z seaborn z końca 2019 roku, jeśli ktoś używa Jupyter :

import seaborn as sns
sns.heatmap(dataframe.corr())
 14
Author: Marcin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-08 08:01:37

Jeśli dataframe jest 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)
 10
Author: Harvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-15 21:06:18

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()
 9
Author: Khandelwal-manik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-19 05:20:29

Statmodels grafika daje również ładny widok macierzy 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()
 3
Author: Shahriar Miraj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-18 05:07:05

Wraz z innymi metodami dobrze jest również mieć parplot, który da wykres punktowy 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)
 2
Author: Nishant Tyagi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-24 07:11:20

Form correlation matrix, w moim przypadku zdf jest ramką danych, która musi 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)

Wtedy możemy zrobić zrzut ekranu. lub przekonwertować html na plik obrazu.

 1
Author: smsivaprakaash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-05 04:56:26

Zaskoczony, że nikt nie wspomniał o bardziej zdolnych, interaktywnych i łatwiejszych w użyciu alternatywach.

A) możesz użyć plotly:

  1. Tylko dwie linijki i otrzymujesz:

  2. Interaktywność,

  3. Gładka skala,

  4. Kolory oparte na całej ramce danych zamiast pojedynczych kolumn,

  5. Nazwy kolumn i indeksy wierszy na osiach,

  6. Zooming w,

  7. Panning,

  8. Wbudowana możliwość zapisania go jednym kliknięciem w formacie PNG,

  9. Automatyczne skalowanie,

  10. Porównanie na zawisanie,

  11. Bąbelki pokazujące wartości, dzięki czemu heatmap nadal wygląda dobrze i widać wartości gdziekolwiek chcesz:

import plotly.express as px
fig = px.imshow(df.corr())
fig.show()

Tutaj wpisz opis obrazka

B) Możesz również użyć Bokeh:

Wszystkie te same funkcje z trochę dużo kłopotów. Ale nadal warto, jeśli nie chcesz do opt-in for plotly and still want all these things:

from bokeh.plotting import figure, show, output_notebook
from bokeh.models import ColumnDataSource, LinearColorMapper
from bokeh.transform import transform
output_notebook()
colors = ['#d7191c', '#fdae61', '#ffffbf', '#a6d96a', '#1a9641']
TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"
data = df.corr().stack().rename("value").reset_index()
p = figure(x_range=list(df.columns), y_range=list(df.index), tools=TOOLS, toolbar_location='below',
           tooltips=[('Row, Column', '@level_0 x @level_1'), ('value', '@value')], height = 500, width = 500)

p.rect(x="level_1", y="level_0", width=1, height=1,
       source=data,
       fill_color={'field': 'value', 'transform': LinearColorMapper(palette=colors, low=data.value.min(), high=data.value.max())},
       line_color=None)
color_bar = ColorBar(color_mapper=LinearColorMapper(palette=colors, low=data.value.min(), high=data.value.max()), major_label_text_font_size="7px",
                     ticker=BasicTicker(desired_num_ticks=len(colors)),
                     formatter=PrintfTickFormatter(format="%f"),
                     label_standoff=6, border_line_color=None, location=(0, 0))
p.add_layout(color_bar, 'right')

show(p)

Tutaj wpisz opis obrazka

 0
Author: Hamza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-26 00:22:00