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

如何将Matplotlib图表X轴设置为非均匀刻度以优化低区间数据展示

Matplotlib X轴刻度比例调整问题

我用Matplotlib绘图时遇到个问题:想放大X轴0-500区间的刻度比例,让1000-3000区间的显示宽度和0-500区间一致,以此更清晰展示0-500区间的数据。期望的刻度点为[0,100,200,300,400,500,2000,3000],尝试了以下代码但未达到预期效果:

fig, ax = plt.subplots()
x = [0, 100,200, 300, 400, 500, 1000, 2000, 3000]
ax.xaxis.set_ticks(range(len(x)))
ax.xaxis.set_ticklabels(x)

plt.plot(df_run_curves_rhc_60["Iteration"],df_run_curves_rhc_60["Fitness"], label="RHC", color="blue")
plt.plot(df_run_curves_sa_60["Iteration"],df_run_curves_sa_60["Fitness"], label="SA", color="orange")
plt.plot(df_run_curves_ga_60["Iteration"],df_run_curves_ga_60["Fitness"], label="GA", color="green")
plt.plot(df_run_curves_mimic_60["Iteration"],df_run_curves_mimic_60["Fitness"], label="MIMIC", color="yellow")
plt.title("Flip Flop Fitness vs iterations - Size 60 - Max Attempts 200")

plt.xlabel("Iterations")
plt.ylabel("Fitness Score")
plt.legend()
plt.show()

图表情况说明

  • 原图表:X轴按线性刻度分布,0-500区间占比极小,该区间数据展示模糊
  • 代码生成的图表:X轴刻度被强制均匀排列,但实际对应迭代值的间隔差异极大,导致曲线形态失真

解决方案:实现非线性X轴缩放

你的需求本质是自定义X轴的刻度比例,通过将原始X值映射到均匀分布的刻度位置即可实现,以下提供两种可行方法:

方法1:手动映射X值(简单直接)

import matplotlib.pyplot as plt

# 定义目标刻度点和对应的均匀位置
target_ticks = [0, 100, 200, 300, 400, 500, 2000, 3000]
tick_positions = range(len(target_ticks))

# 编写映射函数,处理原始X值到刻度位置的转换(含线性插值)
def map_x(x_val):
    for i in range(len(target_ticks)-1):
        if target_ticks[i] <= x_val <= target_ticks[i+1]:
            ratio = (x_val - target_ticks[i]) / (target_ticks[i+1] - target_ticks[i])
            return tick_positions[i] + ratio * (tick_positions[i+1] - tick_positions[i])
    # 处理超出刻度范围的情况
    if x_val > target_ticks[-1]:
        ratio = (x_val - target_ticks[-1])/(target_ticks[-1]-target_ticks[-2])
        return tick_positions[-1] + ratio*(tick_positions[-1]-tick_positions[-2])
    return tick_positions[0]

fig, ax = plt.subplots()

# 对每条曲线的X值做映射后绘图
ax.plot([map_x(x) for x in df_run_curves_rhc_60["Iteration"]], df_run_curves_rhc_60["Fitness"], label="RHC", color="blue")
ax.plot([map_x(x) for x in df_run_curves_sa_60["Iteration"]], df_run_curves_sa_60["Fitness"], label="SA", color="orange")
ax.plot([map_x(x) for x in df_run_curves_ga_60["Iteration"]], df_run_curves_ga_60["Fitness"], label="GA", color="green")
ax.plot([map_x(x) for x in df_run_curves_mimic_60["Iteration"]], df_run_curves_mimic_60["Fitness"], label="MIMIC", color="yellow")

# 设置X轴刻度和标签
ax.set_xticks(tick_positions)
ax.set_xticklabels(target_ticks)

plt.title("Flip Flop Fitness vs iterations - Size 60 - Max Attempts 200")
plt.xlabel("Iterations")
plt.ylabel("Fitness Score")
plt.legend()
plt.show()

方法2:使用Matplotlib自定义缩放类(更规范)

通过自定义Transform实现可复用的非线性缩放:

import matplotlib.pyplot as plt
from matplotlib.scale import FuncScale
from matplotlib.transforms import Transform

class CustomXTransform(Transform):
    input_dims = 1
    output_dims = 1
    is_separable = True

    def __init__(self, target_ticks):
        super().__init__()
        self.target_ticks = target_ticks
        self.tick_positions = range(len(target_ticks))

    def transform_non_affine(self, x):
        result = []
        for x_val in x:
            found = False
            for i in range(len(self.target_ticks)-1):
                if self.target_ticks[i] <= x_val <= self.target_ticks[i+1]:
                    ratio = (x_val - self.target_ticks[i]) / (self.target_ticks[i+1] - self.target_ticks[i])
                    result.append(self.tick_positions[i] + ratio * (self.tick_positions[i+1] - self.tick_positions[i]))
                    found = True
                    break
            if not found:
                if x_val > self.target_ticks[-1]:
                    ratio = (x_val - self.target_ticks[-1])/(self.target_ticks[-1]-self.target_ticks[-2])
                    result.append(self.tick_positions[-1] + ratio*(self.tick_positions[-1]-self.tick_positions[-2]))
                else:
                    result.append(self.tick_positions[0])
        return result

    def inverted(self):
        # 实现反向转换,支持图表交互功能
        class InvertedCustomXTransform(Transform):
            def __init__(self, parent):
                super().__init__()
                self.parent = parent
            def transform_non_affine(self, pos):
                result = []
                for p in pos:
                    found = False
                    for i in range(len(self.parent.tick_positions)-1):
                        if self.parent.tick_positions[i] <= p <= self.parent.tick_positions[i+1]:
                            ratio = (p - self.parent.tick_positions[i]) / (self.parent.tick_positions[i+1] - self.parent.tick_positions[i])
                            result.append(self.parent.target_ticks[i] + ratio*(self.parent.target_ticks[i+1]-self.parent.target_ticks[i]))
                            found = True
                            break
                    if not found:
                        if p > self.parent.tick_positions[-1]:
                            ratio = (p - self.parent.tick_positions[-1])/(self.parent.tick_positions[-1]-self.parent.tick_positions[-2])
                            result.append(self.parent.target_ticks[-1] + ratio*(self.parent.target_ticks[-1]-self.parent.target_ticks[-2]))
                        else:
                            result.append(self.parent.target_ticks[0])
                return result
            def inverted(self):
                return self.parent
        return InvertedCustomXTransform(self)

# 注册自定义缩放类型
FuncScale.register_custom_scale('custom_x', CustomXTransform)

fig, ax = plt.subplots()
# 应用自定义X轴缩放
ax.set_xscale('custom_x', target_ticks=[0,100,200,300,400,500,2000,3000])

# 直接使用原始X值绘图即可
ax.plot(df_run_curves_rhc_60["Iteration"],df_run_curves_rhc_60["Fitness"], label="RHC", color="blue")
ax.plot(df_run_curves_sa_60["Iteration"],df_run_curves_sa_60["Fitness"], label="SA", color="orange")
ax.plot(df_run_curves_ga_60["Iteration"],df_run_curves_ga_60["Fitness"], label="GA", color="green")
ax.plot(df_run_curves_mimic_60["Iteration"],df_run_curves_mimic_60["Fitness"], label="MIMIC", color="yellow")

plt.title("Flip Flop Fitness vs iterations - Size 60 - Max Attempts 200")
plt.xlabel("Iterations")
plt.ylabel("Fitness Score")
plt.legend()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:41:03