Written and maintained by CASRAI Editorial Board
Last updated
Short answer. To make a 3D plot in Python, install Matplotlib, create axes with projection="3d", and call a 3D method such as scatter, plot_surface or plot_wireframe. Then fix the viewpoint with view_init and save the figure. The examples below follow Matplotlib’s official gallery (documentation version 3.11.2, read 2026-11-08).
What it is used for in research
A 3D plot shows a response over two inputs (a surface z = f(x, y)), three measured variables for each observation (a 3D scatter), or a gridded field such as a potential-energy or error surface. Researchers and graduate students most often need one in a paper figure, so this guide stresses reproducible, fixed viewpoints and file export. If the same figure is being made in another environment, see 3D plots in MATLAB and 3D plots in R.
3D plot Python: what to import
Matplotlib’s 3D support lives in the mpl_toolkits.mplot3d toolkit. Its 3D axes provide, among others, plot, scatter, bar, bar3d, plot_surface, plot_wireframe, plot_trisurf, contour, contourf, quiver and voxels. The official gallery example enables 3D axes with subplot_kw={"projection": "3d"} and does not import Axes3D, so older fig.gca(projection='3d') snippets are not needed.
Install or access (official source only)
From the Matplotlib installation page:
python -m pip install -U matplotlib
conda install -c conda-forge matplotlib
Check the install with python -c "import matplotlib; print(matplotlib.__version__, matplotlib.__file__)". The surface example also uses NumPy.
Step-by-step: a 3D plot with Matplotlib
3D plot Matplotlib, step 1: create 3D axes
- Import the libraries:
import matplotlib.pyplot as pltandimport numpy as np. - Create the figure and 3D axes:
fig, ax = plt.subplots(subplot_kw={"projection": "3d"}).
Step 2: a surface plot (official gallery example)
A surface needs 2D arrays of x, y and z values. np.meshgrid turns two 1D coordinate vectors into those grids (see NumPy meshgrid).
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import LinearLocator
fig, ax = plt.subplots(subplot_kw={"projection": "3d"})
X = 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)
surf = ax.plot_surface(X, Y, Z, cmap="coolwarm", linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter('{x:.02f}')
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
In the official example, antialiased=False makes the surface opaque, and the LinearLocator and formatter lines set ten z ticks printed to two decimals.
Step 3: scatter and wireframe
For three measured variables per observation, pass three equal-length arrays: ax.scatter(x, y, z). For a lighter grid view of the same surface data, replace the surface call with ax.plot_wireframe(X, Y, Z). For scattered (non-gridded) points that you want as a surface, plot_trisurf is the matching method in the toolkit’s method list.
Step 4: fix the viewing angle
Call ax.view_init(elev=..., azim=..., roll=...). The documented signature is Axes3D.view_init(elev=None, azim=None, roll=None, vertical_axis='z', share=False), with angles in degrees, not radians.
| Parameter | Meaning (Matplotlib docs) |
|---|---|
elev |
Angle above the x-y plane when vertical_axis is 'z' |
azim |
Rotation around the vertical axis |
roll |
Rotation around the viewing axis |
vertical_axis |
Which axis points up: 'z' (default), 'x' or 'y' |
Recording the three angles in your analysis script makes the figure reproducible for a manuscript revision.
Step 5: save for a paper
Use fig.savefig("figure.png", dpi=300) (or a .pdf or .svg file name) instead of relying on plt.show(). Check the target journal’s figure requirements for format and resolution.
Output and how to read it
| Method | Use it when |
|---|---|
scatter |
Each observation has three measured values |
plot_surface |
Values lie on a regular x-y grid (from meshgrid) |
plot_wireframe |
You want the surface shape without filled faces |
plot_trisurf |
Points are scattered, not gridded |
contour / contourf |
You want level curves drawn on the 3D axes |
bar3d |
Bars over a two-way categorical or gridded layout |
All six methods appear in the mplot3d toolkit reference; the pairing with data shape is the usual meaning of each method. A colorbar, as in the example, carries the z value into a printed figure, since a single rotated view hides part of a surface. Because a 3D view projects three dimensions onto a flat page, consider whether a 2D heatmap or contour plot reads more accurately for your data; for 2D charts see bar plots in Matplotlib.
Troubleshooting
- Objects appear in front of others from some angles. Matplotlib’s mplot3d FAQ calls this the most commonly reported issue: 3D data is reduced to 2D plus a z-order value, so intersecting objects cannot always be drawn correctly. It says complex 3D scenes are better served by Mayavi. Change the viewing angle with
view_initor use a different library (below). - No window or no rotation. The non-interactive backends (Agg, ps, pdf, svg) work out of the box; TkAgg, an interactive default, needs
tkinter, and on Linux the install page notes you may need thepython3-tkpackage. A non-interactive backend can still save files withsavefig. - Angles look wrong.
view_inittakes degrees, not radians. - Axis layout. The FAQ notes that label spacing, tick length and grid line width were historically hard-coded in mplot3d.
Free alternatives
| Library | What its documentation says | Install (official docs) |
|---|---|---|
| Plotly | Lists 3D scatter, surface, line, trisurf, mesh, isosurface, volume, cone and streamtube chart types, plus 3D camera controls | pip install plotly |
| PyVista | Installable from PyPI or conda-forge; extends to mesh formats and Jupyter rendering via optional packages | pip install pyvista |
| Mayavi | Recommended by the Matplotlib FAQ for advanced 3D scenes | See the Mayavi documentation |
For a Matplotlib-versus-Plotly decision on general charting, see Plotly vs Matplotlib.
FAQ
How do I make a 3D plot in Python?
Install Matplotlib, create axes with plt.subplots(subplot_kw={"projection": "3d"}), and call scatter, plot_surface or plot_wireframe on them.
How do I make a 3D plot in Matplotlib with a fixed viewpoint?
Call ax.view_init(elev, azim, roll) with angles in degrees before saving.
Do I need to import Axes3D?
The official gallery example enables 3D axes with subplot_kw={"projection": "3d"} and imports only pyplot, NumPy and a ticker class.
Which library suits complex 3D scenes?
The Matplotlib FAQ recommends Mayavi for complex 3D scenes; Plotly and PyVista are other free options with their own 3D documentation.







