Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python - Matplotlib 3D input formatting Z (dependent) values

I have a question quite similar to this one Matplotlib 3D plot - 2D format for input data? but it only partly solved my problem (which was originally that .plot_surface() didn't recognize any arguments). What I am trying to do is plot a function of 2 parameters and this is what I have:

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
X,Y = np.meshgrid(positions[0],np.transpose(positions[1]))
Z = data[0]
Axes3D.plot_surface(X, Y, Z)

which throws this error:

TypeError: plot_surface() missing 1 required positional argument: 'Z'

data[0] is a 2D array. (data is a list of 2D arrays). positions is a tuple of a row vector and a column vector, so line 3 is essentially reconstructing positions as two row vectors and then making two matrices one for X and one for Y values as I believe Axes3D.plot_surface() requires.

My problem is that even though Z is 2D array, .plot_surface() refuses to recognize it as such.

Edit: I just confirmed that Z is indeed the correct shape using this:

if Z.shape == X.shape:
    print('Same shape')
    Axes3D.plot_surface(X, Y, Z)

So I have no idea why it will not work. Even when I use X for Z like this (since it didn't complain about X missing or being the wrong shape) it still gets mad.

Axes3D.plot_surface(X, Y, X)

Edit: In looking around examples and trying things out, I finally got it to work. I hardly consider this solved though, because I still have no idea why one way works and another doesn't, and I don't want to leave this unsolved for posterity. I got it to work by doing this

surf = ax.plot_surface(X, Y, Z)

instead of "Axes3D.plotsurface()". I have no idea why this change got it to work, so please still help me figure this out.

like image 751
Liam Clink Avatar asked Mar 02 '26 21:03

Liam Clink


1 Answers

As you said, it seems that the right way to do this is via axis object (ax in the code below):

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z)

Alternatively, you can still call it using Axes3D, but then you need to pass it the axis object ax, like so:

Axes3D.plot_surface(ax, X, Y, Z)
like image 85
S. Sergei Avatar answered Mar 04 '26 10:03

S. Sergei



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!