解决使用自定义LinearSegmentedColormap调用plt.set_cmap()时的ValueError
问题:Matplotlib自定义颜色映射用plt.set_cmap报错ValueError?
我尝试在matplotlib中使用自定义颜色映射,写了如下代码:
import numpy as np from matplotlib.colors import LinearSegmentedColormap import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib inline # color_map = mpl.cm.get_cmap('Spectral') # 获取内置颜色映射 color_map = LinearSegmentedColormap.from_list('custom', [(0, '#ff0000'), (1, '#00ff00')], N=10) x = np.array(range(10)) y = np.sin(x) plt.set_cmap(color_map) plt.plot(x, y)
执行后触发了ValueError:
ValueError: 'custom' is not a valid value for name; supported values are 'Accent', 'Accent_r', 'Blues', 'Blues_r', ...(省略部分内置映射名称)
用注释里的内置Spectral颜色映射时就没这个错误,Python版本是3.9.12,请问问题出在哪?
问题原因
plt.set_cmap()的作用是设置当前图像的默认颜色映射,但它要求传入的映射必须已经注册到Matplotlib的全局颜色映射字典里。内置的映射比如Spectral都是预先注册好的,所以能直接用;而你自定义的custom只是创建了一个局部对象,没被加入全局字典,内部逻辑尝试通过名称查找时就会报错。- 另外,
plt.plot()默认是绘制单一颜色的线条,本身并不依赖颜色映射——颜色映射是给scatter、imshow这类需要根据数值映射到不同颜色的绘图函数用的,你这里用plt.set_cmap()属于用错了场景。
解决方案
根据你的需求,分两种情况处理:
情况1:想让plot的线条呈现自定义渐变色彩
如果需要让线条根据数值显示自定义颜色映射的效果,不用plt.set_cmap(),直接在需要的绘图函数里指定cmap参数即可。注意plot本身不支持渐变线条,要实现渐变线条需要用LineCollection,或者用scatter先画点:
import numpy as np from matplotlib.colors import LinearSegmentedColormap import matplotlib.pyplot as plt from matplotlib.collections import LineCollection %matplotlib inline color_map = LinearSegmentedColormap.from_list('custom', [(0, '#ff0000'), (1, '#00ff00')], N=10) x = np.array(range(10)) y = np.sin(x) # 方式1:绘制带颜色渐变的散点 plt.scatter(x, y, c=x, cmap=color_map) plt.colorbar() # 方式2:绘制带颜色渐变的线条 points = np.column_stack((x, y)) segments = np.array([points[i:i+2] for i in range(len(points)-1)]) lc = LineCollection(segments, cmap=color_map) lc.set_array(x) # 用x值作为颜色映射的依据 plt.gca().add_collection(lc) plt.colorbar(lc) plt.xlim(x.min(), x.max()) plt.ylim(y.min(), y.max()) plt.show()
情况2:想让自定义颜色映射全局可用
如果希望自定义映射能像内置映射一样通过名称调用,或者让plt.set_cmap()生效,需要先把它注册到Matplotlib的全局字典中:
import numpy as np from matplotlib.colors import LinearSegmentedColormap import matplotlib as mpl import matplotlib.pyplot as plt %matplotlib inline # 创建自定义颜色映射并注册到全局 color_map = LinearSegmentedColormap.from_list('custom', [(0, '#ff0000'), (1, '#00ff00')], N=10) mpl.colormaps.register(color_map) # 完成注册 x = np.array(range(10)) y = np.sin(x) plt.set_cmap('custom') # 现在可以直接用名称调用自定义映射 # 用scatter测试颜色映射效果 plt.scatter(x, y, c=x) plt.colorbar() plt.show()
内容的提问来源于stack exchange,提问作者Denis Kislitsyn
相关产品推荐
相关产品推荐

