2017-01-04 42 views
7

Używam klasy Seaborn FacetGrid do wykreślenia zestawu macierzy za pomocą funkcji heatmap, również z Seaborn. Nie mogę jednak dostosować proporcji tych wątków. Oto przykład:Jak zrobić mapę cieplną kwadrat w Seaborn FacetGrid

import seaborn as sns 
import numpy as np 
import pandas as pd 

# Generate a set of sample data 
np.random.seed(0) 
indices = pd.MultiIndex.from_product((range(5), range(5), range(5)), names=('label0', 'label1', 'label2')) 
data = pd.DataFrame(np.random.uniform(0, 100, size=len(indices)), index=indices, columns=('value',)).reset_index() 

def draw_heatmap(*args, **kwargs): 
    data = kwargs.pop('data') 
    d = data.pivot(index=args[1], columns=args[0], values=args[2]) 
    sns.heatmap(d, **kwargs) 

fg = sns.FacetGrid(data, col='label0') 
fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False) 

która produkuje ten obrazek:

horizontal array of plots

Wskazówki w jaki sposób elementy działek macierzy są prostokątne, a nie kwadratu. Gdybym tworzył jedną działkę (bez FacetGrid), mógłbym przekazać opcję square=True do sns.heatmap, aby utworzyć kwadrat. Jednakże, jeśli mogę umieścić, że w argumentacji do map_dataframe, otrzymuję ten wynik:

fg = sns.FacetGrid(data, col='label0') 
fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square=True) 

array of plots made with square option

Wygląda osie są zbyt duże dla danych, chociaż stosunek domyślnego obrazu na FacetGrid to 1. (I jednoznacznie ustawienie aspect=1 przy konstruowaniu FacetGrid nie pomaga.)

Czy istnieje sposób, aby to naprawić?

+0

kwestionujesz przypadkowo rozwiązane na moje pytanie! (jak zrobić siatkę map ciepła). – anthonybell

Odpowiedz

2

Po ustawieniu aspect argumentu FacetGrid nie tylko ograniczenia osi, ale również rozmiary i położenia etykiet osi i tytułów są brane pod uwagę w celu obliczenia prawidłowej geometrii osi. Dlatego mapy termiczne to prostokąty.

Aby wyregulować kwadratową mapę cieplną i oś, można ręcznie skorygować położenie ramki ograniczającej osi za pomocą funkcji set_bbox.

Inny sposób jest nieco skomplikowany. Funkcja ax.set_aspect z drugim argumentem box_forced spróbuje dostosować mapę cieplną i oś. Jednak aby całkowicie usunąć pozostają szare granic można go schować, przez ustawienie koloru tła oś według rysunku twarzy koloru jak tutaj:

import seaborn as sns 
import numpy as np 
import pandas as pd 
import matplotlib.pylab as plt 

# Generate a set of sample data 
np.random.seed(0) 
indices = pd.MultiIndex.from_product((range(5), range(5), range(5)), 
names=('label0', 'label1', 'label2')) 
data = pd.DataFrame(np.random.uniform(0, 100, size=len(indices)), 
index=indices, columns=('value',)).reset_index() 

def draw_heatmap(*args, **kwargs): 
    data = kwargs.pop('data') 
    d = data.pivot(index=args[1], columns=args[0], values=args[2]) 
    sns.heatmap(d, **kwargs) 

fg = sns.FacetGrid(data, col='label0') 
fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square = True) 
# get figure background color 
facecolor=plt.gcf().get_facecolor() 
for ax in fg.axes.flat: 
    # set aspect of all axis 
    ax.set_aspect('equal','box-forced') 
    # set background color of axis instance 
    ax.set_axis_bgcolor(facecolor) 
plt.show() 

Wynik:

enter image description here