1

I'm trying to plot some data, which consists of 4 variables. I'm using 2 approaches one is scatter plot and another one is surface. The problem is that when I'm using surface the data is missing. I think it has to do with the color setup.

For the scatter plot, I use this:

def scatter3d(x,y,z, cs, colorsMap='jet'):
   cm = plt.get_cmap(colorsMap)
   cNorm = matplotlib.colors.Normalize(vmin=min(cs), vmax=max(cs))
   scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
   fig = plt.figure()
   ax = Axes3D(fig)
   ax.scatter(x, y, z,c=scalarMap.to_rgba(cs))
   ax.set_xlabel('Thita1')
   ax.set_ylabel('Thita2')
   ax.set_zlabel('Fairness (%)')
   scalarMap.set_array(cs)
   fig.colorbar(scalarMap,label='Error Rate (%)')
   plt.show()

enter image description here

I want to convert it to a surface plot, using this:

   def surfacePlot(x,y,z, cs, colorsMap='jet'):
    cm = plt.get_cmap(colorsMap)
    cNorm = matplotlib.colors.Normalize(vmin=min(cs), vmax=max(cs))
    scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.plot_surface(x, y, z, facecolors=scalarMap.to_rgba(cs))
    ax.set_xlabel('Thita1')
    ax.set_ylabel('Thita2')
    ax.set_zlabel('Fairness')
    scalarMap.set_array(cs)
    fig.colorbar(scalarMap,label='Error Rate (%)')
    plt.show()

However, this results in an empty grid:

enter image description here

Although the axes have received the min and max values from the vectors, the points are missing. What am I doing wrong ?

  • I guess your code may or may not work, depending on what data you put into it. Note that surface plots need 2D arrays as input. – ImportanceOfBeingErnest Dec 11 '18 at 16:53
  • To have a surface plot you need a mesh grid of x and y points and a corresponding z value at each of those (x,y) points – Sheldore Dec 11 '18 at 16:54
  • variables in both cases are vectors of the same length, which means each row is a point in the grid (x,y,z) and cs is the color attribute. If i do it like this: X, Y = np.meshgrid(x, y) Z = np.outer(z.T, z) I get index exceptions. – Βασιλης Ιωσηφιδης Dec 11 '18 at 17:07
  • See e.g. [this question](https://stackoverflow.com/questions/36589521/how-to-surface-plot-3d-plot-from-dataframe). Or [this](https://stackoverflow.com/questions/9170838/surface-plots-in-matplotlib). – ImportanceOfBeingErnest Dec 11 '18 at 18:19
  • I closed as duplicate to prevent other unhelpful answers. Please read through the availabl resources. At the end you need 3 2D arrays of the same shape. To understand the matter, you may create some 16 element arrays and reshape them to 4x4 and plot them. If you need further help, you may ask a new question, but use the toy data in your code when asking for clarification. – ImportanceOfBeingErnest Dec 11 '18 at 20:59

1 Answers1

-1

As mentioned, plot_surface requires 2d array data, or mesh--similar to how you would create a heatmap if you are familiar with that. If your data is regularly spaced across x,y axis (which it seems you do), you can simply use the z data formatted into a 2d array as shown in previous examples linked in the comments:

grid_x, grid_y = np.meshgrid(x, y)

# I'm assuming that your data is already mesh-like, which it looks like it is.
# The data would also need to be appropriately sorted for `reshape` to work.
# `dx` here is number of unique x values, and `dy` is number unique y values.
grid_z = z.reshape(dy, dx)

ax.plot_scatter(grid_x, grid_y, grid_z)

However, in the general case where you have unevenly spaced x,y,z points, you can interpolate your data to create your mesh. Scipy has the function griddata that will interpolate onto a defined meshgrid. You can use this to plot your data:

from scipy.interpolate import griddata
xy = np.column_stack([x, y])
grid_x, grid_y = np.mgrid[0:1:100j, 0:1:100j]  # grid you create
grid_z = griddata(xy, z, (grid_x, grid_y))
ax.plot_scatter(grid_x, grid_y, grid_z)
busybear
  • 10,194
  • 1
  • 25
  • 42