Bar Charts in Python
A bar chart (also called a bar graph) compares values across categories using horizontal bars, one bar
per category, with length encoding the measured value. With xy you build a
Python bar chart that is interactive by default — pan, zoom, and hover all work
without configuration — and horizontal bars keep long category labels readable
where a vertical layout would crowd them. Layer several series to make grouped
or stacked bar charts from the same simple API. The vertical form of the same
mark is a column chart — see Column Charts
below.
Jump to grouped and stacked bars, column charts, or options.
Create a Bar Chart
Pass a list of categories and a matching array of values to bar, and set
orientation="horizontal" so the bars run left to right. This is the minimal
Python bar chart:
Grouped and Stacked Bars
Add one named bar mark per series and include a legend() to compare
categories across groups. Set base to stack each series on top of the
previous one — pass the cumulative totals so bars sit flush — or leave base
off to place bars side by side.
Column Charts (Vertical Bars)
A column chart is the same mark drawn vertically: use column (or bar
with orientation="vertical", the default) when categories are ordered — such
as quarters or months — so the left-to-right reading follows time. Columns
stack the same way bars do, with base set to the running total below each
series.
Stack several column marks the same way as bars — pass a pair to
corner_radius, such as corner_radius=(5, 0), to round only the exposed top:
Interactive Bar Charts
Every bar chart is interactive out of the box — drag to pan, scroll or pinch to zoom, and hover to read exact values in a tooltip. The same chart renders in a notebook, a Reflex app, or exported HTML with no extra configuration.
Bar Chart Options
Pass column names with data= instead of arrays when your data is a table.
Note bar and column share the same implementation — use bar for
horizontal category comparison and column for vertical.
Related Charts
- Histograms — for the distribution of a single continuous variable rather than named categories.
- Line charts — for a continuous trend over time rather than discrete category comparison.
API Reference
xy.bar_chart
A bar chart composing `bar` 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. |
xy.column_chart
A column chart composing `column` 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 horizontal bar chart in Python?
Call xy.bar(categories, values, orientation="horizontal") inside
xy.bar_chart(...) and render it. The resulting bar plot pans, zooms, and
hovers automatically.
What is the difference between a bar chart and a column chart in xy?
They share one implementation. A bar chart uses orientation="horizontal" so
bars run left to right; a column chart runs vertical. Pick the name that reads
best in your app.
How do I stack bars in a Python bar chart?
Add one named bar mark per series and set base on each stacked series to the
running total of the series below it, then add xy.legend().
How do I sort bars by value?
Order your category and value arrays before passing them to bar; the chart
draws categories in the order you supply.