You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何从3D NumPy数组生成Matplotlib 3D曲面图所需的2D数组并实现绘图

解决3D数组转plot_surface所需2D数组的问题

首先,咱们得先理清核心逻辑:plot_surface要求的三个2D数组,本质是两个坐标轴的网格坐标加上对应网格点的高度值。你的example_data是形状为(4,3,6)的三维标量场(每个(x,y,z)位置对应一个数值),所以要画曲面图,得先确定你想展示哪个平面上的数值分布作为高度——也就是固定三个维度中的一个,用另外两个维度构建平面网格,三维数组的对应切片就是高度。

第一步:定义坐标轴的基础取值

先把你的三维数组三个维度对应的坐标值明确下来,和你之前用meshgrid的逻辑保持一致:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d

# 对应example_data的三个维度:(Ny, Nx, Nz) = (4,3,6)
Nx, Ny, Nz = 3, 4, 6
x_vals = np.arange(Nx)    # X轴取值:[0,1,2]
y_vals = np.arange(Ny)    # Y轴取值:[0,1,2,3]
z_vals = -np.arange(Nz)   # Z轴取值:[0,-1,-2,-3,-4,-5]
example_data = np.array([[[ 0. , -0.17641481, -0.72472288, -1.634733 , -2.88745155, -4.45446602], [-0.13739369, -0.31310624, -0.85886054, -1.76420826, -3.01012461, -4.56879708], [-0.35161935, -0.52612019, -1.06770701, -1.96573273, -3.20127564, -4.74702167]], [[-0.04258234, -0.21878815, -0.76633309, -1.67490601, -2.92547351, -4.48988789], [-0.19878962, -0.37417798, -0.91875395, -1.82200802, -3.06494007, -4.61990366], [-0.43114388, -0.60516764, -1.14515408, -2.04045165, -3.27220115, -4.81316763]], [[-0.10061408, -0.27653455, -0.82302458, -1.7296353 , -2.97729546, -4.53817427], [-0.27544339, -0.4504148 , -0.99350961, -1.89414589, -3.1333632 , -4.68370029], [-0.52562477, -0.69907413, -1.23715577, -2.12921336, -3.35644715, -4.89172916]], [[-0.17403085, -0.34958509, -0.89471911, -1.79884052, -3.04285776, -4.59927476], [-0.36725838, -0.54171551, -1.08302212, -1.9805198 , -3.21529955, -4.76010013], [-0.63493209, -0.80770802, -1.34358099, -2.23188968, -3.45389109, -4.9825877 ]]])

第二步:用meshgrid生成网格并绘制曲面

根据你想展示的平面方向,分三种情况实现:

情况1:固定Z轴,展示X-Y平面的数值曲面

比如选Z轴第一个取值(z_vals[0] = 0),此时高度数组是example_data[:, :, 0],形状为(4,3)。我们用meshgrid生成X和Y的2D网格:

# 生成X-Y平面的2D网格,形状为(Ny, Nx) = (4,3),和高度数组形状匹配
X, Y = np.meshgrid(x_vals, y_vals)
# 高度数组取Z=0对应的切片
Z_height = example_data[:, :, 0]

# 绘制曲面
fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(projection='3d')
ax.plot_surface(X, Y, Z_height, edgecolor='royalblue', lw=0.5, rstride=1, cstride=1, alpha=0.7)
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Data Value')
ax.set_title('Surface at Z=0')
plt.show()

情况2:固定Y轴,展示X-Z平面的数值曲面

选Y轴第一个取值(y_vals[0] = 0),高度数组是example_data[0, :, :],形状为(3,6)

# 生成X-Z平面的2D网格
X, Z = np.meshgrid(x_vals, z_vals)
# 高度数组取Y=0对应的切片
Y_height = example_data[0, :, :]

fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(projection='3d')
# 注意这里plot_surface的前两个参数是X和Z,第三个是高度值
ax.plot_surface(X, Z, Y_height, edgecolor='darkred', lw=0.5, rstride=1, cstride=1, alpha=0.7)
ax.set_xlabel('X Axis')
ax.set_ylabel('Z Axis')
ax.set_zlabel('Data Value')
ax.set_title('Surface at Y=0')
plt.show()

情况3:固定X轴,展示Y-Z平面的数值曲面

选X轴最后一个取值(x_vals[2] = 2),高度数组是example_data[:, 2, :],形状为(4,6)。这里要注意meshgrid的索引模式,避免形状不匹配:

# 用indexing='ij'生成形状为(Ny, Nz)的网格,和高度数组形状完全匹配
Y, Z = np.meshgrid(y_vals, z_vals, indexing='ij')
# 高度数组取X=2对应的切片
X_height = example_data[:, 2, :]

fig = plt.figure(figsize=(8,6))
ax = fig.add_subplot(projection='3d')
ax.plot_surface(Y, Z, X_height, edgecolor='green', lw=0.5, rstride=1, cstride=1, alpha=0.7)
ax.set_xlabel('Y Axis')
ax.set_ylabel('Z Axis')
ax.set_zlabel('Data Value')
ax.set_title('Surface at X=2')
plt.show()

关键疑问解答

  • 是否需要生成[4,3]、[4,6]、[3,6]的数组?
    不需要,你只需要根据要绘制的曲面方向,生成对应两个坐标轴的2D网格,再取三维数组的对应切片作为高度即可。
  • meshgrid能不能实现转换?
    完全可以!meshgrid的核心就是把一维坐标转换成二维网格,只要匹配好网格的形状和数据切片的形状(注意indexing参数的使用,默认xy模式和ij模式会生成不同形状的网格)。

额外说明

如果你想绘制类似官方示例的完整三维曲面(不是单一切片),那你的数据需要是一个“二维高度场”(每个(x,y)对应一个z值),而你的数据是三维标量场,这种场景下通常用体绘制(比如mayavi库)或者多切片曲面组合来可视化,单靠plot_surface无法直接展示整个三维标量场。

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

火山引擎 最新活动