调色板的中点
Midpoint of Color Palette
对于我当前的项目,我需要一张热图。热图需要一个可缩放的调色板,因为值只在一个小范围内有趣。这意味着,即使我有从 0 到 1 的值,有趣的只是 0.6 到 0.9 之间的部分;所以我想相应地缩放热图颜色,并在图表旁边显示比例。
在 Matplotlib 中,除了重载原始 class 之外,我无法设置调色板的中点,例如 shown here in the matplotlib guide.
这正是我所需要的,而且没有 Matplotlib 中数据结构不干净的缺点。
所以我尝试了散景。
我在五分钟内取得的成绩比使用 Matplotlib 在一小时内取得的成绩还多,但是,当我想在热图旁边显示色标以及更改调色板的比例时,我遇到了困难。
所以,这是我的问题:
如何在 Bokeh 或 Matplotlib 中缩放调色板?
有没有办法在热图旁边显示带注释的颜色条?
import pandas
scores_df = pd.DataFrame(myScores, index=c_range, columns=gamma_range)
import bkcharts
from bokeh.palettes import Inferno256
hm = bkcharts.HeatMap(scores_df, palette=Inferno256)
# here: how to insert a color bar?
# here: how to correctly scale the inferno256 palette?
hm.ylabel = "C"
hm.xlabel = "gamma"
bkcharts.output_file('heatmap.html')
根据 Aarons 的提示,我现在实现如下:
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from bokeh.palettes import Inferno256
def print_scores(scores, gamma_range, C_range):
# load a color map
# find other colormaps here
# https://docs.bokeh.org/en/latest/docs/reference/palettes.html
cmap = colors.ListedColormap(Inferno256, len(Inferno256))
fig, ax = plt.subplots(1, 1, figsize=(6, 5))
# adjust lower, midlle and upper bound of the colormap
cmin = np.percentile(scores, 10)
cmid = np.percentile(scores, 75)
cmax = np.percentile(scores, 99)
bounds = np.append(np.linspace(cmin, cmid), np.linspace(cmid, cmax))
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(Inferno256))
pcm = ax.pcolormesh(np.log10(gamma_range),
np.log10(C_range),
scores,
norm=norm,
cmap=cmap)
fig.colorbar(pcm, ax=ax, extend='both', orientation='vertical')
plt.show()
ImportanceOfBeingErnest 正确地指出我的第一条评论并不完全清楚(或措辞不准确)。
mpl
中的大多数绘图函数都有一个关键字:norm=
这表示将映射您的数组的 class(mpl.colors.Normalize
的子class)数据到值 [0 - 1] 的目的是映射到颜色图,但实际上并不影响数据的数值。有几个内置的 subclasses,您也可以创建自己的。对于这个应用程序,我可能会使用 BoundaryNorm
。此 class 将 N-1 均匀映射 spaced 颜色到 N 个离散边界之间的 space。
我稍微修改了 example 以更好地适应您的应用:
#adaptation of https://matplotlib.org/users/colormapnorms.html#discrete-bounds
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
#example data
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
'''
BoundaryNorm: For this one you provide the boundaries for your colors,
and the Norm puts the first color in between the first pair, the
second color between the second pair, etc.
'''
fig, ax = plt.subplots(3, 1, figsize=(8, 8))
ax = ax.flatten()
# even bounds gives a contour-like effect
bounds = np.linspace(-1, 1)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[0].pcolormesh(X, Y, Z1,
norm=norm,
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical')
# clipped bounds emphasize particular region of data:
bounds = np.linspace(-.2, .5)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[1].pcolormesh(X, Y, Z1, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical')
# now if we want 0 to be white still, we must have 0 in the middle of our array
bounds = np.append(np.linspace(-.2, 0), np.linspace(0, .5))
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[2].pcolormesh(X, Y, Z1, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical')
fig.show()
对于我当前的项目,我需要一张热图。热图需要一个可缩放的调色板,因为值只在一个小范围内有趣。这意味着,即使我有从 0 到 1 的值,有趣的只是 0.6 到 0.9 之间的部分;所以我想相应地缩放热图颜色,并在图表旁边显示比例。
在 Matplotlib 中,除了重载原始 class 之外,我无法设置调色板的中点,例如 shown here in the matplotlib guide.
这正是我所需要的,而且没有 Matplotlib 中数据结构不干净的缺点。
所以我尝试了散景。 我在五分钟内取得的成绩比使用 Matplotlib 在一小时内取得的成绩还多,但是,当我想在热图旁边显示色标以及更改调色板的比例时,我遇到了困难。
所以,这是我的问题:
如何在 Bokeh 或 Matplotlib 中缩放调色板?
有没有办法在热图旁边显示带注释的颜色条?
import pandas
scores_df = pd.DataFrame(myScores, index=c_range, columns=gamma_range)
import bkcharts
from bokeh.palettes import Inferno256
hm = bkcharts.HeatMap(scores_df, palette=Inferno256)
# here: how to insert a color bar?
# here: how to correctly scale the inferno256 palette?
hm.ylabel = "C"
hm.xlabel = "gamma"
bkcharts.output_file('heatmap.html')
根据 Aarons 的提示,我现在实现如下:
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from bokeh.palettes import Inferno256
def print_scores(scores, gamma_range, C_range):
# load a color map
# find other colormaps here
# https://docs.bokeh.org/en/latest/docs/reference/palettes.html
cmap = colors.ListedColormap(Inferno256, len(Inferno256))
fig, ax = plt.subplots(1, 1, figsize=(6, 5))
# adjust lower, midlle and upper bound of the colormap
cmin = np.percentile(scores, 10)
cmid = np.percentile(scores, 75)
cmax = np.percentile(scores, 99)
bounds = np.append(np.linspace(cmin, cmid), np.linspace(cmid, cmax))
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=len(Inferno256))
pcm = ax.pcolormesh(np.log10(gamma_range),
np.log10(C_range),
scores,
norm=norm,
cmap=cmap)
fig.colorbar(pcm, ax=ax, extend='both', orientation='vertical')
plt.show()
ImportanceOfBeingErnest 正确地指出我的第一条评论并不完全清楚(或措辞不准确)。
mpl
中的大多数绘图函数都有一个关键字:norm=
这表示将映射您的数组的 class(mpl.colors.Normalize
的子class)数据到值 [0 - 1] 的目的是映射到颜色图,但实际上并不影响数据的数值。有几个内置的 subclasses,您也可以创建自己的。对于这个应用程序,我可能会使用 BoundaryNorm
。此 class 将 N-1 均匀映射 spaced 颜色到 N 个离散边界之间的 space。
我稍微修改了 example 以更好地适应您的应用:
#adaptation of https://matplotlib.org/users/colormapnorms.html#discrete-bounds
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal
#example data
N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]
Z1 = (bivariate_normal(X, Y, 1., 1., 1.0, 1.0))**2 \
- 0.4 * (bivariate_normal(X, Y, 1.0, 1.0, -1.0, 0.0))**2
Z1 = Z1/0.03
'''
BoundaryNorm: For this one you provide the boundaries for your colors,
and the Norm puts the first color in between the first pair, the
second color between the second pair, etc.
'''
fig, ax = plt.subplots(3, 1, figsize=(8, 8))
ax = ax.flatten()
# even bounds gives a contour-like effect
bounds = np.linspace(-1, 1)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[0].pcolormesh(X, Y, Z1,
norm=norm,
cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[0], extend='both', orientation='vertical')
# clipped bounds emphasize particular region of data:
bounds = np.linspace(-.2, .5)
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[1].pcolormesh(X, Y, Z1, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical')
# now if we want 0 to be white still, we must have 0 in the middle of our array
bounds = np.append(np.linspace(-.2, 0), np.linspace(0, .5))
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256)
pcm = ax[2].pcolormesh(X, Y, Z1, norm=norm, cmap='RdBu_r')
fig.colorbar(pcm, ax=ax[2], extend='both', orientation='vertical')
fig.show()