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

如何用Matplotlib contourf呈现双曲型数据并优化颜色缩放?

问题描述

想用contourf绘制3D函数z=f(x,y)的图像,同时用黑色线条和自定义标签高亮z为常量的等高线。x、y、z数据存储在CSV文件中,用pandas处理,函数缩放关系为$f(x,y) \propto 1/(x \cdot y)$。

当前代码生成的图像颜色缩放效果极差:99%以上的区域颜色一致,无法区分98%-98.5%、98.5%-99%这类区间,色条显示也异常,推测是缩放设置错误。另外,通用场景下希望Z中的NaN区域显示为白色,尽量不新增额外模块。

解决方案

核心问题分析

当前contourf用len(levels)自动生成等高层级,而Z值分布极不均匀(符合1/(x·y)的反比例特性),自动分层会把绝大多数区间压缩到高值段,导致颜色区分度差。

关键修改点

  • 指定精确等高层级:直接用自定义的levels数组作为contourf的层级参数,确保每个目标区间对应独立颜色层
  • 处理NaN显示:通过颜色映射的set_bad方法,将NaN区域设为白色
  • 匹配色条与层级:让色条刻度完全对应自定义层级,避免自动生成的混乱

修改后的完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams.update({
    "text.usetex": True,
    "font.family": "sans-serif",
    "font.sans-serif": "Helvetica",
})
rcParams['text.latex.preamble'] = r'\usepackage{amsmath}' #for \text command

# 自定义格式化函数:去除末尾零并添加百分号
def fmt(x):
    s = f"{x:.2f}"
    if s.endswith("0"):
        s = f"{x:.1f}"
        if s.endswith("0"):
            s = f"{x:.0f}"
    return rf"{s} \%" if plt.rcParams["text.usetex"] else f"{s} %"

# 读取数据
contour_data = pd.read_csv('MyData.csv', header=None, names=['x','y','z'])

# 重构网格数据
Z = contour_data.pivot_table(index='x', columns='y', values='z', dropna=False).T.values
X_unique = np.sort(contour_data.x.unique())
Y_unique = np.sort(contour_data.y.unique())
X, Y = np.meshgrid(X_unique, Y_unique)

# 初始化绘图
rcParams['figure.figsize'] = 5, 5
fig = plt.figure()
ax = fig.add_subplot(111)

# 定义目标等高层级
levels = np.array([98.,98.5,99.,99.5,99.6,99.7,99.8,99.85])

# 配置颜色映射:设置NaN区域为白色
cmap = plt.get_cmap('Reds')
cmap.set_bad(color='white')

# 生成填充等高线:使用自定义levels确保区间颜色区分
cpf = ax.contourf(X,Y,Z, 
                  levels=levels,
                  extend='both',
                  cmap=cmap
                  )
# 色条刻度与自定义层级对齐
fig.colorbar(cpf, ticks=levels, orientation='vertical', format=fmt)

# 绘制黑色高亮等高线并添加标签
cp = ax.contour(X, Y, Z, 
                levels=levels, 
                colors='black')
ax.clabel(cp, cp.levels, inline=True, fmt=fmt, fontsize=10, colors='black')

# 设置坐标轴标签
ax.set_xlabel(r'$X-\text{axis } [\alpha]$')
ax.set_ylabel(r'$Y-\text{axis } [\beta]$')

# plt.savefig('contour_plot.pdf') # 按需保存图像
plt.show()

修改说明

  • 将contourf的层级参数从len(levels)改为levels,强制Matplotlib使用指定区间划分颜色,解决高值区域颜色扎堆问题
  • 通过cmap.set_bad('white')实现NaN区域显示为白色,适配通用场景
  • 色条直接使用fmt格式化函数,确保刻度显示与等高线标签一致
  • 简化等高线颜色设置,直接用colors='black'替代列表生成,代码更简洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:45:34