geom-violin

Violin layer: mirrored density silhouette of y per x bucket.

Defaults to stat = "ydensity", so the layer accepts raw observations and estimates each bucket’s density internally. The default position = "identity" keeps buckets at their categorical x slot; switch to "dodge" for side-by-side violins per fill level.

Usage

geom-violin(
  mapping: none,
  data: none,
  width: 0.9,
  bw: auto,
  adjust: 1,
  n: 512,
  trim: true,
  scale: "area",
  colour: auto,
  fill: auto,
  stroke: 0.6pt,
  alpha: auto,
  stat: auto,
  position: "identity",
  key: auto,
  inherit-aes: true,
)

Parameters

Parameter Default Description
mapping none Layer-specific aesthetic mapping built with aes. Must map x and y.
data none Layer-specific dataset, or a function applied to the plot data returning the layer frame. Falls back to the plot data when none.
width 0.9 Full violin width in x data units at violinwidth = 1.
bw auto Kernel bandwidth. auto applies Silverman’s rule of thumb; pass a positive number to fix it.
adjust 1 Bandwidth multiplier: adjust: 0.5 halves the smoothing, adjust: 2 doubles it.
n 512 Number of evenly spaced grid points the density is evaluated at per bucket.
trim true Whether to restrict each silhouette to its bucket’s y range instead of letting the tails decay.
scale "area" Width normalisation across buckets: "area" (default), "count", or "width". See stat-ydensity.
colour auto Fixed outline colour. auto resolves via the colour scale, falling back to the theme ink.
fill auto Fixed body fill. auto resolves via the fill scale, falling back to the theme paper.
stroke 0.6pt Outline thickness (a Typst length) or stroke dictionary; none disables the outline.
alpha auto Fill opacity in [0, 1].
stat auto Statistical transform. auto builds stat-ydensity from the parameters above; pass a stat name or stat object to override.
position "identity" Position adjustment name. "identity" (default) or "dodge".
key auto Legend glyph override built with a draw-key-* helper. auto picks the default for the geom.
inherit-aes true Whether to merge the plot-level mapping into this layer’s mapping.

Returns

Layer dictionary consumed by plot.

Examples

Violins of a skewed sample per group.

#let ys = (1, 2, 2, 3, 3, 3, 4, 4, 5, 7)
#let d = ()
#for (i, grp) in ("a", "b", "c").enumerate() {
  for y in ys {
    d.push((grp: grp, y: y + i))
  }
}
#plot(
  data: d,
  mapping: aes(x: "grp", y: "y"),
  layers: (geom-violin(),),
  width: 10cm,
  height: 6cm,
)

Violin chart with groups a, b, c on the x-axis and values on the y-axis; each group shows a mirrored density silhouette, group c shifted upward.

Violin chart with groups a, b, c on the x-axis and values on the y-axis; each group shows a mirrored density silhouette, group c shifted upward.

Map fill and dodge for side-by-side violins per level; keep the tails with trim: false.

#let ys = (1, 2, 2, 3, 3, 3, 4, 4, 5, 7)
#let d = ()
#for grp in ("a", "b") {
  for lvl in ("u", "v") {
    for y in ys {
      d.push((grp: grp, lvl: lvl, y: y + (if lvl == "v" { 2 } else { 0 })))
    }
  }
}
#plot(
  data: d,
  mapping: aes(x: "grp", y: "y", fill: "lvl"),
  layers: (geom-violin(trim: false, position: "dodge", alpha: 0.7),),
  width: 10cm,
  height: 6cm,
)

Violin chart with groups a and b on the x-axis, two dodged fill levels per group, untrimmed tails decaying smoothly beyond the data range.

Violin chart with groups a and b on the x-axis, two dodged fill levels per group, untrimmed tails decaying smoothly beyond the data range.

See also

stat-ydensity, geom-boxplot, geom-density.

Back to top