简体   繁体   English

将colorbar作为图例添加到matplotlib scatterplot(多个子图,多个散点图)

[英]Add colorbar as legend to matplotlib scatterplot (multiple subplots, multiple scatters)

I have several subplots to which I want to add a single colorbar. 我有几个子图,我想添加一个颜色条。 Each subplot consists of 7 scatters. 每个子图由7个散点组成。 I found advise on how to add colorbars, but they are mostly related to the value of each scatter-point and not to the row itself. 我发现了如何添加色块的建议,但它们主要与每个散点的值有关,而与行本身无关。

Representative sample code: 代表性示例代码:

import numpy as np
from matplotlib import pyplot as plt

x = range(50)
scales = np.linspace(0, 2, 7)
locs = range(4)
cmap = plt.get_cmap("Spectral")
for s_plot in range(4):
    plt.subplot(2, 2, s_plot+1)
    color = iter(cmap(np.linspace(0, 1, len(scales))))
    for scale in scales:
        c = next(color)
        y = np.random.normal(loc=locs[s_plot], scale=scale, size=50)
        plt.scatter(x, y, c=c, s=5)
        plt.title("Mean = {:d}".format(locs[s_plot]))
plt.subplots_adjust(hspace=0.4)
plt.show()

The above example gives: 上面的例子给出: 在此输入图像描述

My desired colorbar looks like this (fake, to be placed next to the plot): 我想要的颜色条看起来像这样(假的,放在情节旁边):

在此输入图像描述

So the colorbar does not depict the value of my scatterpoints, but rather the different "rows" (in this case: different scales) that are iterated through. 因此,colorbar不会描绘散点图的值,而是描绘迭代的不同“行”(在这种情况下:不同的比例)。 In the example that would help match the points to the scales. 在有助于将点与比例匹配的示例中。

What I tried is a simple 我试过的很简单

plt.colorbar()

which is called once after finishing each subplot. 在完成每个子图之后调用一次。 But I get TypeError: You must first set_array for mappable Also, since it is the different scales I want to create the colormap for, I also tried 但我得到TypeError: You must first set_array for mappable另外,因为它是我想要创建颜色图的不同尺度,我也尝试过

plt.colorbar(scales) 

which returns: AttributeError: 'numpy.ndarray' object has no attribute 'autoscale_None' . 返回: AttributeError: 'numpy.ndarray' object has no attribute 'autoscale_None'

I am currently lacking orientation on how to proceed on this. 我目前缺乏如何继续这方面的指导。 Edit: I was marked as possible duplicate of matplotlib colorbar for scatter . 编辑:我被标记为matplotlib colorbar for scatter的可能副本。 I found that question already, but it didn't help with my problem. 我已经发现了这个问题,但它对我的问题没有帮助。 In my case, I need a colormap that is independent of a z-value, but will only indicate the "row number" or "scatter-row" or however you want to call it (equivalent to "lines" in a plt.plot ). 在我的情况下,我需要一个独立于z值的colormap,但只会指示“行号”或“散点行”,或者你想要调用它(相当于plt.plot “lines”) )。

A colorbar needs a ScalarMappable as input. colorbar需要ScalarMappable作为输入。 So if none of the things you create in your plot is suitable for that, you may create it yourself. 因此,如果您在绘图中创建的任何内容都不适合,那么您可以自己创建它。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.cm import ScalarMappable

x = range(50)
scales = np.linspace(0, 2, 7)
locs = range(4)
cmap = plt.get_cmap("Spectral")
norm = plt.Normalize(scales.min(), scales.max())

fig, axes = plt.subplots(2,2, constrained_layout=True, sharey=True)

for s_plot, ax in enumerate(axes.flat):
    for scale in scales:
        y = np.random.normal(loc=locs[s_plot], scale=scale, size=50)
        sc = ax.scatter(x, y, c=[cmap(norm(scale))], s=5)
        ax.set_title("Mean = {:d}".format(locs[s_plot]))

sm =  ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])
cbar = fig.colorbar(sm, ax=axes[:,1])
cbar.ax.set_title("scale")

plt.show()

在此输入图像描述

If I understand correctly then you have some range and want to plot a colormap for that (without some plot actually using the colormap). 如果我理解正确,那么你有一些范围,并希望为此绘制一个色彩图(没有一些情节实际上使用色彩图)。 Basically you can plot a colormap in any axes using 基本上,您可以使用任何轴绘制颜色图

import matplotlib
norm = matplotlib.colors.Normalize(vmin=0, vmax=50)

ax = plt.gca()
matplotlib.colorbar.ColorbarBase(ax, cmap='viridis', norm=norm)

where of course you can use any axes (or use inset_axes to place axes somewhere specific). 当然,您可以使用任何轴(或使用inset_axes将轴放置在特定的位置)。

More tricky is getting colors for your scatter plots that match the colormap in the first place. 更棘手的是获得与首先匹配色彩图的散点图的颜色。 I'm not sure if there is an easier way, but I convert the colors to RGB for plotting. 我不确定是否有更简单的方法,但我将颜色转换为RGB以进行绘图。 Here's a full example: 这是一个完整的例子:

import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import numpy as np

N = 10

# dummy data
x_ = [k/10*np.arange(10) for k in range(N)]

cmap = matplotlib.cm.get_cmap('viridis')
cmap_values = np.linspace(0., 1., N)
colors = cmap(cmap_values)

colors_rgb = ['#{0:02x}{1:02x}{2:02x}'.format(int(255*a), int(255*b), int(255*c)) for a, b, c, _ in colors]

plt.figure()

for x, c in zip(x_, colors_rgb):
    plt.plot(x, c=c)

norm = matplotlib.colors.Normalize(vmin=0, vmax=50)
ticks = np.arange(0, 60, 10)

# vertical colorbar
cbaxes = inset_axes(plt.gca(), width="3%", height="80%", loc=2)
cbar = matplotlib.colorbar.ColorbarBase(cbaxes, cmap=cmap, norm=norm, ticks=ticks)
cbar.set_label('scale')
cbar.ax.set_yticklabels(ticks, fontsize=12)

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM