seaborn 热图中的自定义调色板间隔
Custom color palette intervals in seaborn heatmap
我正在尝试使用 seaborn 库绘制 heatmap。
绘图函数如下所示:
def plot_confusion_matrix(data, labels, **kwargs):
"""Visualize confusion matrix as a heat map."""
col_map = kwargs.get('color_palette', sns.light_palette('navy', n_colors=5, as_cmap=False))
sns.heatmap(
vmin=0.0,
vmax=1.0,
data=data,
cmap=col_map,
xticklabels=labels,
yticklabels=labels,
linewidths=0.75,
)
data
的直方图如下所示:
现在我正在努力解决的问题是 seaborn 热图(如下图)均匀分割色标,因此大部分数据具有相同的颜色(因为数据分布不均匀)。
我无法找到如何为颜色级别设置某种间隔或边界。
假设我有以下十六进制颜色值数组:
['#e5e5ff', '#acacdf', '#7272bf', '#39399f', '#000080']
有没有办法设置颜色如
[(threshold_0, hex_0), (threshold_1, hex_1), ..., (threshold_n, hex_n)]
其中 threshold_i
是 [0, 1)
范围内的值
感谢任何帮助。
PS:用于说明的当前热图:
故意不解决您问题中的 "custom" - 同时这可能有帮助:
除了在整个范围内平滑变化的众所周知的颜色图之外,还有一些更适合显示多个数据波段中的微小差异,例如gist_ncar
。
另见 https://matplotlib.org/examples/color/colormaps_reference.html
创建于
sns.heatmap(vmin=0.0, vmax=1.0, data=data, cmap='gist_ncar', linewidths=0.75)
我能够找到(在我看来不是很干净)解决方案,它使用 matplotlib.colors.LinearSegmentedColormap
。
代码如下所示:
# NOTE: jupyter notebook mode
%matplotlib inline
import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap
boundaries = [0.0, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 1.0] # custom boundaries
# here I generated twice as many colors,
# so that I could prune the boundaries more clearly
hex_colors = sns.light_palette('navy', n_colors=len(boundaries) * 2 + 2, as_cmap=False).as_hex()
hex_colors = [hex_colors[i] for i in range(0, len(hex_colors), 2)]
colors=list(zip(boundaries, hex_colors))
custom_color_map = LinearSegmentedColormap.from_list(
name='custom_navy',
colors=colors,
)
sns.heatmap(
vmin=0.0,
vmax=1.0,
data=data,
cmap=custom_color_map,
xticklabels=labels,
yticklabels=labels,
linewidths=0.75,
)
关于此文档 here,您可以创建自己的 color-dictionary。这些字典必须是 rgb-values,所以我写了第一个测试函数来从 Hex_colors 和你想要的阈值生成一个:
def NonLinCdict(steps, hexcol_array):
cdict = {'red': (), 'green': (), 'blue': ()}
for s, hexcol in zip(steps, hexcol_array):
rgb =matplotlib.colors.hex2color(hexcol)
cdict['red'] = cdict['red'] + ((s, rgb[0], rgb[0]),)
cdict['green'] = cdict['green'] + ((s, rgb[1], rgb[1]),)
cdict['blue'] = cdict['blue'] + ((s, rgb[2], rgb[2]),)
return cdict
hc = ['#e5e5ff', '#acacdf', '#7272bf', '#39399f', '#000080']
th = [0, 0.1, 0.5, 0.9, 1]
cdict = NonLinCdict(th, hc)
cm = mc.LinearSegmentedColormap('test', cdict)
plt.figure()
sns.heatmap(
vmin=0.0,
vmax=1.0,
data=data,
cmap=cm,
linewidths=0.75)
生成:
还可以做更多(例如,离散跳跃,看看文档...)但这应该回答你原来的问题 - "custom" 这次包括...
不过,我要补充一点个人看法:像这里拉长的色图可能是'pleasing',但要注意不要误导观众的眼睛。
希望对您有所帮助。
我正在尝试使用 seaborn 库绘制 heatmap。
绘图函数如下所示:
def plot_confusion_matrix(data, labels, **kwargs):
"""Visualize confusion matrix as a heat map."""
col_map = kwargs.get('color_palette', sns.light_palette('navy', n_colors=5, as_cmap=False))
sns.heatmap(
vmin=0.0,
vmax=1.0,
data=data,
cmap=col_map,
xticklabels=labels,
yticklabels=labels,
linewidths=0.75,
)
data
的直方图如下所示:
现在我正在努力解决的问题是 seaborn 热图(如下图)均匀分割色标,因此大部分数据具有相同的颜色(因为数据分布不均匀)。
我无法找到如何为颜色级别设置某种间隔或边界。
假设我有以下十六进制颜色值数组:
['#e5e5ff', '#acacdf', '#7272bf', '#39399f', '#000080']
有没有办法设置颜色如
[(threshold_0, hex_0), (threshold_1, hex_1), ..., (threshold_n, hex_n)]
其中 threshold_i
是 [0, 1)
感谢任何帮助。
PS:用于说明的当前热图:
故意不解决您问题中的 "custom" - 同时这可能有帮助:
除了在整个范围内平滑变化的众所周知的颜色图之外,还有一些更适合显示多个数据波段中的微小差异,例如gist_ncar
。
另见 https://matplotlib.org/examples/color/colormaps_reference.html
创建于
sns.heatmap(vmin=0.0, vmax=1.0, data=data, cmap='gist_ncar', linewidths=0.75)
我能够找到(在我看来不是很干净)解决方案,它使用 matplotlib.colors.LinearSegmentedColormap
。
代码如下所示:
# NOTE: jupyter notebook mode
%matplotlib inline
import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap
boundaries = [0.0, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 1.0] # custom boundaries
# here I generated twice as many colors,
# so that I could prune the boundaries more clearly
hex_colors = sns.light_palette('navy', n_colors=len(boundaries) * 2 + 2, as_cmap=False).as_hex()
hex_colors = [hex_colors[i] for i in range(0, len(hex_colors), 2)]
colors=list(zip(boundaries, hex_colors))
custom_color_map = LinearSegmentedColormap.from_list(
name='custom_navy',
colors=colors,
)
sns.heatmap(
vmin=0.0,
vmax=1.0,
data=data,
cmap=custom_color_map,
xticklabels=labels,
yticklabels=labels,
linewidths=0.75,
)
关于此文档 here,您可以创建自己的 color-dictionary。这些字典必须是 rgb-values,所以我写了第一个测试函数来从 Hex_colors 和你想要的阈值生成一个:
def NonLinCdict(steps, hexcol_array):
cdict = {'red': (), 'green': (), 'blue': ()}
for s, hexcol in zip(steps, hexcol_array):
rgb =matplotlib.colors.hex2color(hexcol)
cdict['red'] = cdict['red'] + ((s, rgb[0], rgb[0]),)
cdict['green'] = cdict['green'] + ((s, rgb[1], rgb[1]),)
cdict['blue'] = cdict['blue'] + ((s, rgb[2], rgb[2]),)
return cdict
hc = ['#e5e5ff', '#acacdf', '#7272bf', '#39399f', '#000080']
th = [0, 0.1, 0.5, 0.9, 1]
cdict = NonLinCdict(th, hc)
cm = mc.LinearSegmentedColormap('test', cdict)
plt.figure()
sns.heatmap(
vmin=0.0,
vmax=1.0,
data=data,
cmap=cm,
linewidths=0.75)
生成:
还可以做更多(例如,离散跳跃,看看文档...)但这应该回答你原来的问题 - "custom" 这次包括...
不过,我要补充一点个人看法:像这里拉长的色图可能是'pleasing',但要注意不要误导观众的眼睛。
希望对您有所帮助。