2016-08-08 17 views
8

Korzystam z danych tutaj przedstawionych do skonstruowania tej mapy termicznej przy użyciu ptaków morskich i pand.Odrębna legenda na wykresie mapy termicznej seaborn

pliku CSV wejście jest tutaj: https://www.dropbox.com/s/5jc1vr6u8j7058v/LUH2_trans_matrix.csv?dl=0

Kod:

import pandas 
    import seaborn.apionly as sns 

    # Read in csv file 
    df_trans = pandas.read_csv('LUH2_trans_matrix.csv') 

    sns.set(font_scale=0.8) 
    cmap = sns.cubehelix_palette(start=2.8, rot=.1, light=0.9, as_cmap=True) 
    cmap.set_under('gray') # 0 values in activity matrix are shown in gray (inactive transitions) 
    df_trans = df_trans.set_index(['Unnamed: 0']) 
    ax = sns.heatmap(df_trans, cmap=cmap, linewidths=.5, linecolor='lightgray') 

    # X - Y axis labels 
    ax.set_ylabel('FROM') 
    ax.set_xlabel('TO') 

    # Rotate tick labels 
    locs, labels = plt.xticks() 
    plt.setp(labels, rotation=0) 
    locs, labels = plt.yticks() 
    plt.setp(labels, rotation=0) 

    # revert matplotlib params 
    sns.reset_orig() 

Jak widać z pliku csv, zawiera 3 wartości dyskretnych: 0, -1 i 1. Chcę dyskretnej legenda zamiast paska kolorów. Oznakowanie 0 jako A, -1 jako B i 1 jako C. Jak mogę to zrobić?

+0

Proszę podać próbkę danych jako tekst, SO ppl nie jest prawdopodobne, aby pobrać plik nieznanego do swoich maszyn. – Merlin

+1

dzięki @Merlin, dodane dane w formie tekstowej oraz – user308827

+1

