防止在matplotlib中将颜色栏拉伸到绘图轴的宽度

时间:2018-10-31 16:05:24

标签: python matplotlib colorbar

enter image description here

上面的图是使用mpl_toolkits和matplotlib.colorbar.ColorbarBase生成的,因为我需要为离散数据集自定义颜色图和颜色条,如下所示:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colorbar
from matplotlib.collections import LineCollection
from matplotlib.colors import BoundaryNorm, ListedColormap
from mpl_toolkits.axes_grid1 import make_axes_locatable
import random

x = np.arange(1, 1142)
y = np.zeros(len(x))
z = []
for _ in range(len(x)):
    z.append(random.randint(-1, 5))
z = np.array(z)

cmap = ListedColormap(['#FF0000', '#D52B00', '#AA5500', '#808000', '#55AA00', '#2BD500', '#00FF00'])
norm = BoundaryNorm([-1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5], cmap.N)

points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(z)
lc.set_linewidth(10)

plt.gca().add_collection(lc)

plt.xlim(x.min() - (x.max() * 0.05), x.max() + (x.max() * 0.05))
plt.ylim(-1.1, 1.1)

plt.tick_params(axis='both', which='both', bottom=False, labelbottom=False, left=False, labelleft=False)

divider = make_axes_locatable(plt.gca())
ax_cb = divider.append_axes('bottom', size="2%", pad=-0.5)
cb = colorbar.ColorbarBase(ax_cb, cmap=cmap, norm=norm, orientation='horizontal', ticks=[-1, 0, 1, 2, 3, 4, 5])
cb.ax.set_yticklabels(['-1', '0', '1', '2', '3', '4', '5'])
plt.gcf().add_axes(ax_cb)

plt.show()

此解决方案基于示例here

我的问题是,如何使颜色条更短,以使其不会在绘图轴的整个宽度上伸展?

2 个答案:

答案 0 :(得分:1)

问题在于,通过make_axes_locatable创建的分隔线确保新轴与从中切出的轴完全一样大。这是此功能的主要目标。但是在某种程度上,它具有不同大小的渴望。

解决方案是不使用这种分隔器,而以通常的方式通过plt.colorbarfig.colorbar创建颜色条。这允许使用参数shrinkaspect。由于数据的两边都有5%的边距,因此您可能希望将颜色栏缩小到90%。

plt.colorbar(sm, orientation='horizontal', pad=-0.2,  shrink=0.9, aspect=30,
             ticks=[-1, 0, 1, 2, 3, 4, 5])

完整代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.colors import BoundaryNorm, ListedColormap
from matplotlib.cm import ScalarMappable

x = np.arange(1, 1142)
y = np.zeros(len(x))
z = np.random.randint(-1, 5, size=x.shape)

cmap = ListedColormap(['#FF0000', '#D52B00', '#AA5500', '#808000', '#55AA00', '#2BD500', '#00FF00'])
norm = BoundaryNorm([-1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5], cmap.N)

points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(z)
lc.set_linewidth(10)

plt.gca().add_collection(lc)

plt.xlim(x.min() - (x.max() * 0.05), x.max() + (x.max() * 0.05))
plt.ylim(-1.1, 1.1)

plt.tick_params(axis='both', which='both', bottom=False, labelbottom=False, 
                left=False, labelleft=False)

sm = ScalarMappable(norm=norm, cmap=cmap)
sm.set_array([])

plt.colorbar(sm, orientation='horizontal', pad=-0.2,  shrink=0.9, aspect=30,
             ticks=[-1, 0, 1, 2, 3, 4, 5])

plt.show()

enter image description here

答案 1 :(得分:0)

它可能就像更改颜色栏轴上的填充一样简单,

ax_cb = divider.append_axes('bottom', size="2%", pad=0.5)

看起来已经更好了

enter image description here

更灵活的方法是添加subplots_adjustadd_axes。请注意,这需要设置带有轴fig的图形ax。所以你的例子是,

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colorbar
from matplotlib.collections import LineCollection
from matplotlib.colors import BoundaryNorm, ListedColormap
from mpl_toolkits.axes_grid1 import make_axes_locatable
import random

x = np.arange(1, 1142)
y = np.zeros(len(x))
z = []
for _ in range(len(x)):
    z.append(random.randint(-1, 5))
z = np.array(z)

cmap = ListedColormap(['#FF0000', '#D52B00', '#AA5500', '#808000', '#55AA00', '#2BD500', '#00FF00'])
norm = BoundaryNorm([-1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5], cmap.N)

points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)

lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(z)
lc.set_linewidth(10)

fig, ax = plt.subplots(1,1)

ax.add_collection(lc)

plt.xlim(x.min() - (x.max() * 0.05), x.max() + (x.max() * 0.05))
plt.ylim(-1.1, 1.1)
plt.tick_params(axis='both', which='both', bottom=False, labelbottom=False, left=False, labelleft=False)

fig.subplots_adjust(bottom=0.2)
ax_cb = fig.add_axes([0.15, 0.11, 0.7, 0.05])

cb = colorbar.ColorbarBase(ax_cb, cmap=cmap, norm=norm, orientation='horizontal', ticks=[-1, 0, 1, 2, 3, 4, 5])
cb.ax.set_yticklabels(['-1', '0', '1', '2', '3', '4', '5'])
plt.gcf().add_axes(ax_cb)

plt.show()