以下代码和情节试图说明正在发生的事情。
LinearSegmentedColormap.from_list("", colors) 在内部创建一个平滑的颜色图,在这种情况下,5 种颜色的值分别为 0、0.25、0.5、0.75 和 1(即范围 0-1 均匀分布到 5-1=4 个相等的空间中。in-位置之间平滑插值。当你设置N时,N区域被放入0-1范围内。例如N=10,设置了10个区域(使用11个边界)。每个区域的颜色值为通过将 0-1 之间的平滑颜色范围划分为 N(因此,不是 N+1)相等的位置获得。
现在,为了将外部值 50-450 映射到内部值 0-1,使用 norm。默认情况下,使用数据的最小值和最大值。 vmin 和/或vmax 可以设置明确的最小值和最大值。 (除此之外,还可以指定一个显式的范数函数。)
要计算外部值的边界,需要将范围 50-450 切割成 N 个相等的区域,因此有 N+1 个边界。 np.linspace(50, 450, N+1) 是一个 numpy 函数,它将这些边界值创建到一个数组中。
from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.cm import ScalarMappable
import numpy as np
colors = ['#FBE9BD', '#F2C370', '#E58B48', '#C35D30', '#A12F29']
cmap1 = LinearSegmentedColormap.from_list("mycmap1", colors, N=10)
minval = 50
maxval = 450
bounds = np.linspace(minval, maxval, cmap1.N + 1)
x = np.random.uniform(size=1000)
y = np.random.uniform(minval, maxval, size=x.size)
plt.scatter(x, y, c=y, vmin=minval, vmax=maxval, cmap=cmap1)
cbar = plt.colorbar(ScalarMappable(cmap=LinearSegmentedColormap.from_list("mycmap1", colors, N=256)),
label='Complete colormap', ticks=np.linspace(0, 1, len(colors)))
cbar.ax.set_yticklabels(colors)
plt.colorbar(ticks=bounds, label=f'LinearSegmentedColormap N={cmap1.N}')
plt.show()
左边N=5,右边N=10。
下图显示了相同的情况,但颜色更易区分。平滑颜色条上的粗标记显示分段颜色条的确切颜色来源。
PS:以类似的方式创建图例:
from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.lines import Line2D
import numpy as np
colors = ['#FBE9BD', '#F2C370', '#E58B48', '#C35D30', '#A12F29']
cmap1 = LinearSegmentedColormap.from_list("mycmap1", colors, N=10)
minval = 50
maxval = 450
bounds = np.linspace(minval, maxval, cmap1.N + 1)
x = np.random.uniform(size=1000)
y = np.random.uniform(minval, maxval, size=x.size)
plt.scatter(x, y, c=y, vmin=minval, vmax=maxval, cmap=cmap1)
handles = [Line2D([], [], color=cmap1(i / (cmap1.N - 1)),
marker='o', ls='', label=f'{bounds[i]:.0f}-{bounds[i+1]:.0f}')
for i in range(cmap1.N) if i < 6 or i == cmap1.N-1]
plt.legend(handles=handles, bbox_to_anchor=[1.02, 1.02], loc='upper left')
plt.tight_layout()
plt.show()