精确控制坐标轴的刻度位置和标签格式,是实现专业图表的必要技能。

ticker 模块控制刻度的位置。
import matplotlib.pyplot as pltimport matplotlib.ticker as tickerimport numpy as npfig, axes = plt.subplots(3, 2, figsize=(12, 10))x = np.linspace(0, 10, 100)locators = [ ('AutoLocator', ticker.AutoLocator()), ('MaxNLocator', ticker.MaxNLocator(nbins=5)), ('LinearLocator', ticker.LinearLocator(numticks=10)), ('MultipleLocator', ticker.MultipleLocator(base=0.5)), ('FixedLocator', ticker.FixedLocator([0.5, 2, 4.7, 8.3])), ('LogLocator', ticker.LogLocator(base=10)),]for (name, loc), ax in zip(locators, axes.flat): ax.plot(x, np.sin(x)) ax.xaxis.set_major_locator(loc) ax.set_title(name)| Locator | 说明 | 常用参数 |
|---|---|---|
AutoLocator | 自动选择(默认) | — |
MaxNLocator | 最多 N 个刻度 | nbins, steps, integer |
LinearLocator | 等距刻度 | numticks |
MultipleLocator | 基数的倍数位置 | base |
FixedLocator | 固定位置 | locs (列表) |
IndexLocator | 等距 + 偏移 | base, offset |
LogLocator | 对数刻度 | base, subs |
SymmetricalLogLocator | 对称对数 | base, linthresh |
NullLocator | 无刻度 | — |
# 常用 Locator 示例ax.xaxis.set_major_locator(ticker.MaxNLocator(nbins=6, integer=True, steps=[1, 2, 5, 10]))ax.yaxis.set_major_locator(ticker.MultipleLocator(0.2)) # 每 0.2 一个刻度ax.xaxis.set_major_locator(ticker.LogLocator(base=10, subs='all')) # 对数ax.xaxis.set_major_locator(ticker.NullLocator()) # 隐藏刻度
fig, ax = plt.subplots(figsize=(10, 5))ax.plot(x, np.sin(x))# 主刻度(major ticks)ax.xaxis.set_major_locator(ticker.MultipleLocator(2))# 次刻度(minor ticks)ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.5))# 开启次刻度网格ax.grid(which='major', color='gray', linestyle='-', linewidth=0.8)ax.grid(which='minor', color='lightgray', linestyle='--', linewidth=0.4)# AutoMinorLocator 自动设置次刻度ax.xaxis.set_minor_locator(ticker.AutoMinorLocator(n=4)) # 每个主刻度间 4 个次刻度
Formatter 控制刻度标签的显示格式。
formatters = [ ('ScalarFormatter', ticker.ScalarFormatter()), ('FormatStrFormatter', ticker.FormatStrFormatter('%.2f')), ('PercentFormatter', ticker.PercentFormatter(xmax=100, decimals=1)), ('FuncFormatter', ticker.FuncFormatter(lambda x, p: f'{x:.1f}°C')), ('FixedFormatter', ticker.FixedFormatter(['A', 'B', 'C', 'D', 'E'])), ('StrMethodFormatter', ticker.StrMethodFormatter('{x:.3f}')), ('EngFormatter', ticker.EngFormatter(unit='V')), ('LogFormatter', ticker.LogFormatter(base=10)), ('NullFormatter', ticker.NullFormatter()),]ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.2f'))# 常用格式: '%.2f'(两位小数), '%.0f'(整数), '%d'(整数), '%e'(科学计数)# xmax=100: 0-100 范围显示为 0%-100%# xmax=1: 0-1 范围显示为 0%-100%ax.yaxis.set_major_formatter(ticker.PercentFormatter(xmax=1, decimals=0))
# 自定义格式化函数# 接收两个参数: x(刻度值), pos(位置,通常不用)def currency_fmt(x, pos): if x >= 1e6: return f'¥{x/1e6:.1f}M' elif x >= 1e3: return f'¥{x/1e3:.0f}K' else: return f'¥{x:.0f}'ax.yaxis.set_major_formatter(ticker.FuncFormatter(currency_fmt))# Lambda 版本ax.yaxis.set_major_formatter( ticker.FuncFormatter(lambda x, p: f'{x:,.0f}'))# 日期格式化from datetime import datetimeax.xaxis.set_major_formatter( ticker.FuncFormatter(lambda x, p: datetime.fromtimestamp(x).strftime('%Y-%m')))ax.yaxis.set_major_formatter(ticker.EngFormatter(unit='Hz'))# 自动使用 k, M, G, m, μ 等单位前缀
formatter = ticker.ScalarFormatter()formatter.set_powerlimits((-3, 4)) # 超出范围才用科学计数法formatter.set_useOffset(True) # 使用偏移量formatter.set_useMathText(True) # LaTeX 风格ax.yaxis.set_major_formatter(formatter)
刻度线样式
# 刻度线参数ax.tick_params( axis='both', # 'x', 'y', 'both' which='major', # 'major', 'minor', 'both' direction='in', # 'in', 'out', 'inout' length=8, # 刻度线长度 width=1.5, # 刻度线宽度 color='red', # 刻度线颜色 pad=8, # 刻度与标签的间距 labelsize=12, # 标签字体大小 labelcolor='black', # 标签颜色 labelrotation=45, # 标签旋转角度 top=True, # 是否显示顶部刻度 right=True, # 是否显示右侧刻度 bottom=True, # 是否显示底部刻度 left=True # 是否显示左侧刻度)# 单独设置ax.tick_params(axis='x', labelrotation=45, labelsize=10)ax.tick_params(axis='y', which='minor', length=4, color='gray')
fig, ax = plt.subplots(figsize=(8, 5))ax.plot(x, np.sin(x))# 隐藏上方和右侧边框ax.spines['top'].set_visible(False)ax.spines['right'].set_visible(False)# 移动边框位置ax.spines['left'].set_position(('data', 0)) # 左框移到 x=0ax.spines['bottom'].set_position(('data', 0)) # 下框移到 y=0ax.spines['left'].set_position(('axes', 0.05)) # 左框在 5% 处ax.spines['left'].set_position('center') # 左框在中间# 边框样式ax.spines['bottom'].set_color('red')ax.spines['bottom'].set_linewidth(2)ax.spines['bottom'].set_linestyle('--')import matplotlib.dates as mdatesfrom datetime import datetime, timedelta# 生成日期数据dates = [datetime(2024, 1, 1) + timedelta(days=i) for i in range(365)]values = np.random.randn(365).cumsum()fig, ax = plt.subplots(figsize=(14, 5))ax.plot(dates, values)# 日期 Locatorax.xaxis.set_major_locator(mdates.MonthLocator(interval=1)) # 每月ax.xaxis.set_minor_locator(mdates.WeekdayLocator(byweekday=mdates.MO)) # 每周一# 日期 Formatterax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d')) # "Jan 01"ax.xaxis.set_major_formatter(mdates.ConciseDateFormatter( ax.xaxis.get_major_locator())) # 简洁自适应格式(推荐)# 自动格式化fig.autofmt_xdate(rotation=45, ha='right') # 自动旋转日期标签# 日期 Locator 速查# DayLocator, HourLocator, MinuteLocator, SecondLocator# MonthLocator, YearLocator# WeekdayLocator, AutoDateLocatorfig, ax = plt.subplots(figsize=(10, 6))ax.plot(x, y)# 左侧用原始值ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.1f'))# 右侧辅助轴用百分比secax = ax.secondary_yaxis('right', functions=( lambda x: x / y_total * 100, # forward lambda x: x / 100 * y_total # inverse))secax.yaxis.set_major_formatter(ticker.PercentFormatter())secax.set_ylabel('Percentage')fig, ax = plt.subplots(figsize=(10, 5))ax.plot(x, np.sin(x))# 只保留左/下边框for spine in ['top', 'right']: ax.spines[spine].set_visible(False)# 刻度线朝外ax.tick_params(axis='both', direction='out', length=5, width=1)# 网格ax.grid(True, which='major', axis='y', color='lightgray', linestyle='-', linewidth=0.5)# 偏移边框ax.spines['left'].set_position(('outward', 10))ax.spines['bottom'].set_position(('outward', 10))