Создание пользовательской цветовой панели в matplotlib

Как я могу создать цветовую панель в matplotlib, которая выглядит следующим образом:

Вот что я попробовал:

import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.cm import ScalarMappable
from matplotlib.colors import Normalize

# Define the custom colormap
colors = ['red', 'cyan', 'darkgreen']
cmap = LinearSegmentedColormap.from_list(
    'custom_colormap', 
    [(0.0, colors[0]), (0.5 / 2.0, colors[0]),
     (0.5 / 2.0, colors[1]), (1.5 / 2.0, colors[1]),
     (1.5 / 2.0, colors[2]), (2.0 / 2.0, colors[2])]
)

# Create a scalar mappable object with the colormap
sm = ScalarMappable(norm=Normalize(vmin=3.5, vmax=4.5), cmap=cmap)

# Create the colorbar
plt.figure(figsize=(3, 1))
cb = plt.colorbar(sm, orientation='horizontal', ticks=[3.5, 4.5], extend='neither')
cb.set_label('')
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
164
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Использование ListedColorMap создает цветовую полосу, похожую на ту, которую вы представили на рисунке:

from matplotlib.cm import ScalarMappable
from matplotlib.colors import ListedColormap, Normalize
import matplotlib.pyplot as plt
import matplotlib as mpl

fig, ax = plt.subplots(figsize=(6, 1), layout='constrained')
cmap = ListedColormap(["red", "cyan", "slategrey"])
norm = mpl.colors.Normalize(vmin=5, vmax=10)
sm = ScalarMappable(norm=Normalize(2.5,5.5), cmap=cmap)
fig.colorbar(sm, cmap=cmap, ticks=[3.5, 4.5], cax=ax, 
orientation='horizontal', label='Colorbar')
plt.show()
cb = plt.colorbar(sm, cmap=cmap, ticks=[3.5, 4.5], cax=ax, 
orientation='horizontal', label='Colorbar')

Вы хотите, чтобы это выглядело так?

Ответ принят как подходящий

Одно из решений — нарисовать широкие белые края вокруг цветных сегментов (используя cb.solids.set ниже), скрыть шипы (cb.outline.set_visible) и нарисовать вертикальные линии в качестве разделителей (cb.ax.axvline). Чтобы соответствовать желаемой цветовой панели, обязательно передайте ymin, который больше 0.

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, Normalize
from matplotlib.cm import ScalarMappable

fig, ax = plt.subplots(figsize=(3, 1), layout='tight')

colors = ['red', 'cyan', 'darkgreen']
ticks = [3.5, 4.5]
cmap = ListedColormap(colors)
norm = Normalize(vmin=2.5, vmax=5.5)
cb = fig.colorbar(
    mappable=ScalarMappable(norm=norm, cmap=cmap),
    cax=ax,
    ticks=ticks,
    ticklocation='top',
    orientation='horizontal',
)
cb.solids.set(edgecolor='white', linewidth=5)
cb.outline.set_visible(False)
cb.ax.tick_params(width=1, length=10, color='k')
for bound in ticks:
    cb.ax.axvline(bound, c='k', linewidth=1, ymin=0.3, alpha=0.6)
plt.setp(cb.ax.xaxis.get_ticklines(), alpha=0.6)
cb.set_ticklabels(ticks, alpha=0.6, color='k', fontsize=15, fontfamily='Arial')

Другое решение — вместо рисования вертикальных линий в качестве разделителей просто используйте линии-разделители, определенные на самом объекте цветовой панели (пропустите drawedges=True). Однако конечный результат будет немного отличаться от желаемого, поскольку разделительная линия проводится снизу вверх (не может пройти ymin, как указано выше).

fig, ax = plt.subplots(figsize=(3, 1), layout='tight')

colors = ['red', 'cyan', 'darkgreen']
ticks = [3.5, 4.5]
cmap = ListedColormap(colors)
norm = Normalize(vmin=2.5, vmax=5.5)
cb = fig.colorbar(
    mappable=ScalarMappable(norm=norm, cmap=cmap),
    cax=ax,
    ticks=ticks,
    ticklocation='top',
    orientation='horizontal',
    drawedges=True
)
cb.solids.set(edgecolor='white', linewidth=5)
cb.outline.set_visible(False)
cb.dividers.set(linewidth=1, alpha=0.6)
cb.ax.tick_params(width=1, length=10, color='k')
plt.setp(cb.ax.xaxis.get_ticklines(), alpha=0.6)
cb.set_ticklabels(ticks, alpha=0.6, color='k', fontsize=15, fontfamily='Arial')

Другие вопросы по теме