更改颜色条限制而不更改它在散点图中表示的数据值

Change colorbar limits without changing the values of the data it represents in scatter

我正在尝试更改附加到散点图的颜色条,以便颜色条的最小值和最大值是数据的最小值和最大值,但我希望数据以零为中心,因为我使用白色为零的颜色图。这是我的例子

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 1, 61)
y = np.linspace(0, 1, 61)
C = np.linspace(-10, 50, 61)
M = np.abs(C).max() # used for vmin and vmax

fig, ax = plt.subplots(1, 1, figsize=(5,3), dpi=150)
sc=ax.scatter(x, y, c=C, marker='o', edgecolor='k', vmin=-M, vmax=M, cmap=plt.cm.RdBu_r)
cbar=fig.colorbar(sc, ax=ax, label='$R - R_0$ (mm)')
ax.set_xlabel('x')
ax.set_ylabel('y')

正如您从附图中看到的那样,颜色条下降到 -M,我希望颜色条下降到 -10,但是如果我让 vmin=-10 那么颜色条不会归零为白色。通常,在使用 contourf 时将 vmin 设置为 +/- M,颜色栏会自动按我想要的方式排序。当 contourf 使用 levels=np.linspace(-M,M,61) 而不是使用 vminvmax 设置 levels=62 时,这种行为是我所期望的。下面显示了我在 scatter 示例中想要的默认 contourf 颜色条行为的示例

plt.figure(figsize=(6,5), dpi=150)
plt.contourf(x, x, np.reshape(np.linspace(-10, 50, 61*61), (61,61)),
                   levels=62, vmin=-M, vmax=M, cmap=plt.cm.RdBu_r)
plt.colorbar(label='$R - R_0$ (mm)')

有没有人有什么想法?我发现 this link 我认为这可能会解决问题,但是在执行 cbar.outline.set_ydata 行时出现此错误 AttributeError: 'Polygon' object has no attribute 'set_ydata' .

EDIT 有点恼火有人关闭了这个问题,却不允许我澄清他们可能有的任何问题,因为 none 我提出的解决方案我要求。 至于 Normalize.TwoSlopeNorm,我不想重新缩放较小的负边以使用整个颜色图范围,我只是希望连接到我的图表一侧的颜色条停在 -10This link 也没有解决我的问题,因为它又是 TwoSlopeNorm 解决方案。

更改颜色条的ylim后,周围的书脊形成的矩形太大了。您可以使该轮廓不可见。然后添加一个新的矩形边框:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 1, 61)
y = np.linspace(0, 1, 61)
C = np.linspace(-10, 50, 61)
M = np.abs(C).max()  # used for vmin and vmax

fig, ax = plt.subplots(1, 1, figsize=(5, 3), dpi=150)
sc = ax.scatter(x, y, c=C, marker='o', edgecolor='k', vmin=-M, vmax=M, cmap=plt.cm.RdBu_r)
cbar = fig.colorbar(sc, ax=ax, label='$R - R_0$ (mm)')

cb_ymin = C.min()
cb_ymax = C.max()
cb_xmin, cb_xmax = cbar.ax.get_xlim()
cbar.ax.set_ylim(cb_ymin, cb_ymax)
cbar.outline.set_visible(False)  # hide the surrounding spines, which are too large after set_ylim
cbar.ax.add_patch(plt.Rectangle((cb_xmin, cb_ymin), cb_xmax - cb_xmin, cb_ymax - cb_ymin,
                                fc='none', ec='black', clip_on=False))
plt.show()

在 v3.5 发布之前的另一种方法是制作一个自定义颜色图来满足您的需求(另请参阅 https://matplotlib.org/stable/tutorials/colors/colormap-manipulation.html#sphx-glr-tutorials-colors-colormap-manipulation-py

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm
from matplotlib.colors import ListedColormap

fig, axs = plt.subplots(2, 1)

X = np.random.randn(32, 32) + 2
pc = axs[0].pcolormesh(X, vmin=-6, vmax=6, cmap='RdBu_r')
fig.colorbar(pc, ax=axs[0])

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.cm as cm
from matplotlib.colors import ListedColormap

fig, axs = plt.subplots(2, 1)

X = np.random.randn(32, 32) + 2
pc = axs[0].pcolormesh(X, vmin=-6, vmax=6, cmap='RdBu_r')
fig.colorbar(pc, ax=axs[0])

def keep_center_colormap(vmin, vmax, center=0):
    vmin = vmin - center
    vmax = vmax - center
    dv = max(-vmin, vmax) * 2
    N = int(256 * dv / (vmax-vmin))
    RdBu_r = cm.get_cmap('RdBu_r', N)
    newcolors = RdBu_r(np.linspace(0, 1, N))
    beg = int((dv / 2 + vmin)*N / dv)
    end = N - int((dv / 2 - vmax)*N / dv)
    newmap = ListedColormap(newcolors[beg:end])
    return newmap

newmap = keep_center_colormap(-2, 6, center=0)
pc = axs[1].pcolormesh(X, vmin=-2, vmax=6, cmap=newmap)
fig.colorbar(pc, ax=axs[1])
plt.show()