Violin Plots

Three violin shapes comparing car acceleration distributions by origin
Category-centered kernel-density profiles with shared width resolution.

Use createViolinPlot to compare kernel-density profiles inside categorical bands. It accepts the same categorical/quantitative x/y role family as box and gradient plots, then infers orientation from the complete field pair.

Minimal vertical violin

const program = chart()
  .createCanvas()
  .createData({ values })
  .createViolinPlot({
    x: "category",
    y: "value"
  });

The action creates an area mark, immutable density data, category and value scales, full closed paths, and applicable Cartesian guides. Field types are inferred when the current dataset makes one categorical and one quantitative role unambiguous.

Density width and orientation

.createViolinPlot({
  x: { field: "value", fieldType: "quantitative" },
  y: { field: "category", fieldType: "nominal" },
  density: {
    bandwidth: 0.8,
    extent: [0, 30],
    steps: 80,
    width: { band: 0.7, resolve: "independent" }
  }
})

width.band is the fraction of each categorical band available to the full shape. resolve: "shared" uses one density maximum across categories; "independent" gives each category its own maximum. The default is { band: 0.8, resolve: "shared" }.

Split a category into two halves

.createViolinPlot({
  x: "category",
  y: "value",
  split: {
    field: "period",
    domain: ["early", "late"]
  },
  color: {
    field: "period",
    scale: { range: ["#4c78a8", "#e45756"] }
  }
})

A split must contain exactly two observed values. The first domain value owns the left or top half and the second owns the right or bottom half. When the domain is omitted, ggaction uses first-appearance order only if exactly two values are observed.

Appearance and guides

.createViolinPlot({
  x: "category",
  y: "value",
  color: "category",
  area: { opacity: 0.7, strokeWidth: 1.5 },
  guides: { legend: false }
})

When strokeWidth is supplied without a constant stroke, each outline follows its materialized fill. A category-color legend is omitted by default because the categorical axis already identifies the same field; request guides: { legend: {} } to show it explicitly.

Editing

createViolinPlot is an aggregate create action. Edit the resource owned by the decision you want to change:

const revised = program
  .editDensity({
    bandwidth: 1.1,
    placement: {
      type: "category",
      width: { band: 0.6, resolve: "shared" }
    }
  })
  .editAreaMark({ opacity: 0.55 });

Use { type: "baseline" } as the placement edit to return the area to the ordinary zero-baseline density layout. Canvas, scale, data, filtering, selection, highlighting, and facet changes rematerialize the complete density paths.

Current boundary

Violin recipe · Density encoding · Area marks · Box plots