Violin Plot with Overlaid Swarm Points in ggplot2 (R)

The same plot in 14 other libraries — Python: Altair, Bokeh, lets-plot, Matplotlib, Plotly, plotnine, Pygal, Seaborn; Julia: Makie.jl; JavaScript: Chart.js, D3.js, Apache ECharts, Highcharts, MUI X Charts. Compare all 15 side by side: Violin Plot with Overlaid Swarm Points in Python, R, Julia and JavaScript.

A violin plot with individual data points overlaid as a swarm plot, combining smooth kernel density estimation with raw data visibility. The violin shape shows the distribution density while the swarm points reveal actual observations, enabling viewers to see both the overall distribution pattern and individual data values simultaneously. This hybrid approach provides maximum transparency, showing exactly how many observations exist at each level while maintaining the smooth distribution visualization.

Violin Plot with Overlaid Swarm Points rendered with ggplot2

Renders

R source (ggplot2)

#' anyplot.ai
#' violin-swarm: Violin Plot with Overlaid Swarm Points
#' Library: ggplot2 3.5.1 | R 4.4.1
#' Quality: 88/100 | Created: 2026-05-18

library(ggplot2)
library(dplyr)
library(ragg)

set.seed(42)

# --- Theme tokens -----------------------------------------------------------
THEME       <- Sys.getenv("ANYPLOT_THEME", "light")
PAGE_BG     <- if (THEME == "light") "#FAF8F1" else "#1A1A17"
INK         <- if (THEME == "light") "#1A1A17" else "#F0EFE8"
INK_SOFT    <- if (THEME == "light") "#4A4A44" else "#B8B7B0"
IMPRINT   <- c("#009E73", "#C475FD", "#4467A3", "#BD8233",
                 "#AE3030", "#2ABCCD", "#954477")

# --- Data -------------------------------------------------------------------
df <- tibble::tibble(
  condition = rep(c("Control", "Treatment A", "Treatment B", "Treatment C"),
                  each = 60),
  reaction_time = c(
    rnorm(60, mean = 350, sd = 50),
    rnorm(60, mean = 320, sd = 45),
    rnorm(60, mean = 300, sd = 55),
    rnorm(60, mean = 310, sd = 48)
  )
)

# --- Plot -------------------------------------------------------------------
p <- ggplot(df, aes(x = condition, y = reaction_time)) +
  geom_violin(
    fill = IMPRINT[1],
    alpha = 0.4,
    color = INK_SOFT,
    linewidth = 0.8
  ) +
  geom_jitter(
    color = IMPRINT[1],
    size = 2.5,
    alpha = 0.7,
    width = 0.2,
    height = 0
  ) +
  labs(
    title = "violin-swarm · R · ggplot2 · anyplot.ai",
    x = "Experimental Condition",
    y = "Reaction Time (ms)"
  ) +
  theme_minimal(base_size = 14) +
  theme(
    plot.background  = element_rect(fill = PAGE_BG, color = PAGE_BG),
    panel.background = element_rect(fill = PAGE_BG, color = NA),
    panel.grid.major.x = element_blank(),
    panel.grid.major.y = element_line(color = INK, linewidth = 0.3),
    panel.grid.minor = element_blank(),
    axis.title       = element_text(color = INK, size = 20),
    axis.text        = element_text(color = INK_SOFT, size = 16),
    plot.title       = element_text(color = INK, size = 24)
  )

# --- Save -------------------------------------------------------------------
ggsave(
  filename = sprintf("plot-%s.png", THEME),
  plot     = p,
  device   = ragg::agg_png,
  width    = 16,
  height   = 9,
  units    = "in",
  dpi      = 300
)

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/violin-swarm/ggplot2/code. Any spec id and library id listed in llms-full.txt fit the same URL shape; every URL below is complete and callable.

{
  "spec_id": "violin-swarm",
  "language": "r",
  "library": "ggplot2",
  "page": "https://anyplot.ai/violin-swarm/r/ggplot2",
  "hub": "https://anyplot.ai/violin-swarm",
  "code_json": "https://api.anyplot.ai/specs/violin-swarm/ggplot2/code",
  "spec_json": "https://api.anyplot.ai/specs/violin-swarm",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/violin-swarm/r/ggplot2/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/violin-swarm/r/ggplot2/plot-dark.png",
  "quality_score": 88.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Violin Plot with Overlaid Swarm Points on anyplot.ai.

Other implementations