Python 使散点颜色条仅显示vmin/vmax的子集

Python 使散点颜色条仅显示vmin/vmax的子集,python,matplotlib,colorbar,Python,Matplotlib,Colorbar,我想创建一个颜色条,其颜色(与散点图关联)跨越特定范围,但仅在颜色条本身上显示该范围的子集。我可以用contourf,因为我可以独立于轮廓级别设置vmin和vmax,但我不知道如何使用散射。见下文: import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable x = np.linspace(0, 2*np.pi, 101) x_arr =

我想创建一个颜色条,其颜色(与散点图关联)跨越特定范围,但仅在颜色条本身上显示该范围的子集。我可以用
contourf
,因为我可以独立于轮廓级别设置
vmin
vmax
,但我不知道如何使用散射。见下文:

import numpy as np

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

x = np.linspace(0, 2*np.pi, 101)
x_arr = np.sin(x)
y_arr = np.cos(x)
arr = y_arr[:,None] * x_arr[None,:]

arr = np.where(arr < 0, arr*4, arr)
ptslist = np.array([-4, -3, -2, -1, 0, 1], dtype=np.float32)

fig, axs = plt.subplots(figsize=(11,5), nrows=1, ncols=2)

# I can achieve my desired behavior with contourf
cont = axs[0].contourf(x, x, arr, levels=np.linspace(-4,1,11),
                       cmap='BrBG_r', vmin=-4, vmax=4)
div0 = make_axes_locatable(axs[0])
cax0 = div0.append_axes('right', '5%', '2%')
plt.colorbar(cont, cax=cax0)

# I can't make this colorbar do a similar thing
sc = axs[1].scatter(np.arange(-4, 2), np.arange(-4, 2), c=ptslist, cmap='BrBG_r',
                    marker='o', s=144, edgecolors='black', vmin=-4, vmax=4)
div1 = make_axes_locatable(axs[1])
cax1 = div1.append_axes('right', '5%', '2%')
cb = plt.colorbar(sc, cax=cax1)
导致这种奇怪的事情发生:

如果我使用
set_ticks
,它只会删除缺少的ticks,而不会更改限制。有什么办法可以让这一切顺利发生吗

我正在使用matplotlib 1.5.0


p、 我还尝试了一个以中点为中心的Normalize子类,我在SO上发现了这个子类,但它独立地缩放正值和负值,这是我不想要的(它使+1.0的值变成深棕色,我希望它仍然是浅棕色,除非我设置了
vmax=4
,在这一点上我有完全相同的问题).

您可以将
边界
参数传递到
颜色栏

plt.colorbar(sc, cax=cax1, boundaries=sc.get_array())

我不知道
sc.get\u array()
在这里是否总是正确的选择,但是
get\u array
是一种可缩放的方法,应该可以将数据映射到颜色上,因此这似乎是一个合理的选择。(对于等高线集,
colorbar
会自动获取等高线级别并将其用作边界。)

您可以通过几种不同的方式执行此操作,但听起来您真正想要的是从另一个颜色贴图的一部分创建自定义颜色贴图:

例如:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap

# Let's create a new colormap from a region of another colormap.
cmap = plt.get_cmap('BrBG_r')
colors = cmap(np.linspace(0, 5 / 8.0, 20))
cmap = LinearSegmentedColormap.from_list('my cmap', colors)

# And now let's plot some data...
x, y, z = np.random.random((3, 10))
z = 5 * z - 4

fig, ax = plt.subplots()
scat = ax.scatter(x, y, c=z, s=200, cmap=cmap, vmin=-4, vmax=1)
cbar = fig.colorbar(scat)

plt.show()

或者,如果您更喜欢离散颜色贴图,可以执行以下类似操作:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import from_levels_and_colors

# Let's create a new set of colors from a region of another colormap.
ncolors = 10
cmap = plt.get_cmap('BrBG_r')
colors = cmap(np.linspace(0, 5 / 8.0, ncolors - 1))

# We'll then create a new colormap from that set of colors and tie it
# to specific values
levels = np.linspace(-4, 1, ncolors)
cmap, norm = from_levels_and_colors(levels, colors)

x, y, z = np.random.random((3, 10))
z = 5 * z - 4

fig, ax = plt.subplots()
scat = ax.scatter(x, y, c=z, s=200, cmap=cmap, norm=norm)
cbar = fig.colorbar(scat)
cbar.set_ticks(range(-4, 2))

plt.show()

您是否关心这两个颜色条实际上是否相同,还是只希望它们代表相同的颜色空间区域?你的等高线数据比散射数据包含更多不同的值,因此它的颜色栏应该更“详细”(即,在颜色图的光谱中包含更多的“阴影”)。不,等高线颜色栏只是用于说明-我不关心“细节”,我只关心限制。i、 e.我希望右侧颜色栏的顶部在1.0时为浅棕色,而不是在4.0时为深棕色。我不知道为什么
ylim
做了这么奇怪的事……噢!很高兴知道。然而。。。。也许我真的很在乎细节,我想保持平滑的渐变。这给了我清晰的“步骤”,但我正在绘制的实际数据实际上是一组分布非常不均匀的浮点数。边界可以接受任意数组吗?啊哈!我刚刚用
bounders=np.linspace(-4,1101)
试过,它看起来很可爱。谢谢哦,还不错!实际上,你第一个例子中的0到5/8让我想到了为什么
ylim
工作得如此有趣。。。结果表明,cbar ylimits(尽管有刻度)的工作范围是从0到1,就像colorbar值一样。。。。我尝试了
cb.ax.set_ylim(0,5/8.)
,它也成功了!
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import from_levels_and_colors

# Let's create a new set of colors from a region of another colormap.
ncolors = 10
cmap = plt.get_cmap('BrBG_r')
colors = cmap(np.linspace(0, 5 / 8.0, ncolors - 1))

# We'll then create a new colormap from that set of colors and tie it
# to specific values
levels = np.linspace(-4, 1, ncolors)
cmap, norm = from_levels_and_colors(levels, colors)

x, y, z = np.random.random((3, 10))
z = 5 * z - 4

fig, ax = plt.subplots()
scat = ax.scatter(x, y, c=z, s=200, cmap=cmap, norm=norm)
cbar = fig.colorbar(scat)
cbar.set_ticks(range(-4, 2))

plt.show()