『Python』matplotlib自定义colormap与ticklabel

本文介绍如何在Matplotlib中自定义颜色映射(colormap)和坐标轴形式,包括创建自定义colormap、设置坐标轴刻度及标签,以及调整字体样式和网格线,适用于全球经纬网数据可视化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 自定义colormap

from matplotlib import cm
from matplotlib.colors import LinearSegmentedColormap

# 定义colorbar的颜色帧
color_list = ['#0000FF', '#3333FF', '#00FF33', '#FFFF33', '#FF9900', '#FF0000', '#FF00FF', '#6600CC']

# 线性补帧,并定义自定义colormap的名字,此处为rain
my_cmap = LinearSegmentedColormap.from_list('rain', color_list)

# 注册自定义的cmap,此后可以像使用内置的colormap一样使用自定义的rain
cm.register_cmap(cmap=my_cmap)

gci = plt.imshow(data, vmin=0, vmax=10, cmap="rain")  # data是你要可视化的矩阵,使用时直接使用rain这个名字

2. 自定义坐标轴形式

from matplotlib.ticker import MultipleLocator
from mpl_toolkits.axes_grid1 import make_axes_locatable
import matplotlib.pyplot as plt
import matplotlib as mpl

mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['font.serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题,或者转换负号为字符串

# 示例的data的shape是(514, 1028),我们想要让其坐标显示全球的经纬网效果

plt.figure(figsize=(18, 9))  # 创建画布

ax = plt.subplot(111)  # 划分子图,这里只有1x1的子图

gci = ax.imshow(data, vmin=0, vmax=10, cmap="rain")  # 画热力图,这里cmap用的就是自定义的rain

# ================================= 二选一即可 ==================================

# 方法一:设置主要刻度,MultipleLocator传的参数会导致该参数的整数倍都会显示刻度
ax.xaxis.set_major_locator(MultipleLocator(1028 / 12))
ax.yaxis.set_major_locator(MultipleLocator(514 / 6))

# 方法二:直接设置要显示的刻度列表
ax.xaxis.set_ticks(np.arange(0, 1029, 1028 / 12.))
ax.yaxis.set_ticks(np.arange(0, 515, 514 / 6.))

# =============================================================================

# 自定义要显示的刻度值标签,替代实际刻度值
ax.set_xticklabels([-180, -150, -120, -90, -60, -30, 0, 30, 60, 90, 120, 150, 180])
ax.set_yticklabels([-90, -60, -30, 0, 30, 60, 90])

# 设置要显示的坐标轴的位置
ax.xaxis.set_ticks_position("top")
ax.yaxis.set_ticks_position("left")

# =============================== 设置刻度样式 ==================================
for ticklabel in ax.xaxis.get_ticklabels():
    ticklabel.set_fontfamily("Times New Roman")
    ticklabel.set_fontweight("bold")
    ticklabel.set_fontsize(10)

for ticklabel in ax.yaxis.get_ticklabels():
    ticklabel.set_fontfamily("Times New Roman")
    ticklabel.set_fontweight("bold")
    ticklabel.set_fontsize(10)

# 显示网格
# which: 显示什么刻度,major表示主刻度,minor表示副刻度,both表示都显示
# axis: 显示哪一个轴的网格线,both表示全部显示,x表示只显示x轴网格线,y表示只显示y轴网格线
plt.grid(which="major", axis="both", linestyle="-", color="black")

divider = make_axes_locatable(ax)  # 指定要显示哪个子图的colorbar
cax = divider.append_axes("bottom", size="5%", pad=0.2)  # size表示colorbar宽度,pad表示colorbar距离axes的距离
cbar = plt.colorbar(gci, ax=ax, cax=cax, orientation='horizontal')
cbar.set_ticks([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# 设置colorbar相关的字体格式
font = {
    "family": "times new roman",
    "color": "darkred",
    "style": 'italic',
    "weight": "bold",
    "size": "16",
}
cbar.set_label(r'$rain(mm\cdot h^{-1})$', fontdict=font)

# 设置图形的标题,注意,这里是suptitle,表示全部子图的标题,colorbar也是一个子图,所以直接plt.title()显示的是colorbar的标题
plt.suptitle("Global Precipitation on 2020-06-29", family="times new roman",
                 size=24, weight="bold", style="italic",color="blue",
                 verticalalignment="center",  # 水平对齐方式
                 horizontalalignment="center",  # 垂直对齐方式
                 y=0.95)

plt.show()

最终,画出来的图的效果为:

在这里插入图片描述

<think>嗯,用户想了解如何在Matplotlib自定义colormap的映射方式。首先,我需要回忆一下Matplotlib中关于colormap的相关知识。记得colormap用于将数据值映射到颜色,这在可视化中很重要,比如热图、散点图等。 用户提到的自定义映射方式,可能需要调整现有colormap或者创建全新的。我记得Matplotlib提供了几种方法,比如使用LinearSegmentedColormap或ListedColormap自定义colormap。另外,可能还涉及到归一化(Normalization)的过程,将数据范围映射到0-1之间,然后通过colormap转换为颜色。 然后,我需要检查系统提供的引用内容。引用3提到colormap参数可以自动分配颜色,引用4提到ax参数的使用。不过用户的问题主要在于如何自定义映射,可能需要更详细的步骤。比如,如何创建自定义colormap,或者如何修改现有的映射方式。 接下来,我应该分步骤解释。首先,从预定义的colormap中选择并修改,比如截取部分颜色。例如,使用`truncate_colormap`函数截取'viridis'的一部分。然后,创建全新的colormap,通过指定颜色列表或者颜色分段。 另外,归一化处理也很重要。用户可能需要不同的数据映射范围,比如LogNorm或者PowerNorm,这会影响颜色如何对应数据值。例如,使用LogNorm可以让颜色在数据对数尺度上分布。 还需要示例代码来演示这些方法。比如,使用LinearSegmentedColormap定义渐变色,或者用ListedColormap定义离散颜色。同时,展示如何在绘图时应用自定义colormap和归一化方法。 可能的问题点:用户是否了解归一化的概念?是否需要解释Normalization类的作用?比如,Normalization将数据线性映射到[0,1],而其他如LogNorm处理非线性映射。这会影响颜色分布的方式。 另外,引用中提到的matplotlib.collections可能有相关类使用colormap,但用户的问题更偏向于整体colormap的定制,而非特定集合类的使用。需要确保回答集中在colormap本身的设置,而不是绘图对象的其他参数。 最后,验证步骤是否正确。比如,代码示例是否能正常运行,是否涵盖了用户的需求。可能需要检查是否有遗漏的方法,比如使用BoundaryNorm进行离散化映射,或者结合colorbar来显示映射关系。 总结回答结构:首先介绍自定义colormap的两种主要方法(修改现有和创建新),然后讲解归一化的调整,最后提供相关问题。确保每个步骤都有代码示例,并引用相关的Matplotlib文档或用户提供的引用中的内容(如引用3提到colormap参数的使用)。</think>### 在Matplotlib自定义Colormap映射方式 #### 1. 使用预定义Colormap并调整范围 通过截取现有colormap的片段实现映射范围调整: ```python import matplotlib.pyplot as plt import matplotlib.colors as mcolors def truncate_colormap(cmap, minval=0.0, maxval=1.0): return mcolors.LinearSegmentedColormap.from_list( 'truncated_' + cmap.name, cmap(np.linspace(minval, maxval, 256)) ) trunc_viridis = truncate_colormap(plt.cm.viridis, 0.2, 0.8) plt.imshow(data, cmap=trunc_viridis) ``` 这会使用viridis colormap中间60%的颜色范围[^3]。 #### 2. 创建全新Colormap **(1) 渐变颜色映射** ```python colors = ['#FF0000', '#FFFF00', '#00FF00'] # 红-黄-绿渐变 custom_cmap = mcolors.LinearSegmentedColormap.from_list('custom', colors) ``` **(2) 离散颜色映射** ```python from matplotlib.colors import ListedColormap discrete_colors = ['blue', 'green', 'red'] discrete_cmap = ListedColormap(discrete_colors, name='Discrete3') ``` #### 3. 控制数据映射范围 通过Normalization类调整数据到颜色的映射关系: ```python import numpy as np # 自定义归一化范围 class MidpointNormalize(mcolors.Normalize): def __init__(self, vmin, vmax, midpoint=0, clip=False): self.midpoint = midpoint mcolors.Normalize.__init__(self, vmin, vmax, clip) def __call__(self, value, clip=None): x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1] return np.ma.masked_array(np.interp(value, x, y)) # 使用示例 data = np.random.randn(100) norm = MidpointNormalize(vmin=-3, vmax=3, midpoint=0) plt.scatter(x, y, c=data, cmap=custom_cmap, norm=norm) ``` #### 4. 非线性映射 使用对数或指数映射: ```python from matplotlib.colors import LogNorm, PowerNorm # 对数映射 plt.imshow(np.exp(data), cmap='viridis', norm=LogNorm(vmin=1, vmax=100)) # 伽马校正映射 plt.hist2d(x, y, cmap='plasma', norm=PowerNorm(gamma=0.5)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值