surface plots in matplotlib surface plots in matplotlib python python

surface plots in matplotlib


For surfaces it's a bit different than a list of 3-tuples, you should pass in a grid for the domain in 2d arrays.

If all you have is a list of 3d points, rather than some function f(x, y) -> z, then you will have a problem because there are multiple ways to triangulate that 3d point cloud into a surface.

Here's a smooth surface example:

import numpy as npfrom mpl_toolkits.mplot3d import Axes3D  # Axes3D import has side effects, it enables using projection='3d' in add_subplotimport matplotlib.pyplot as pltimport randomdef fun(x, y):    return x**2 + yfig = plt.figure()ax = fig.add_subplot(111, projection='3d')x = y = np.arange(-3.0, 3.0, 0.05)X, Y = np.meshgrid(x, y)zs = np.array(fun(np.ravel(X), np.ravel(Y)))Z = zs.reshape(X.shape)ax.plot_surface(X, Y, Z)ax.set_xlabel('X Label')ax.set_ylabel('Y Label')ax.set_zlabel('Z Label')plt.show()

3d


You can read data direct from some file and plot

from mpl_toolkits.mplot3d import Axes3Dimport matplotlib.pyplot as pltfrom matplotlib import cmimport numpy as npfrom sys import argvx,y,z = np.loadtxt('your_file', unpack=True)fig = plt.figure()ax = Axes3D(fig)surf = ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.1)fig.colorbar(surf, shrink=0.5, aspect=5)plt.savefig('teste.pdf')plt.show()

If necessary you can pass vmin and vmax to define the colorbar range, e.g.

surf = ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.1, vmin=0, vmax=2000)

surface

Bonus Section

I was wondering how to do some interactive plots, in this case with artificial data

from __future__ import print_functionfrom ipywidgets import interact, interactive, fixed, interact_manualimport ipywidgets as widgetsfrom IPython.display import Imagefrom mpl_toolkits.mplot3d import Axes3Dimport matplotlib.pyplot as pltimport numpy as npfrom mpl_toolkits import mplot3ddef f(x, y):    return np.sin(np.sqrt(x ** 2 + y ** 2))def plot(i):    fig = plt.figure()    ax = plt.axes(projection='3d')    theta = 2 * np.pi * np.random.random(1000)    r = i * np.random.random(1000)    x = np.ravel(r * np.sin(theta))    y = np.ravel(r * np.cos(theta))    z = f(x, y)    ax.plot_trisurf(x, y, z, cmap='viridis', edgecolor='none')    fig.tight_layout()interactive_plot = interactive(plot, i=(2, 10))interactive_plot


I just came across this same problem. I have evenly spaced data that is in 3 1-D arrays instead of the 2-D arrays that matplotlib's plot_surface wants. My data happened to be in a pandas.DataFrame so here is the matplotlib.plot_surface example with the modifications to plot 3 1-D arrays.

from mpl_toolkits.mplot3d import Axes3Dfrom matplotlib import cmfrom matplotlib.ticker import LinearLocator, FormatStrFormatterimport matplotlib.pyplot as pltimport numpy as npX = np.arange(-5, 5, 0.25)Y = np.arange(-5, 5, 0.25)X, Y = np.meshgrid(X, Y)R = np.sqrt(X**2 + Y**2)Z = np.sin(R)fig = plt.figure()ax = fig.gca(projection='3d')surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,    linewidth=0, antialiased=False)ax.set_zlim(-1.01, 1.01)ax.zaxis.set_major_locator(LinearLocator(10))ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))fig.colorbar(surf, shrink=0.5, aspect=5)plt.title('Original Code')

That is the original example. Adding this next bit on creates the same plot from 3 1-D arrays.

# ~~~~ MODIFICATION TO EXAMPLE BEGINS HERE ~~~~ #import pandas as pdfrom scipy.interpolate import griddata# create 1D-arrays from the 2D-arraysx = X.reshape(1600)y = Y.reshape(1600)z = Z.reshape(1600)xyz = {'x': x, 'y': y, 'z': z}# put the data into a pandas DataFrame (this is what my data looks like)df = pd.DataFrame(xyz, index=range(len(xyz['x']))) # re-create the 2D-arraysx1 = np.linspace(df['x'].min(), df['x'].max(), len(df['x'].unique()))y1 = np.linspace(df['y'].min(), df['y'].max(), len(df['y'].unique()))x2, y2 = np.meshgrid(x1, y1)z2 = griddata((df['x'], df['y']), df['z'], (x2, y2), method='cubic')fig = plt.figure()ax = fig.gca(projection='3d')surf = ax.plot_surface(x2, y2, z2, rstride=1, cstride=1, cmap=cm.coolwarm,    linewidth=0, antialiased=False)ax.set_zlim(-1.01, 1.01)ax.zaxis.set_major_locator(LinearLocator(10))ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))fig.colorbar(surf, shrink=0.5, aspect=5)plt.title('Meshgrid Created from 3 1D Arrays')# ~~~~ MODIFICATION TO EXAMPLE ENDS HERE ~~~~ #plt.show()

Here are the resulting figures:

enter image description hereenter image description here