A 3-D scatter plot in Plotly is an interactive chart that displays the relationship among three numerical variables in three-dimensional Cartesian space.
How to Build a 3-D Scatter Plot in Plotly
A 3-D scatter plot lets you visualise relationships among three numerical variables in a single, interactive view. Plotly’s Python API makes the process concise while delivering publication-quality graphics.
A 3-D scatter plot is an extension of its 2-D counterpart: instead of mapping points onto an (x, y) plane, each point occupies a location in (x, y, z) space. Plotly, the popular open-source charting library, renders the plot using WebGL, resulting in smooth, interactive rotation, zooming, and hovering out of the box.
Many real-world datasets involve three or more quantitative variables—think spatial coordinates (latitude, longitude, altitude), experiment metrics (pressure, temperature, time), or customer behaviour indicators (recency, frequency, monetary value). A 3-D scatter plot offers:
pip install plotly
)pandas
or numpy
for data wranglingimport plotly.graph_objects as go
fig = go.Figure(data=[
go.Scatter3d(
x=x_vals,
y=y_vals,
z=z_vals,
mode='markers',
marker=dict(size=5, color=z_vals, colorscale='Viridis')
)
])
fig.update_layout(scene=dict(xaxis_title='X', yaxis_title='Y', zaxis_title='Z'))
fig.show()
import pandas as pd
import plotly.express as px
df = px.data.iris() # 150 flower measurements
plotly.express.scatter_3d
fig = px.scatter_3d(
df,
x="sepal_length",
y="sepal_width",
z="petal_length",
color="species",
symbol="species",
size_max=10,
title="Iris Measurements in 3-D"
)
fig.show()
fig.update_traces(marker=dict(opacity=0.8, line=dict(width=0.5, color='DarkSlateGrey')))
fig.update_layout(margin=dict(l=0, r=0, b=0, t=40))
fig.write_html('iris_scatter3d.html')
for a self-contained file.fig.to_json()
to embed in web apps.fig = px.scatter_3d(df, x='sepal_length', y='sepal_width', z='petal_length',
color='species', size='petal_width', size_max=18)
fig = px.scatter_3d(time_df, x='x', y='y', z='z', animation_frame='timestamp')
fig = go.Figure()
fig.add_trace(go.Surface(z=surface_z, x=surface_x, y=surface_y, showscale=False, opacity=0.4))
fig.add_trace(go.Scatter3d(x=df.x, y=df.y, z=df.z, mode='markers'))
px.scatter_3d
for fast prototyping; switch to go.Scatter3d
for granular control.fig.update_scenes(xaxis_showspikes=False
) if performance is critical.aspectmode='cube'
.Viridis
, Plasma
.Symptom: sluggish rotation, browser crashes. Fix: sample the dataset or encode density via alpha blending.
aspectmode
Symptom: stretched or flattened geometry. Fix: fig.update_layout(scene_aspectmode='cube')
.
Symptom: colours convey no meaning. Fix: map colour to a variable or categorical label, not to row index.
Check:
If the third variable adds little explanatory power or if your audience needs quick quantitative comparisons, a 2-D plot with faceting or colour encoding may communicate more effectively.
import plotly.express as px
df = px.data.iris()
fig = px.scatter_3d(
df,
x="sepal_length",
y="sepal_width",
z="petal_length",
color="species",
symbol="species",
size="petal_width",
size_max=12,
title="Iris Dataset 3-D Scatter Plot"
)
fig.update_traces(marker=dict(opacity=0.85))
fig.update_layout(scene_aspectmode='cube',
margin=dict(l=10, r=10, b=10, t=40))
fig.show()
kaleido
.Visualising three variables simultaneously uncovers multidimensional patterns—clusters, correlations, and anomalies—that remain invisible in flat 2-D charts. Plotly automates interactivity, letting analysts rotate, zoom, and drill into data points for deeper insight without extra code. Mastering 3-D scatter plots expands your exploratory-data-analysis toolbox and elevates dashboards with engaging visuals.
Plotly’s WebGL renderer comfortably displays thousands of points. For larger datasets, consider downsampling, density plotting, or server-side image rendering.
Use fig.update_layout(scene_camera=dict(eye=dict(x=1.2, y=1.2, z=0.6)))
to set the initial viewpoint.
Yes. Install kaleido
(pip install -U kaleido
) and call fig.write_image('plot.png')
.
Use Plotly Express for rapid prototyping and defaults; switch to go.Scatter3d
when you need advanced control like multiple traces or mixed plot types.