如何将颜色条添加到像这样创建的散点图中?

kjo*_*kjo 8 python matplotlib

我使用代码创建散点图,实质上就是这样

cmap = (matplotlib.color.LinearSegmentedColormap.
        from_list('blueWhiteRed', ['blue', 'white', 'red']))

fig = matplotlib.figure.Figure(figsize=(4, 4), dpi=72)
ax = fig.gca()

for record in data:
    level = record.level # a float in [0.0, 1.0]
    marker = record.marker # one of 'o', 's', '^', '*', etc.
    ax.scatter(record.x, record.y, marker=marker,
               c=level, vmin=0, vmax=1, cmap=cmap, **otherkwargs)

# various settings of ticks, labels, etc. omitted

canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)
fig.set_canvas(canvas)
canvas.print_png('/path/to/output/fig.png')
Run Code Online (Sandbox Code Playgroud)

我的问题是:

我需要在上面的代码中添加什么来获得cmap沿着图的右边缘的垂直颜色条(表示颜色图)?

注意:我发现Matplotlib 完全不可理解,这既适用于它的设计,也适用于它的文档.(不是因为没有尝试:我花了很多时间,精力,甚至还有一些钱.)所以我会欣赏完整的,有效的代码(即使它只是一个玩具的例子),因为我很可能赢了'能够填写省略的细节或修复代码中的错误.


编辑:我在上面的"代码草图"中修复了一个重要的遗漏,即每次调用时记录特定的标记规范ax.scatter.这就是创建具有多个调用的散点图的原因ax.scatter,但是,诚然,人们至少可以减少每个使用的制造商形状分散到一个调用的次数; 例如

for marker in set(record.marker for record in data):
    X, Y, COLOR = zip(*((record.x, record.y, record.level)
                        for record in data if record.marker == marker))
    ax.scatter(X, Y, marker=marker,
               c=COLOR, vmin=0, vmax=1, cmap=cmap,
               **otherkwargs)
Run Code Online (Sandbox Code Playgroud)

我试图扩展相同的技巧,将所有调用ax.scatter合并为一个(通过传递一系列标记作为marker参数),如下所示:

X, Y, COLOR, MARKER = zip(*((record.x, record.y, record.level, record.marker)
                            for record in data))

ax.scatter(X, Y, marker=MARKER,
           c=COLOR, vmin=0, vmax=1, cmap=cmap,
           **otherkwargs)
Run Code Online (Sandbox Code Playgroud)

......但是失败了.错误是这样的(修剪一些长路径后):

Traceback (most recent call last):
  File "src/demo.py", line 222, in <module>
    main()
  File "src/demo.py", line 91, in main
    **otherkwargs)
  File "<abbreviated-path>/matplotlib/axes.py", line 6100, in scatter
    marker_obj = mmarkers.MarkerStyle(marker)
  File "<abbreviated-path>/matplotlib/markers.py", line 113, in __init__
    self.set_marker(marker)
  File "<abbreviated-path>/matplotlib/markers.py", line 179, in set_marker
    raise ValueError('Unrecognized marker style {}'.format(marker))
ValueError: Unrecognized marker style ('^', 'o', '^', '*', 'o', 's', 'o', 'o', '^', 's', 'o', 'o', '^', '^', '*', 'o', '*', '*', 's', 's', 'o', 's', 'o', '^', 'o', 'o', '*', '^', 's', '^', '^', 's', '*')
Run Code Online (Sandbox Code Playgroud)

AFAICT,tcaswell的配方需要减少对ax.scatter单个调用的调用,但这个要求似乎与我在同一散点图中对多个标记形状的绝对要求相冲突.

tac*_*ell 8

如果必须为每个集合使用不同的标记,则必须执行一些额外的工作并强制所有clims相同(否则它们默认从c每个散点图的数据的最小值/最大值缩放).

from pylab import *
import matplotlib.lines as mlines
import itertools
fig = gcf()
ax = fig.gca()