Spójrz na to: [https://github.com/mwaskom/seaborn/issues/858](https://github.com/mwaskom/seaborn/issues/ 858) –

Odpowiedz

7

Cóż, na pewno więcej niż jeden sposób, aby tego dokonać. W tym przypadku, przy użyciu tylko trzech kolorów, sam bym wybrał kolory, tworząc LinearSegmentedColormap zamiast generowania ich za pomocą cubehelix_palette. Jeśli było wystarczająco kolorów, aby zagwarantować użycie cubehelix_palette, zdefiniowałbym segmenty na mapie kolorów za pomocą opcji boundaries parametru cbar_kws. Tak czy inaczej, tyknięcia można określić ręcznie za pomocą set_ticks i set_ticklabels.

Poniższy przykładowy kod demonstruje ręczne utworzenie LinearSegmentedColormap i zawiera komentarze dotyczące sposobu określania granic, jeśli zamiast tego używa się cubehelix_palette.

import matplotlib.pyplot as plt 
import pandas 
import seaborn.apionly as sns 
from matplotlib.colors import LinearSegmentedColormap 

sns.set(font_scale=0.8) 
dataFrame = pandas.read_csv('LUH2_trans_matrix.csv').set_index(['Unnamed: 0']) 

# For only three colors, it's easier to choose them yourself. 
# If you still really want to generate a colormap with cubehelix_palette instead, 
# add a cbar_kws={"boundaries": linspace(-1, 1, 4)} to the heatmap invocation 
# to have it generate a discrete colorbar instead of a continous one. 
myColors = ((0.8, 0.0, 0.0, 1.0), (0.0, 0.8, 0.0, 1.0), (0.0, 0.0, 0.8, 1.0)) 
cmap = LinearSegmentedColormap.from_list('Custom', myColors, len(myColors)) 

ax = sns.heatmap(dataFrame, cmap=cmap, linewidths=.5, linecolor='lightgray') 

# Manually specify colorbar labelling after it's been generated 
colorbar = ax.collections[0].colorbar 
colorbar.set_ticks([-0.667, 0, 0.667]) 
colorbar.set_ticklabels(['B', 'A', 'C']) 

# X - Y axis labels 
ax.set_ylabel('FROM') 
ax.set_xlabel('TO') 

# Only y-axis labels need their rotation set, x-axis labels already have a rotation of 0 
_, labels = plt.yticks() 
plt.setp(labels, rotation=0) 

plt.show() 

Heatmap using red, green, and blue as colors with a discrete colorbar

2

Link dostarczany przez @Fabio Lamanna to świetny początek.

Stamtąd nadal należy ustawić etykiety paska koloru we właściwej lokalizacji i użyć etykiet oznaczających dane.

zakładając, że masz poziom równo rozmieszczone w swoich danych, to tworzy piękny dyskretne colorbar:

Zasadniczo, to sprowadza się do wyłączenia colorbar Seaborn i zastąpienie go discretized colorbar siebie.

enter image description here

import pandas 
import seaborn.apionly as sns 
import matplotlib.pyplot as plt 
import numpy as np 
import matplotlib 

def cmap_discretize(cmap, N): 
    """Return a discrete colormap from the continuous colormap cmap. 

     cmap: colormap instance, eg. cm.jet. 
     N: number of colors. 

    Example 
     x = resize(arange(100), (5,100)) 
     djet = cmap_discretize(cm.jet, 5) 
     imshow(x, cmap=djet) 
    """ 

    if type(cmap) == str: 
     cmap = plt.get_cmap(cmap) 
    colors_i = np.concatenate((np.linspace(0, 1., N), (0.,0.,0.,0.))) 
    colors_rgba = cmap(colors_i) 
    indices = np.linspace(0, 1., N+1) 
    cdict = {} 
    for ki,key in enumerate(('red','green','blue')): 
     cdict[key] = [ (indices[i], colors_rgba[i-1,ki], colors_rgba[i,ki]) for i in xrange(N+1) ] 
    # Return colormap object. 
    return matplotlib.colors.LinearSegmentedColormap(cmap.name + "_%d"%N, cdict, 1024) 

def colorbar_index(ncolors, cmap, data): 

    """Put the colorbar labels in the correct positions 
     using uique levels of data as tickLabels 
    """ 

    cmap = cmap_discretize(cmap, ncolors) 
    mappable = matplotlib.cm.ScalarMappable(cmap=cmap) 
    mappable.set_array([]) 
    mappable.set_clim(-0.5, ncolors+0.5) 
    colorbar = plt.colorbar(mappable) 
    colorbar.set_ticks(np.linspace(0, ncolors, ncolors)) 
    colorbar.set_ticklabels(np.unique(data)) 


# Read in csv file 
df_trans = pandas.read_csv('d:/LUH2_trans_matrix.csv') 

sns.set(font_scale=0.8) 
cmap = sns.cubehelix_palette(n_colors=3,start=2.8, rot=.1, light=0.9, as_cmap=True) 
cmap.set_under('gray') # 0 values in activity matrix are shown in gray (inactive transitions) 
df_trans = df_trans.set_index(['Unnamed: 0']) 

N = df_trans.max().max() - df_trans.min().min() + 1 

f, ax = plt.subplots() 
ax = sns.heatmap(df_trans, cmap=cmap, linewidths=.5, linecolor='lightgray',cbar=False) 
colorbar_index(ncolors=N, cmap=cmap,data=df_trans)  

# X - Y axis labels 
ax.set_ylabel('FROM') 
ax.set_xlabel('TO') 

# Rotate tick labels 
locs, labels = plt.xticks() 
plt.setp(labels, rotation=0) 
locs, labels = plt.yticks() 
plt.setp(labels, rotation=0) 

# revert matplotlib params 
sns.reset_orig() 

kawałki recyklingowi i dostosowane od here i here

4

Uważam, że discretized colorbar w Seaborn jest znacznie łatwiej tworzyć, jeśli używasz ListedColormap. Nie ma potrzeby definiowania własnych funkcji, wystarczy dodać kilka linii, aby w zasadzie dostosować swoje osie.

import pandas 
import matplotlib.pyplot as plt 
import seaborn as sns 
from matplotlib.colors import ListedColormap 


# Read in csv file 
df_trans = pandas.read_csv('LUH2_trans_matrix.csv') 

sns.set(font_scale=0.8) 
# cmap is now a list of colors 
cmap = sns.cubehelix_palette(start=2.8, rot=.1, light=0.9, n_colors=3) 
df_trans = df_trans.set_index(['Unnamed: 0']) 

# Create two appropriately sized subplots 
grid_kws = {'width_ratios': (0.9, 0.03), 'wspace': 0.18} 
fig, (ax, cbar_ax) = plt.subplots(1, 2, gridspec_kw=grid_kws) 

ax = sns.heatmap(df_trans, ax=ax, cbar_ax=cbar_ax, cmap=ListedColormap(cmap), 
       linewidths=.5, linecolor='lightgray', 
       cbar_kws={'orientation': 'vertical'}) 

# Customize tick marks and positions 
cbar_ax.set_yticklabels(['B', 'A', 'C']) 
cbar_ax.yaxis.set_ticks([ 0.16666667, 0.5, 0.83333333]) 


# X - Y axis labels 
ax.set_ylabel('FROM') 
ax.set_xlabel('TO') 

# Rotate tick labels 
locs, labels = plt.xticks() 
plt.setp(labels, rotation=0) 
locs, labels = plt.yticks() 
plt.setp(labels, rotation=0) 

enter image description here

Powiązane problemy