matplotlib: paski kolorów i ich etykiety tekstowe

108

Chciałbym stworzyć colorbarlegendę dla heatmaptakiego, aby etykiety znajdowały się w środku każdego dyskretnego koloru. Przykład zapożyczony stąd :

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap

#discrete color scheme
cMap = ListedColormap(['white', 'green', 'blue','red'])

#data
np.random.seed(42)
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=cMap)

#legend
cbar = plt.colorbar(heatmap)
cbar.ax.set_yticklabels(['0','1','2','>3'])
cbar.set_label('# of contacts', rotation=270)

# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)
ax.invert_yaxis()

#labels
column_labels = list('ABCD')
row_labels = list('WXYZ')
ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)

plt.show()

Generuje to następujący wykres:

działka pmesh

Idealnie chciałbym wygenerować pasek legendy, która ma cztery kolory i dla każdego koloru, etykietę w środku: 0,1,2,>3. Jak można to osiągnąć?

dimka
źródło

Odpowiedzi:

116
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap

#discrete color scheme
cMap = ListedColormap(['white', 'green', 'blue','red'])

#data
np.random.seed(42)
data = np.random.rand(4, 4)
fig, ax = plt.subplots()
heatmap = ax.pcolor(data, cmap=cMap)

#legend
cbar = plt.colorbar(heatmap)

cbar.ax.get_yaxis().set_ticks([])
for j, lab in enumerate(['$0$','$1$','$2$','$>3$']):
    cbar.ax.text(.5, (2 * j + 1) / 8.0, lab, ha='center', va='center')
cbar.ax.get_yaxis().labelpad = 15
cbar.ax.set_ylabel('# of contacts', rotation=270)


# put the major ticks at the middle of each cell
ax.set_xticks(np.arange(data.shape[1]) + 0.5, minor=False)
ax.set_yticks(np.arange(data.shape[0]) + 0.5, minor=False)
ax.invert_yaxis()

#labels
column_labels = list('ABCD')
row_labels = list('WXYZ')
ax.set_xticklabels(column_labels, minor=False)
ax.set_yticklabels(row_labels, minor=False)

plt.show()

Byłeś bardzo blisko. Gdy masz już odniesienie do osi paska kolorów, możesz robić, co chcesz, w tym umieszczać etykiety tekstowe na środku. Możesz bawić się formatowaniem, aby było bardziej widoczne.

próbny

tacaswell
źródło
6

Aby dodać do odpowiedzi tacaswell , colorbar()funkcja ma opcjonalne caxdane wejściowe, których można użyć do przekazania osi, na której powinien być narysowany pasek kolorów. Jeśli używasz tego wejścia, możesz bezpośrednio ustawić etykietę za pomocą tej osi.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

fig, ax = plt.subplots()
heatmap = ax.imshow(data)
divider = make_axes_locatable(ax)
cax = divider.append_axes('bottom', size='10%', pad=0.6)
cb = fig.colorbar(heatmap, cax=cax, orientation='horizontal')

cax.set_xlabel('data label')  # cax == cb.ax
Steven C. Howell
źródło
1
Myślę, że powinno być axes_grid1zamiast axes.grid1.
rvf