如何用Python的三个1D数组绘制3D曲面图?解决Z维度报错问题
Hey there! Let's work through your 3D plotting problem together—you've run into two key issues here: fixing the array dimension error for Z, and figuring out how to plot a surface when Z isn't a defined function of X and Y.
Z Dimension Error First, that AttributeError: 'list' object has no attribute 'ndim' happens because plot_surface requires two things from Z:
- It has to be a NumPy array (not a plain Python list)
- Its shape must match the 2D grid shape of
XandY(which are 20x20 aftermeshgrid)
Right now your Z is a 1D list of 20 elements, so we need to adjust it. Here's how:
Step 1: Convert Z to a NumPy array
import numpy as np Z = np.array([7.209, 7.223, 7.229, 7.236, 7.243, 7.27, 7.277, 7.284, 7.292, 7.306, 7.312, 7.329, 7.337, 7.347, 7.354, 8.356, 8.363, 8.374, 8.39, 8.398])
Step 2: Match Z to the 20x20 grid shape
Since X and Y are 20x20 after meshgrid, Z needs to be the same shape. If your original Z values are meant to repeat across rows (or columns), you can use np.tile to expand it:
# Reshape Z to 20x1, then repeat each row 20 times to make 20x20 Z = np.tile(Z.reshape(20, 1), (1, 20))
If your data doesn't fit this pattern (i.e., Z isn't tied to a grid row/column), then plot_surface isn't the right tool—skip to section 2 below.
Z Isn't a Function of X and Y If your data is just a set of 20 independent (x, y, z) points (no structured grid), you have two solid options:
Option A: Use Triangular Surface Plot (plot_trisurf)
This method automatically creates a triangular mesh from your scattered points to generate a surface—perfect for unstructured data:
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D # Your original 1D data Z = np.array([7.209, 7.223, 7.229, 7.236, 7.243, 7.27, 7.277, 7.284, 7.292, 7.306, 7.312, 7.329, 7.337, 7.347, 7.354, 8.356, 8.363, 8.374, 8.39, 8.398]) X = np.random.rand(20) Y = np.random.rand(20) fig = plt.figure() ax = fig.add_subplot(111, projection="3d") # Draw the triangular surface ax.plot_trisurf(X, Y, Z, cmap=plt.cm.coolwarm) plt.show()
Option B: Interpolate to a Structured Grid
If you still want to use plot_surface, you can interpolate your scattered points onto a regular grid first using scipy.interpolate.griddata:
import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from scipy.interpolate import griddata # Original scattered data Z = np.array([7.209, 7.223, 7.229, 7.236, 7.243, 7.27, 7.277, 7.284, 7.292, 7.306, 7.312, 7.329, 7.337, 7.347, 7.354, 8.356, 8.363, 8.374, 8.39, 8.398]) X = np.random.rand(20) Y = np.random.rand(20) # Create a regular grid to interpolate onto xi = np.linspace(X.min(), X.max(), 100) yi = np.linspace(Y.min(), Y.max(), 100) xi, yi = np.meshgrid(xi, yi) # Interpolate Z values (use 'linear', 'cubic', or 'nearest' for different smoothing) zi = griddata((X, Y), Z, (xi, yi), method="cubic") fig = plt.figure() ax = fig.add_subplot(111, projection="3d") ax.plot_surface(xi, yi, zi, rstride=4, cstride=4, cmap=plt.cm.coolwarm) plt.show()
- Use
plot_surfaceonly if you have structured grid data (matchZshape toX/Ygrid) - Use
plot_trisurffor scattered, unstructured points (no interpolation needed) - Use interpolation +
plot_surfaceif you want a smooth, regular surface from scattered data
内容的提问来源于stack exchange,提问作者MVReddy

