Plotly Python
Build and verify a figure tree. A Plotly figure has data traces, layout, and
optional frames; it is serialized to Plotly.js for rendering. Keep application
state and event transport in the host that actually supports them.
Boundary
Use this skill when a project imports Plotly or explicitly requests a Plotly
figure. Do not route Dash callback graphs, Streamlit rerun/state design, Altair
Vega-Lite specs, or Matplotlib-only output here. A figure can contain controls,
but a standalone Figure is not a full server application.
Know the objects
| Object |
Meaning |
Responsibility |
go.Figure |
Validated JSON-like figure tree |
Own traces, layout, frames, and figure methods. |
| Trace |
Typed series/mark set in figure.data |
Own x/y/z/locations, name, legend group, hover/custom data, marker/line, subplot refs. |
| Layout |
Figure-wide non-data presentation |
Own title, axes, legend, color axes, annotations, shapes, margins, templates, subplots. |
| Frame |
Named animation state |
Own per-frame trace/layout changes and stable identity. |
| Plotly Express |
High-level constructor returning go.Figure |
Build common figures from tidy/wide data, color, facet, animation, hover. |
| FigureWidget |
Widget-backed figure in an ipywidgets host |
Enable Python callbacks on trace events in a displayed widget context. |
| Renderer/export |
Host-specific materialization |
Notebook/browser HTML, JSON, or image through optional engine. |
Read the figure and trace model before mixing
Express with graph objects, editing facets/subplots, or debugging a schema path.
Ordered workflow
- State the analytical question, input and displayed grain, trace grouping,
order, units, missing values, target host, and required interaction/export.
- Start with Plotly Express for one standard figure described by dataframe
columns. Use graph objects when trace-by-trace construction, specialized
types, secondary axes, exact subplot assignment, or incremental mutation is
essential.
- Inspect the produced figure tree. Identify which fields create traces and
which attributes belong to a trace, axis/subplot, color axis, or whole layout.
- Add only contract-required layout, hover/customdata, ordering, facets,
annotations, and controls. Do not replace data semantics with visual defaults.
- For facets/subplots, define category/panel order, shared axes, matches,
legend duplication, annotation labels, and trace targeting.
- Choose the actual event host. Use
FigureWidget callbacks only in a live
ipywidgets context; use the application's callback/rerun API elsewhere.
- Validate the JSON-compatible figure, test trace/layout semantics, then render
or export in the real environment.
Intent to API family
| Need |
Start with |
Switch/extend when |
| Common chart from dataframe columns |
plotly.express |
Customize returned Figure with update/add methods. |
| Exact trace composition |
go.Figure + typed traces |
Trace identity, order, subplot refs, or unsupported Express shape matters. |
| Small multiples |
Express facet_row/facet_col |
Use subplots for heterogeneous trace types or layouts. |
| Multiple panels |
make_subplots + add_trace(row=..., col=...) |
Secondary axes/specs/rowspan/colspan require explicit grid. |
| Same styling across traces |
selector-based update_traces |
Target by trace type/name/legend group, not fragile index alone. |
| Axes/layout |
update_xaxes, update_yaxes, update_layout |
Know whether a change is per-subplot or global. |
| Per-point hover payload |
hover_data/hovertemplate + customdata |
Keep stable record IDs in customdata for host events. |
| Animation |
Express animation or frames |
Frame/category order and trace identity are explicit. |
| Python click callback |
FigureWidget |
Only when displayed in supported ipywidgets context. |
| Web app events |
Host framework callback/selection API |
A plain figure callback will not execute on static HTML. |
Canonical anchor
import plotly.express as px
def sales_figure(data):
fig = px.line(
data,
x="date",
y="revenue",
color="region",
markers=True,
category_orders={"region": ["North", "South", "West"]},
custom_data=["record_id"],
labels={"date": "Date", "revenue": "Revenue", "region": "Region"},
)
fig.update_layout(title="Revenue by region", hovermode="x unified")
return fig
Express creates one or more traces based on discrete mappings/facets/animation.
Do not assume fig.data[0] represents all categories; inspect and target traces
semantically.
Trace, layout, and facet invariants
- Put data arrays and per-series styling on traces; put figure/subplot guides,
annotations, and template on layout.
- Keep x/y arrays aligned and define missing-value/line-gap behavior.
- Give traces stable
name, legendgroup, and record identity where host
events or updates depend on them.
- Set category order explicitly when business order differs from encounter or
lexical order. Facet order and legend/color order can share that contract.
- With facets, decide axis matching and remove duplicated annotations/legends
only through targeted figure operations.
- Avoid dual axes unless units and mapping are unmistakable; use small multiples
when direct comparison would mislead.
Read composition and events.
Verification and export
Use fig.to_dict()/to_json() to inspect semantic nodes. Test trace count/type,
x/y/customdata alignment, names/order, subplot refs, axis titles/types/ranges,
color scale/legend, frames, and absence of sensitive data. Do not snapshot the
entire default template. Read export and testing.
Inspect the installed version of Plotly and the target host before using a
drift-sensitive trace property, event API, renderer, or image engine. Plotly was
absent from this foundry during authoring, so source/static checks do not prove
rendering.
Completion requires a valid figure tree; correct trace and displayed grain;
explicit order/units/missing policy; no fragile trace-index mutation; truthful
event-host behavior; semantic tests; and a real-host HTML/image/widget render
when appearance or interaction is contractual.
References
- Figure, trace, and layout model
- Composition, facets, and events
- Export and semantic testing
1---2name: plotly-python3description: Build, verify, and debug interactive Python visualizations with Plotly, including Plotly Express, graph_objects, subplots, facets, hover/customdata, axes, legends, FigureWidget events, and HTML/image export.4---56# Plotly Python78Build and verify a figure tree. A Plotly figure has `data` traces, `layout`, and9optional `frames`; it is serialized to Plotly.js for rendering. Keep application10state and event transport in the host that actually supports them.1112## Boundary1314Use this skill when a project imports Plotly or explicitly requests a Plotly15figure. Do not route Dash callback graphs, Streamlit rerun/state design, Altair16Vega-Lite specs, or Matplotlib-only output here. A figure can contain controls,17but a standalone `Figure` is not a full server application.1819## Know the objects2021| Object | Meaning | Responsibility |22|---|---|---|23| `go.Figure` | Validated JSON-like figure tree | Own traces, layout, frames, and figure methods. |24| Trace | Typed series/mark set in `figure.data` | Own x/y/z/locations, name, legend group, hover/custom data, marker/line, subplot refs. |25| Layout | Figure-wide non-data presentation | Own title, axes, legend, color axes, annotations, shapes, margins, templates, subplots. |26| Frame | Named animation state | Own per-frame trace/layout changes and stable identity. |27| Plotly Express | High-level constructor returning `go.Figure` | Build common figures from tidy/wide data, color, facet, animation, hover. |28| FigureWidget | Widget-backed figure in an ipywidgets host | Enable Python callbacks on trace events in a displayed widget context. |29| Renderer/export | Host-specific materialization | Notebook/browser HTML, JSON, or image through optional engine. |3031Read [the figure and trace model](references/figure-model.md) before mixing32Express with graph objects, editing facets/subplots, or debugging a schema path.3334## Ordered workflow35361. State the analytical question, input and displayed grain, trace grouping,37 order, units, missing values, target host, and required interaction/export.382. Start with Plotly Express for one standard figure described by dataframe39 columns. Use graph objects when trace-by-trace construction, specialized40 types, secondary axes, exact subplot assignment, or incremental mutation is41 essential.423. Inspect the produced figure tree. Identify which fields create traces and43 which attributes belong to a trace, axis/subplot, color axis, or whole layout.444. Add only contract-required layout, hover/customdata, ordering, facets,45 annotations, and controls. Do not replace data semantics with visual defaults.465. For facets/subplots, define category/panel order, shared axes, matches,47 legend duplication, annotation labels, and trace targeting.486. Choose the actual event host. Use `FigureWidget` callbacks only in a live49 ipywidgets context; use the application's callback/rerun API elsewhere.507. Validate the JSON-compatible figure, test trace/layout semantics, then render51 or export in the real environment.5253## Intent to API family5455| Need | Start with | Switch/extend when |56|---|---|---|57| Common chart from dataframe columns | `plotly.express` | Customize returned `Figure` with update/add methods. |58| Exact trace composition | `go.Figure` + typed traces | Trace identity, order, subplot refs, or unsupported Express shape matters. |59| Small multiples | Express `facet_row`/`facet_col` | Use subplots for heterogeneous trace types or layouts. |60| Multiple panels | `make_subplots` + `add_trace(row=..., col=...)` | Secondary axes/specs/rowspan/colspan require explicit grid. |61| Same styling across traces | selector-based `update_traces` | Target by trace type/name/legend group, not fragile index alone. |62| Axes/layout | `update_xaxes`, `update_yaxes`, `update_layout` | Know whether a change is per-subplot or global. |63| Per-point hover payload | `hover_data`/`hovertemplate` + `customdata` | Keep stable record IDs in customdata for host events. |64| Animation | Express animation or `frames` | Frame/category order and trace identity are explicit. |65| Python click callback | `FigureWidget` | Only when displayed in supported ipywidgets context. |66| Web app events | Host framework callback/selection API | A plain figure callback will not execute on static HTML. |6768## Canonical anchor6970```python71import plotly.express as px727374def sales_figure(data):75 fig = px.line(76 data,77 x="date",78 y="revenue",79 color="region",80 markers=True,81 category_orders={"region": ["North", "South", "West"]},82 custom_data=["record_id"],83 labels={"date": "Date", "revenue": "Revenue", "region": "Region"},84 )85 fig.update_layout(title="Revenue by region", hovermode="x unified")86 return fig87```8889Express creates one or more traces based on discrete mappings/facets/animation.90Do not assume `fig.data[0]` represents all categories; inspect and target traces91semantically.9293## Trace, layout, and facet invariants9495- Put data arrays and per-series styling on traces; put figure/subplot guides,96 annotations, and template on layout.97- Keep x/y arrays aligned and define missing-value/line-gap behavior.98- Give traces stable `name`, `legendgroup`, and record identity where host99 events or updates depend on them.100- Set category order explicitly when business order differs from encounter or101 lexical order. Facet order and legend/color order can share that contract.102- With facets, decide axis matching and remove duplicated annotations/legends103 only through targeted figure operations.104- Avoid dual axes unless units and mapping are unmistakable; use small multiples105 when direct comparison would mislead.106107Read [composition and events](references/composition-events.md).108109## Verification and export110111Use `fig.to_dict()`/`to_json()` to inspect semantic nodes. Test trace count/type,112x/y/customdata alignment, names/order, subplot refs, axis titles/types/ranges,113color scale/legend, frames, and absence of sensitive data. Do not snapshot the114entire default template. Read [export and testing](references/export-testing.md).115116Inspect the installed version of Plotly and the target host before using a117drift-sensitive trace property, event API, renderer, or image engine. Plotly was118absent from this foundry during authoring, so source/static checks do not prove119rendering.120121Completion requires a valid figure tree; correct trace and displayed grain;122explicit order/units/missing policy; no fragile trace-index mutation; truthful123event-host behavior; semantic tests; and a real-host HTML/image/widget render124when appearance or interaction is contractual.125126## References127128- [Figure, trace, and layout model](references/figure-model.md)129- [Composition, facets, and events](references/composition-events.md)130- [Export and semantic testing](references/export-testing.md)