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

Python中如何基于不同尺寸网格点绘制3D表面图?

解决合并矩形网格点的3D表面图颜色映射问题

首先,你遇到的颜色映射失效问题,核心原因是两个独立的plot_surface调用会各自计算自己的颜色范围——也就是说,第一个表面用的是自身Z值的 min/max 来映射颜色,第二个表面也是如此,导致原本数值高的蓝色区域(应该显示红色)因为自身范围小而被映射成了蓝色。

方法一:统一颜色范围(快速修复)

最简单的解决方式是,先计算所有Z值的全局最小值和最大值,然后在两个plot_surface中统一指定vmin和vmax参数,让它们共享同一个颜色映射范围:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

# 假设你已经有了gridValue、x1/x2、y1/y2这些数据
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x1 = np.arange(0,2,1)
x2 = np.arange(0,10,1)
y1 = np.arange(0,5,1)
y2 = np.arange(5,12,1)

Y1, X1 = np.meshgrid(x1, y1)
Y2, X2 = np.meshgrid(x2, y2)

gridValue1 = gridValue[:10]
gridValue2 = gridValue[10:]
Z1 = gridValue1.reshape(X1.shape)
Z2 = gridValue2.reshape(X2.shape)

# 计算全局的Z值范围
global_min = min(Z1.min(), Z2.min())
global_max = max(Z1.max(), Z2.max())

# 绘制两个表面时统一指定vmin和vmax
cset1 = ax.plot_surface(X1, Y1, Z1, cmap=cm.coolwarm, linewidth=0, 
                        antialiased=False, vmin=global_min, vmax=global_max)
cset2 = ax.plot_surface(X2, Y2, Z2, cmap=cm.coolwarm, linewidth=0, 
                        antialiased=False, vmin=global_min, vmax=global_max)

# 添加颜色条(注意只需要一个,因为颜色范围统一了)
fig.colorbar(cset1, shrink=0.5, aspect=5)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('σ ')
plt.show()

这样两个表面就会使用同一个颜色映射规则,数值高的区域会正确显示为红色,低的显示为蓝色。

方法二:构造完整网格(更优雅的方式)

如果你不想分开绘制,还可以先构造一个完整的大网格,把没有数据的区域设为NaN,然后一次性绘制,这样天然就会有统一的颜色映射:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

# 构造完整的X、Y网格
x_full = np.arange(0,10,1)
y_full = np.arange(0,12,1)
X_full, Y_full = np.meshgrid(x_full, y_full)

# 初始化Z_full为NaN
Z_full = np.full(X_full.shape, np.nan)

# 填充第一个矩形区域(y从0到4,x从0到1)
Z_full[0:5, 0:2] = gridValue[:10].reshape(5,2)
# 填充第二个矩形区域(y从5到11,x从0到9)
Z_full[5:12, 0:10] = gridValue[10:].reshape(7,10)

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 一次性绘制完整表面,NaN区域会自动被忽略
cset = ax.plot_surface(X_full, Y_full, Z_full, cmap=cm.coolwarm, 
                       linewidth=0, antialiased=False)

fig.colorbar(cset, shrink=0.5, aspect=5)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('σ ')
plt.show()

这种方法更接近你最开始尝试的完整网格绘制思路,而且不需要分开处理两个表面,颜色映射自然是统一的,也避免了reshape错误(因为我们是按实际数据位置填充到完整网格的对应区域)。

补充说明

  • 你最开始遇到的ValueError: cannot reshape array of size 80 into shape (12,10),是因为完整网格(12,10)需要120个点,但你只有80个有效数据点,直接reshape肯定不行——上面的方法二通过填充NaN解决了这个问题。
  • clabel方法通常是给等高线图(contour)用的,plot_surface并不支持clabel,所以你之前的ax.clabel(cset1)其实不会生效,建议去掉这两行代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:02:06