Scatter Plots in Python
When to Use
A scatter plot (also called a scatter chart or scatter graph) accepts NumPy arrays directly and preserves interactive navigation. Use one for relationships, clusters, outliers, and multichannel point data.
Live Demo
Selections in a live widget resolve canonical source rows even when the visible overview is aggregated. Point hover becomes available when the view refines to direct points; the density surface itself does not pretend that a pixel is one source row.
Styled Color Encoding
Map a value array to color with a fixed color_domain, pick a non-default
symbol, and add a crisp border with stroke and stroke_width.
Bubble Chart with Multiple Series
Encode a third variable as marker area with size plus size_range, give each
cluster its own named series and symbol, and let xy.legend() label them.
Scatter
Use scatter for individual observations positioned by two variables. Optional
size, color, symbol, opacity, and stroke channels can reveal additional groups
or measures without changing the x/y relationship.
Variants
color and size accept constants, arrays, or named columns. Numeric color
uses colormap and optional color_domain; categorical color creates a stable
palette. size_range maps numeric size values into pixel diameters.
Markers support 17 renderer-backed symbols, from circle, square, and
directional triangles through star, hexagon, pixel/point, and line-only
glyphs, plus stroke and stroke_width for crisp borders. The complete list
is in Customize Each Part.
Expected Data Shape
Pass equal-length one-dimensional x and y values, or resolve both from a
mapping, DataFrame, or Arrow-compatible table through data=. Optional color
and size channels may be constants, matching arrays, or column names.
Key Options
Use symbol, size, size_range, color, colormap, color_domain,
opacity, stroke, and stroke_width. Set density only when you need to
override automatic tier selection.
Density Mode
Large point collections automatically switch to a bounded density surface when
individual markers become sub-pixel. Set density=True to force aggregation,
False to keep points, or leave it as None for automatic selection. Zooming
can refine the visible window back toward exact points.
API Reference
xy.scatter_chart
A scatter chart composing `scatter` marks and axis/legend children.
Props
| Prop | Type | Description |
|---|---|---|
*children | Component | Marks, axes, annotations, and chart chrome. |
title | Optional[str] | Title shown above the plot. |
width | int | str | Chart width in pixels or a CSS size such as ``"100%"``. |
height | int | str | Chart height in pixels or a CSS size such as ``"100%"``. |
padding | Union[float, Sequence[float], None] | Plot margins, as one value or a sequence of side values. Use zero for an edge-to-edge sparkline. |
data | TableLike | Chart-level data used by marks that omit their own ``data``. |
class_name | Optional[str] | CSS class applied to the chart container. |
class_names | Optional[dict[str, str]] | CSS classes keyed by stable chart DOM slot. |
style | Optional[dict[str, StyleValue]] | Inline style overrides for the chart container. |
styles | Optional[dict[str, dict[str, StyleValue]]] | Inline style mappings keyed by stable chart DOM slot. |
on_hover | Optional[Callable[[dict], None]] | Callback receiving hover event payloads. |
on_click | Optional[Callable[[dict], None]] | Callback receiving picked-mark click payloads. |
on_brush | Optional[Callable[[dict], None]] | Callback receiving brush event payloads. |
on_select | Optional[Callable[[Selection], None]] | Callback receiving data-space selections. |
on_view_change | Optional[Callable[[dict], None]] | Callback receiving viewport change payloads. |
hover | Optional[bool] | Whether pointer movement emits hover events. |
click | Optional[bool] | Whether picked marks emit click events. |
select | Optional[bool] | Whether shift-drag box selection is enabled. |
brush | Optional[bool] | Whether brush selection is enabled. |
crosshair | Optional[bool] | Whether plot-aligned hover guides are shown. |
navigation | Optional[bool] | Whether browser pan and zoom navigation is enabled. |
pan | Optional[bool] | Whether plain-drag panning is enabled. |
pan_axes | Optional[tuple[str, ...]] | Declared axis IDs translated by pan gestures. |
zoom | Optional[bool] | Whether viewport zoom is enabled. |
default_drag_action | Optional[DefaultDragAction] | Initial action performed by a plain plot drag. |
zoom_axes | Optional[tuple[str, ...]] | Declared axis IDs changed by zoom gestures and controls. |
zoom_limits | Optional[ZoomLimits] | Minimum and maximum magnification globally or by axis. |
wheel_zoom | Optional[bool] | Whether wheel and trackpad zoom is available. |
box_zoom | Optional[bool] | Whether box zoom is available as a drag action. |
zoom_buttons | Optional[bool] | Whether modebar Zoom In/Out commands are available. |
double_click_reset | Optional[bool] | Whether double-click restores ``reset_axes``. |
reset_axes | Optional[tuple[str, ...]] | Declared axis IDs restored by reset. |
link_group | Optional[str] | Identifier used to synchronize charts in the browser. |
link_axes | Optional[tuple[str, ...]] | Axes synchronized within the link group. |
FAQ
How do I make a scatter plot in Python?
Call xy.scatter(x, y) inside xy.scatter_chart(...) and render it. Pan, zoom,
and hover work automatically — no extra configuration required.
How many points can an xy scatter plot handle?
Millions. When individual markers become sub-pixel, xy automatically switches
to a bounded density surface and refines back toward exact points as you zoom.
How do I color scatter points by a value?
Pass an array (or column name) to color and choose a colormap; use
color_domain to fix the value range. Categorical values create a stable
palette instead.
How do I make a bubble chart in Python?
Pass a value array to size along with size_range to map it to pixel
diameters — a bubble chart is a scatter plot with a third variable encoded as
point size.