# make some temorary arrays
X = []
Y = []
C = []
cb = None
# generate fake data
markers = ['','o','*','^','v']
cmin = 0
cmax = 1
for record,marker in itertools.izip(range(5),itertools.cycle(mlines.Line2D.filled_markers)):
    x = rand(50)
    y = rand(50)
    c = rand(1)[0] * np.ones(x.shape)
    if cb is None:
        s = ax.scatter(x,y,c=c,marker=markers[record],linewidths=0)
        s.set_clim([cmin,cmax])
        cb = fig.colorbar(s)
    else:
        s = ax.scatter(x,y,c=c,marker=markers[record],linewidths=0)
        s.set_clim([cmin,cmax])

cb.set_label('Cbar Label Here')
Run Code Online (Sandbox Code Playgroud)

linewidths=0集上的形状的边框的宽度,我发现,对于小的形状的黑色边框可以压倒填充的颜色.

彩色散点图

如果您只需要一个形状,则可以使用单个散点图完成所有这些操作,无需为每次通过循环创建单独的形状.

from pylab import *
fig = gcf()
ax = fig.gca()

# make some temorary arrays
X = []
Y = []
C = []
# generate fake data
for record in range(5):
    x = rand(50)
    y = rand(50)
    c = rand(1)[0] * np.ones(x.shape)
    print c
    X.append(x)
    Y.append(y)
    C.append(c)

X = np.hstack(X)
Y = np.hstack(Y)
C = np.hstack(C)
Run Code Online (Sandbox Code Playgroud)

一旦你将数据全部打入一维数组,制作散点图,并保留返回的值:

s = ax.scatter(X,Y,c=C)
Run Code Online (Sandbox Code Playgroud)

然后创建颜色条并将返回的对象scatter作为第一个参数传递.

cb = plt.colorbar(s)
cb.set_label('Cbar Label Here')
Run Code Online (Sandbox Code Playgroud)

您需要这样做,以便颜色条知道要使用哪个颜色映射(地图和范围).

在此输入图像描述


Pau*_*l H 6

我认为您最好的选择是将数据填充到pandas数据框中,并循环遍历所有标记,如下所示:

import numpy as np    
import pandas as pd
import matplotlib.pyplot as plt

markers = ['s', 'o', '^']
records = []
for n in range(37):
    records.append([np.random.normal(), np.random.normal(), np.random.normal(), 
                    markers[np.random.randint(0, high=3)]])

records = pd.DataFrame(records, columns=['x', 'y', 'z', 'marker'])

fig, ax = plt.subplots()
for m in np.unique(records.marker):
    selector = records.marker == m
    s = ax.scatter(records[selector].x, records[selector].y, c=records[selector].z,
                   marker=m, cmap=plt.cm.coolwarm, 
                   vmin=records.z.min(), vmax=records.z.max())

cbar = plt.colorbar(mappable=s, ax=ax)
cbar.set_label('My Label')
Run Code Online (Sandbox Code Playgroud)

结果图


Jos*_*lis 1

我认为这应该可以解决问题。我很确定我不久前从 matplotlib 食谱示例中获取了这个,但现在我似乎找不到它......

from mpl_toolkits.axes_grid1 import make_axes_locatable

cmap = (matplotlib.color.LinearSegmentedColormap.
        from_list('blueWhiteRed', ['blue', 'white', 'red']))

fig = matplotlib.figure.Figure(figsize=(4, 4), dpi=72)
ax = fig.gca()

for record in data:
    level = record.level # a float in [0.0, 1.0]
    ax.scatter(record.x, record.y,
               c=level, vmin=0, vmax=1, cmap=cmap, **otherkwargs)

# various settings of ticks, labels, etc. omitted

divider= make_axes_locatable(ax)
cax = divider.append_axes("right", size="1%", pad=0.05)
cb = plt.colorbar(cax=cax)
cb.set_label('Cbar Label Here')

canvas = matplotlib.backends.backend_agg.FigureCanvasAgg(fig)
fig.set_canvas(canvas)
canvas.print_png('/path/to/output/fig.png')
Run Code Online (Sandbox Code Playgroud)