Skip to main content
geom.bar() draws a rectangle per observation. In the default cartesian plane the rectangles are vertical columns; add coord.flip() to turn them into horizontal bars. Columns suit comparing categories, or a value over discrete time periods. Bars suit rankings, and categories with labels too long to fit under a vertical axis.

Basic example

Value on y, category on x. The default cartesian plane draws vertical columns:

Stacked and grouped

Map a group column to color, then choose how the bars in each band are arranged with position. The data is long: one row per quarter × region:
  • 'stack' — segments stacked into one column
  • 'dodge' — segments side by side within the band
  • 'fill' — stacked and normalized to 100%
A bar layer defaults to 'dodge', so a multi-group bar chart with no position renders grouped. See position modes for the full list.

Negative values

'identity' draws each bar at its raw value, so a negative y hangs below the zero baseline instead of joining a stack:

Counting rows

Map only x and set the count stat. Each bar’s height is the number of rows in its category, with no value column needed:

Horizontal bars

Keep the mapping as it is, category on x and value on y, and add coord.flip() to swap the axes. Stacking, grouping and styling carry over unchanged:

Ranking

To order bars by value, sort the data with a transform. This is most useful with horizontal bars:

Bar geometry

geom.bar() takes one param, width. It is geometry, not paint:
number
default:"0.7"
Bar width as a fraction of its band, in (0, 1]. Under coord.polar() it defaults to 1, so wedges touch.
A value outside (0, 1] draws with a substitute width and reports an INVALID_GEOM_PARAM warning.

Painting the bars

Fill, opacity, corner rounding and the border come from the stylesheet, through the style.geom.bar target:
style.geom.bar declares fill, alpha, saturation, cornerRadius, stroke, strokeWidth and maxWidth.

Corner rounding

cornerRadius is a named token, not a pixel value, so each coordinate system renders it its own way: a rectangle corner in cartesian, an arc corner in polar:
A stacked column rounds only the outer corners of the whole column, so the segments inside it stay flush against each other.

Capping the width

maxWidth caps a bar’s thickness in pixels without moving its center. It applies to vertical and flipped cartesian bars; polar bars ignore it. Without a cap, the bar keeps the width set by geom.bar({ width }). A stack narrows to the smallest cap among its segments, so its edges stay aligned. Data labels and annotations place against the narrowed bar.

Borders

A bar draws a 1px translucent border by default, from the geomBorder token. A border in the chart’s background color is the usual way to separate stacked segments or pie wedges. strokeWidth: 0 removes the border:
Scope an entry with { layer } to paint one bar layer of a combo differently, or with { where } to paint by value, such as negative bars in a warning color.