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

Matplotlib如何实现Y轴局部非线性或截断适配极值数据?

解决Matplotlib中极值拉伸Y轴的可视化问题

针对你的数据(90%低值、10%极高值)导致Y轴被拉伸的问题,这里提供三个实用的解决方案:

一、断裂Y轴(截断处理)

直接把Y轴分成上下两段,让低值区域拥有足够的展示空间,高值区域单独占一小段,中间用断裂标记区分,既能看清低值细节,又能保留高值的存在。

import matplotlib.pyplot as plt
import numpy as np

# 模拟你的数据分布
low_values = np.random.uniform(0.32, 16.27, 90)
high_values = np.random.uniform(200, 367.1, 10)
data = np.concatenate([low_values, high_values])
x = np.arange(len(data))

# 创建上下两个子图,共享X轴
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8, 6), sharex=True)
fig.subplots_adjust(hspace=0.05)  # 缩小子图间距,让断裂更自然

# 下方子图:展示低值区域
ax2.plot(x, data, 'o')
ax2.set_ylim(0, 17)  # 覆盖最大低值16.27
ax2.set_ylabel('数值')
# 隐藏上方边框,避免重复
ax2.spines['top'].set_visible(False)
ax2.tick_params(labeltop=False)

# 上方子图:展示高值区域
ax1.plot(x, data, 'o')
ax1.set_ylim(350, 370)  # 覆盖最高值367.1
# 隐藏下方边框
ax1.spines['bottom'].set_visible(False)
ax1.tick_params(labelbottom=False)

# 添加断裂标记
d = .015  # 控制断裂线的倾斜角度
kwargs = dict(transform=ax1.transAxes, color='k', clip_on=False)
ax1.plot((-d, +d), (-d, +d), **kwargs)        # 左上断裂线
ax1.plot((1 - d, 1 + d), (-d, +d), **kwargs)  # 右上断裂线

kwargs.update(transform=ax2.transAxes)
ax2.plot((-d, +d), (1 - d, 1 + d), **kwargs)  # 左下断裂线
ax2.plot((1 - d, 1 + d), (1 - d, 1 + d), **kwargs)  # 右下断裂线

ax1.set_title('断裂Y轴展示极值数据')
plt.xlabel('样本索引')
plt.show()

二、局部非线性缩放

自定义分段缩放函数,对低值区域用线性缩放保证细节,对高值区域用压缩式缩放(比如平方根),通过调整缩放系数让整体刻度间距看起来均匀。

import matplotlib.pyplot as plt
import numpy as np

def forward(x):
    # 分段处理:<=16.27用线性,>16.27用平方根压缩
    mask = x <= 16.27
    out = np.empty_like(x)
    out[mask] = x[mask]
    # 调整缩放系数k,控制高值区域的轴间距
    k = 0.2
    out[~mask] = 16.27 + (np.sqrt(x[~mask]) - np.sqrt(16.27)) * k
    return out

def inverse(x):
    # 逆变换,对应forward函数
    mask = x <= 16.27
    out = np.empty_like(x)
    out[mask] = x[mask]
    k = 0.2
    out[~mask] = ((x[~mask] - 16.27)/k + np.sqrt(16.27)) ** 2
    return out

# 模拟数据
low_values = np.random.uniform(0.32, 16.27, 90)
high_values = np.random.uniform(200, 367.1, 10)
data = np.concatenate([low_values, high_values])
x = np.arange(len(data))

fig, ax = plt.subplots(figsize=(8,6))
ax.plot(x, data, 'o')
# 设置自定义缩放
ax.set_yscale('function', functions=(forward, inverse))

# 手动设置刻度,保证间距均匀
yticks = [0.32, 4.3075, 8.295, 12.2825, 16.27, 100, 200, 367.1]
ax.set_yticks(yticks)
ax.set_yticklabels([str(t) for t in yticks])

ax.set_title('局部非线性缩放Y轴')
ax.set_xlabel('样本索引')
ax.set_ylabel('数值')
plt.show()

提示:可以根据实际效果调整k值,让16.27到367.1的轴间距和前面的刻度间距匹配。

三、聚焦低值+突出高值

如果不需要精确展示高值的分布细节,只需提示存在高值,可以让Y轴聚焦于低值区域,同时用颜色或注释突出高值样本。

import matplotlib.pyplot as plt
import numpy as np

# 模拟数据
low_values = np.random.uniform(0.32, 16.27, 90)
high_values = np.random.uniform(200, 367.1, 10)
data = np.concatenate([low_values, high_values])
x = np.arange(len(data))

fig, ax = plt.subplots(figsize=(8,6))
# 绘制低值样本
ax.plot(x, data, 'o', color='blue', label='低值样本')
# 筛选并绘制高值样本,用红色突出
high_indices = np.where(data > 16.27)[0]
ax.plot(x[high_indices], data[high_indices], 'o', color='red', label='高值样本')

# Y轴聚焦低值区域
ax.set_ylim(0, 17)
ax.set_yticks([0.32, 4.3075, 8.295, 12.2825, 16.27])

# 添加注释说明高值范围
ax.annotate(f'高值范围: {np.min(high_values):.1f}~{np.max(high_values):.1f}', 
            xy=(0.95, 0.95), xycoords='axes fraction',
            ha='right', va='top', bbox=dict(boxstyle='round', facecolor='wheat'))

ax.set_title('聚焦低值区域+突出高值样本')
ax.set_xlabel('样本索引')
ax.set_ylabel('数值')
ax.legend()
plt.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 00:24:50