#interpolation #bokeh #heatmap #palette
Вопрос:
Я построил тепловую карту в Боке, которая отлично работает. Я хочу, чтобы он постоянно менял цвет с ярко-зеленого на ярко-красный. Текущий код является:
colors = ["#66ff00", "#FFFFFF", "#FF0000"]
colors.reverse()
mapper = LinearColorMapper(palette=colors, low=-50, high=50)
p.rect(..., fill_color=transform('percentage', mapper))
Проблема в том, что на тепловой карте отображаются только 3 цвета. Я бы ожидал, что все значения от -50 до 50 будут линейно интерполировать значения от ярко-красного до белого до ярко-зеленого и отображаться на тепловой карте. Как я могу этого достичь?
Ответ №1:
Принятый в настоящее время ответ абсолютно правильный, я просто подумал, что любой, кто найдет это, может использовать рабочее решение для своей проблемы.
С помощью matplotlib
вы можете создать линейную сегментированную цветовую карту:
colors = ["darkorange", "gold", "lawngreen", "lightseagreen"]
cmap1 = matplotlib.colors.LinearSegmentedColormap.from_list("mycmap", colors)
Если ваши цвета не должны быть равномерно распределены по диапазону, вы также можете определить их положение:
colors = ["darkorange", "gold", "lawngreen", "lightseagreen"]
nodes = [0.0, 0.4, 0.8, 1.0]
cmap2 = matplotlib.colors.LinearSegmentedColormap.from_list("mycmap", list(zip(nodes, colors)))
Отсюда вы можете обрабатывать эту цветовую карту так же, как и любую встроенную линейную сегментированную цветовую карту, например, медь. Например, вы можете экспортировать список из 192 цветов в диапазоне от 25% до 90% вашей цветовой карты следующим образом:
palette = [matplotlib.colors.rgb2hex(c) for c in cmap1(np.linspace(0.25, 0.9, 192))]
А затем вы можете использовать эту палитру в любом решении для построения графиков, которое вы предпочитаете.
Редактировать: Поскольку мне также часто нужна точно такая же функциональность, я только что создал функцию для этого.
- Суть с документами: https://gist.github.com/ka-steve/18745d14513b54eaba35597b0e72d110
- Колаб с примерами: https://colab.research.google.com/drive/1eQ7Bw5ao8FGW_jauOt3vz5dmrxHe14CM?usp=sharing
Сам код:
def get_palette(cmap='Greys', n=192, start=0, end=1):
import matplotlib, numpy as np
linspace = np.linspace(start, end, n)
if isinstance(cmap, list):
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("customcmap", cmap)
palette = cmap(linspace)
elif isinstance(cmap, str):
cmap = matplotlib.pyplot.cm.get_cmap(cmap)
palette = cmap(linspace)
else:
palette = cmap(linspace)
hex_palette = [matplotlib.colors.rgb2hex(c) for c in palette]
return hex_palette
Ответ №2:
Начиная с версии 2.3.1, палитры-это просто списки цветов, и существующие в настоящее время приложения для отображения цветов просто используют палитры, как указано, без их изменения. Если вам нужно больше цветов, вам нужно будет интерполировать палитру (список цветов) до нужного размера, прежде чем передавать ее Боке. «Линейный» в LinearColorMapper
относится к тому, как значения линейно отображаются в ячейки, определенные палитрой.