You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用动态变量为不同Matplotlib图表设置不同FuncFormatter

循环生成多图时动态绑定Y轴缩放比例的问题解决

我需要在循环中生成多个图表,每个图表展示同一条曲线,同时右侧Y轴使用不同的缩放比例,且缩放比例依赖循环变量。

固定缩放因子的代码可以正常运行:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

data = np.random.normal(0, 0.01, (20))

# 这段代码正常工作,两个图表的右侧Y轴分别按2倍和10倍缩放
for right_scale in [2, 10]:
    fig, ax = plt.subplots()
    ax.plot(data)
    ax2 = ax.twinx()
    ax2.set_ylim(ax.get_ylim())
    if right_scale == 2:
        formatter = FuncFormatter(lambda x, pos: '{:.2f}'.format(x * 2))
    else:
        formatter = FuncFormatter(lambda x, pos: '{:.3f}'.format(x * 10))
    ax2.yaxis.set_major_formatter(formatter)
plt.show()

但改用动态循环变量时,所有图表的右侧Y轴都按最后一个缩放因子(10倍)显示,问题出在lambda函数绑定的是变量引用而非定义时的具体值。


问题原因

Python的lambda函数在定义时不会立即捕获变量的当前值,而是保留对变量的引用。当循环执行完毕,right_scale的最终值为10,所有之前创建的lambda函数都会使用这个最终值。


解决方案

方法1:用默认参数捕获当前值

在lambda中添加默认参数,将当前的right_scale值作为默认值传入,让lambda捕获定义时的具体值而非变量引用:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

data = np.random.normal(0, 0.01, (20))

for right_scale in [2, 10]:
    fig, ax = plt.subplots()
    ax.plot(data)
    ax2 = ax.twinx()
    ax2.set_ylim(ax.get_ylim())
    if right_scale == 2:
        # 通过默认参数s=right_scale捕获当前循环的缩放值
        formatter = FuncFormatter(lambda x, pos, s=right_scale: '{:.2f}'.format(x * s))
    else:
        formatter = FuncFormatter(lambda x, pos, s=right_scale: '{:.3f}'.format(x * s))
    ax2.yaxis.set_major_formatter(formatter)
plt.show()

方法2:用工厂函数生成格式化器

定义专门的工厂函数,利用函数局部作用域保存当前的缩放因子值:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

data = np.random.normal(0, 0.01, (20))

def create_formatter(scale):
    # 函数局部作用域会保存当前传入的scale值
    if scale == 2:
        return FuncFormatter(lambda x, pos: '{:.2f}'.format(x * scale))
    else:
        return FuncFormatter(lambda x, pos: '{:.3f}'.format(x * scale))

for right_scale in [2, 10]:
    fig, ax = plt.subplots()
    ax.plot(data)
    ax2 = ax.twinx()
    ax2.set_ylim(ax.get_ylim())
    formatter = create_formatter(right_scale)
    ax2.yaxis.set_major_formatter(formatter)
plt.show()

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 02:48:24