12

I've got 3 arrays as shown below and I'm trying to plot a 3d surface plot (wireframe or any other) from it. I've created a scatter plot from it but not sure how to approach it from a 3D surface plot point of view. Any help would be greatly appreciated.

X = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]

Y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Z =[21384, 29976, 15216, 4584, 10236, 7546, 6564, 2844, 4926, 7722, 4980, 2462, 12768, 9666, 2948, 6548, 10776, 8260, 8674, 5584, 5382, 10542, 12544, 5268, 25888, 31220, 9064, 7536, 6618, 1928, 9030, 5790, 6076, 8290, 8692, 4006, 14722, 11016, 2818, 9458, 3054, 5976, 1102, 1084, 9700, 8904, 12510, 11176, 10712, 6548, 2600, 5070, 6538, 4514, 1036, 292, 12572, 6534, 4478, 18500, 10452, 1912, 14254, 31050, 3880, 744, 990, 5534, 1670, 446, 2778, 8272, 14726, 27094, 872, 418, 884, 476, 2806, 1246, 1140, 922, 6202, 10848, 28828, 2360, 9660, 1412, 4296, 5272, 2854, 4150, 770, 5628, 4676, 3500, 31220, 10480, 5704, 5550, 1528, 3168, 2092, 2056, 1874, 7312, 938, 7428]

Code for Scatter plot

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt

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

ax.scatter(x, y, z, c='y', marker='o')

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

plt.show()

Image from Scatter plot enter image description here

I tried to use the code below to create a 3D surface plot but

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

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

ax.plot_wireframe(x,y,z, rstride=2, cstride=2)

plt.show()

but unfortunately I get an error.

Abid Abdul Gafoor
  • 462
  • 1
  • 6
  • 18

2 Answers2

21

As you have a regular grid, you can just use numpy to reshape your data, then use ax.plot_surface. In your example case, you want to reshape to a shape of (9, 12):

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

X = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]

Y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Z = [21384, 29976, 15216, 4584, 10236, 7546, 6564, 2844, 4926, 7722, 4980, 2462, 12768, 9666, 2948, 6548, 10776, 8260, 8674, 5584, 5382, 10542, 12544, 5268, 25888, 31220, 9064, 7536, 6618, 1928, 9030, 5790, 6076, 8290, 8692, 4006, 14722, 11016, 2818, 9458, 3054, 5976, 1102, 1084, 9700, 8904, 12510, 11176, 10712, 6548, 2600, 5070, 6538, 4514, 1036, 292, 12572, 6534, 4478, 18500, 10452, 1912, 14254, 31050, 3880, 744, 990, 5534, 1670, 446, 2778, 8272, 14726, 27094, 872, 418, 884, 476, 2806, 1246, 1140, 922, 6202, 10848, 28828, 2360, 9660, 1412, 4296, 5272, 2854, 4150, 770, 5628, 4676, 3500, 31220, 10480, 5704, 5550, 1528, 3168, 2092, 2056, 1874, 7312, 938, 7428]

x = np.reshape(X, (9, 12))
y = np.reshape(Y, (9, 12))
z = np.reshape(Z, (9, 12))


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

ax.plot_surface(x, y, z)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

plt.show()

enter image description here

tmdavison
  • 64,360
  • 12
  • 187
  • 165
  • 3
    Thank you so much! What does (9,12) represent? and what happens if I have an array with more values than for X, Y, Z? – Abid Abdul Gafoor Jul 03 '18 at 12:32
  • 3
    in your example, you have 9 points in the x direction and 12 in the y direction. If you have a larger grid, you need to change that shape accordingly – tmdavison Jul 03 '18 at 13:21
  • I don't understand why x and y should be reshaped! Could you please send me some mathematical explanation? – giammi56 Sep 24 '20 at 07:33
  • 3
    @Giammi `plot_surface` expects 2D arrays for the x, y and z coordinates. In the example here, they are 1D lists. Because of the format of those 1D arrays (repeating X and Y values at regular intervals), we can just reshape them to get those 2D arrays – tmdavison Sep 24 '20 at 08:40
  • @tmdavison that's absolutely clear. I am wondering why the function cannot handle 1D arrays, since we are just reshaping it! Thank you for your asnwer – giammi56 Sep 25 '20 at 10:16
0

It looks like you need to reshape your data:

ax.plot_wireframe(x.reshape(12,12).T, y.reshape(12,12).T, z.reshape(12,12).T)
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712