【问题标题】:Using color scales as axes in matplotlib在 matplotlib 中使用色标作为轴
【发布时间】:2017-08-30 16:02:16
【问题描述】:

我正在尝试创建一个改变颜色的可视化(特别是 HSV 配色方案的 H 和 V 值,同时保持 S 不变),同时表示给定函数对这些颜色的响应。

实际上,它是一个热图,其中 x 和 y 轴是颜色而不是数字。通过 matplotlib 库搜索,我可以找到很多基于颜色条的示例,例如 herehere

颜色条的实现与我正在寻找的很接近,但有以下重要注意事项:

  1. 我希望将颜色对齐为主图上的刻度,而不是向颜色条本身添加刻度。主要是这需要确保绘图和颜色条是对齐的,我还没有找到任何实际保证这一点的方法。
  2. 我正在尝试确保颜色条将显示在图的左侧(代替标准 x 轴)而不是右侧。

第二点听起来微不足道,但不幸的是,我还没有找到任何记录在案的方法。

有没有什么方法可以在 matplotlib 中创建这样的图,这比在 d3 或类似的较低级别的可视化库中从头开始创建它要少得多?

【问题讨论】:

  • 只是想知道您是否可以澄清“x 和 y 轴是颜色而不是数字的热图”。别人不清楚,但我觉得很难想象你脑海中的那个身影。具体来说,如果两个轴都不是数字,图中的数据是什么?例如,我如何知道在经典位置 (1,0) 显示什么颜色?
  • 图中的数据是数字。所以基本上考虑一个函数,它接受一种颜色并返回一个从零到一的数字。如果更容易想象,可以认为 x 轴为蓝色,y 轴为蓝色。该函数可以是所得颜色的强度度量。实际结果是机器学习模型的输出。
  • @Y.Luo 在 (1,0) 处显示的颜色将是对纯蓝色的响应。你可以假设我有一个适合图表本身的值数组。

标签: python matplotlib visualization


【解决方案1】:

我还是不太确定;但我会试一试。对不起,如果我误解了。

主要想法是使用GridSpec 来解决您的两个要求:对齐“颜色轴”并将它们放在经典轴旁边。对齐应该是正确的,因为ax_x/ax_y 和主ax 之间的对应轴是相同的。

import matplotlib.pyplot as plt
from matplotlib.colors import hsv_to_rgb
from matplotlib.gridspec import GridSpec
import numpy as np

# Create a spectrum sample
# Convert HSV to RGB so that matplotlib can plot;
# hsv_to_rgb assumes values to be in range [0, 1]
N = 0.001
v_y, h_x = np.mgrid[0:1:N, 0:1:N]
c = hsv_to_rgb(np.stack([h_x, np.ones(h_x.shape), v_y], axis=2))
c_x = hsv_to_rgb(np.stack([h_x, np.ones(h_x.shape), np.zeros(v_y.shape)], axis=2))
c_y = hsv_to_rgb(np.stack([np.zeros(h_x.shape), np.ones(h_x.shape), v_y], axis=2))

fig = plt.figure()
# Ratio to adjust width for "x axis" and "y axis"
fig_ratio = np.divide(*fig.get_size_inches())
gs = GridSpec(2, 2, wspace=0.0, hspace=0.0,
              width_ratios=[1, 20], height_ratios=[20/fig_ratio, 1])
# Lower-left corner is ignored
ax_y = plt.subplot(gs[0])
ax = plt.subplot(gs[1])
ax_x = plt.subplot(gs[3])

# Image are stretched to fit the ax since numbers are hided or not important in this figure.
img = ax.imshow(c, aspect='auto', origin='lower')
# Colorbar on img won't give correct results since it is plot with raw RGB values
img_x = ax_x.imshow(c_x, aspect='auto', origin='lower')
img_y = ax_y.imshow(c_y, aspect='auto', origin='lower')
# Remove ticks and ticklabels
for ax in [ax_y, ax, ax_x]:
    ax.tick_params(left=False, bottom=False, 
                   labelleft=False, labelbottom=False)

plt.show()

对评论的回应:

为了澄清,您正在制作三个图,并通过将它们分配给网格的象限来使用 imshow 图作为轴?

是的,它是一个 2x2 网格,我忽略了左下方的网格。文档可能不是很好,但我所做的类似于this part

如果我想在这里的轴和主图之间添加空间,我会增加 wspace 和 hspace?

是的,它在文档的this part 中有简要说明。另外,我用width_ratiosheight_ratios调整了它,使图形的3部分大小不一样,比如this

另外,为了确认,这张图片的底部有一个全黑的轴,它不是左轴的错位。

底部是彩色的 x 轴。它是黑色的,因为我认为它对应于v=0。如果你改变了

c_x = hsv_to_rgb(np.stack([h_x, np.ones(h_x.shape), np.zeros(v_y.shape)], axis=2))

c_x = hsv_to_rgb(np.stack([h_x, np.ones(h_x.shape), np.ones(v_y.shape)], axis=2))

你会得到这个数字,证明它没有错位:

如果更简单,你也可以忽略整个 hsv 的东西,使用灰色框或其他东西作为中心图像。

对不起,我真的很慢。我仍然不知道你想在图中显示什么。所以我不知道如何帮助。如果您删除或注释掉该行

img = ax.imshow(c, aspect='auto', origin='lower') 

你得到了这个:

【讨论】:

  • 我很确定这就是我要找的东西,但是 Gridspec 文档已经够糟糕了,我不太确定。为了澄清,您正在制作三个图,并通过将它们分配给网格的象限来使用 imshow 图作为轴?大概如果我想在这里的轴和主图之间添加空间,我会增加 wspace 和 hspace?另外,为了确认一下,这张图片的底部有一个全黑的轴,这不是左轴的错位。如果更简单,你也可以忽略整个 hsv 的东西,使用灰色框或其他东西作为中心图像。
  • @SlaterTyranus 老实说,我仍然不知道我应该提供什么。再次尝试在答案中解决您的 cmets。请再检查一遍好吗?
猜你喜欢
  • 1970-01-01
  • 2016-10-16
  • 2012-12-19
  • 1970-01-01
  • 2014-09-04
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 1970-01-01
相关资源
最近更新 更多