Basic Density Plot — ggplot2

A density plot (also known as Kernel Density Estimation or KDE plot) visualizes the distribution of a continuous variable by smoothing the data into a continuous probability density curve. Unlike histograms which use discrete bins, density plots provide a smooth representation of the underlying distribution, making it easier to identify patterns such as skewness, modality, and overall shape.

Basic Density Plot rendered with ggplot2

Renders

R source (ggplot2)

#' anyplot.ai
#' density-basic: Basic Density Plot
#' Library: ggplot2 3.5.1 | R 4.4.1
#' Quality: 88/100 | Created: 2026-05-30

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

set.seed(42)

# Theme tokens — Imprint palette, theme-adaptive chrome
THEME       <- Sys.getenv("ANYPLOT_THEME", "light")
PAGE_BG     <- if (THEME == "light") "#FAF8F1" else "#1A1A17"
ELEVATED_BG <- if (THEME == "light") "#FFFDF6" else "#242420"
INK         <- if (THEME == "light") "#1A1A17" else "#F0EFE8"
INK_SOFT    <- if (THEME == "light") "#4A4A44" else "#B8B7B0"
INK_MUTED   <- if (THEME == "light") "#6B6A63" else "#A8A79F"

IMPRINT_PALETTE <- c(
    "#009E73",  # 1 — brand green (ALWAYS first series)
    "#C475FD",  # 2 — lavender
    "#4467A3",  # 3 — blue
    "#BD8233",  # 4 — ochre
    "#AE3030",  # 5 — matte red
    "#2ABCCD",  # 6 — cyan
    "#954477",  # 7 — rose
    "#99B314"   # 8 — lime
)
BRAND <- IMPRINT_PALETTE[1]

# Raised fill alpha for dark theme so the fill silhouette reads clearly against near-black bg
FILL_ALPHA <- if (THEME == "light") 0.22 else 0.35

# Data — simulated plant seedling heights (mm) from two cultivars mixed in one batch,
# producing a characteristic bimodal distribution (short- and tall-growing varieties)
heights_short <- rnorm(420, mean = 38, sd = 6)
heights_tall  <- rnorm(180, mean = 72, sd = 9)
df <- data.frame(height = c(heights_short, heights_tall))

# Compute KDE to get annotation positions at the two cultivar peaks
dens_curve <- density(df$height, bw = "sj")
y_offset   <- max(dens_curve$y) * 0.06
ann_x      <- c(38, 72)
ann_y      <- approx(dens_curve$x, dens_curve$y, xout = ann_x)$y + y_offset

# Plot
p <- ggplot(df, aes(x = height)) +
    geom_density(
        fill      = BRAND,
        color     = BRAND,
        alpha     = FILL_ALPHA,
        linewidth = 1.2,
        bw        = "sj"
    ) +
    geom_rug(
        color     = BRAND,
        alpha     = 0.12,
        length    = unit(0.018, "npc"),
        linewidth = 0.4
    ) +
    annotate("text",
        x          = ann_x,
        y          = ann_y,
        label      = c("Short-growing\n(n = 420)", "Tall-growing\n(n = 180)"),
        color      = INK_SOFT,
        size       = 2.8,
        hjust      = 0.5,
        vjust      = 0,
        lineheight = 0.9
    ) +
    scale_x_continuous(expand = expansion(mult = c(0.02, 0.02))) +
    scale_y_continuous(expand = expansion(mult = c(0.0, 0.18))) +
    labs(
        x     = "Seedling Height (mm)",
        y     = "Density",
        title = "density-basic · r · ggplot2 · anyplot.ai"
    ) +
    theme_minimal(base_size = 8) +
    theme(
        plot.background    = element_rect(fill = PAGE_BG, color = PAGE_BG),
        panel.background   = element_rect(fill = PAGE_BG, color = NA),
        panel.grid.major.y = element_line(color = INK_SOFT, linewidth = 0.2),
        panel.grid.major.x = element_blank(),
        panel.grid.minor   = element_blank(),
        panel.border       = element_blank(),
        axis.title         = element_text(color = INK,      size = 10),
        axis.text          = element_text(color = INK_SOFT, size = 8),
        axis.line          = element_line(color = INK_SOFT, linewidth = 0.4),
        axis.ticks         = element_line(color = INK_SOFT, linewidth = 0.3),
        plot.title         = element_text(color = INK, size = 12, face = "bold",
                                          margin = margin(b = 10)),
        plot.margin        = margin(20, 25, 15, 15)
    )

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

Retrieve this implementation

Runnable source as JSON, for any HTTP client: https://api.anyplot.ai/specs/density-basic/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": "density-basic",
  "language": "r",
  "library": "ggplot2",
  "page": "https://anyplot.ai/density-basic/r/ggplot2",
  "hub": "https://anyplot.ai/density-basic",
  "code_json": "https://api.anyplot.ai/specs/density-basic/ggplot2/code",
  "spec_json": "https://api.anyplot.ai/specs/density-basic",
  "render_light_png": "https://storage.googleapis.com/anyplot-images/plots/density-basic/r/ggplot2/plot-light.png",
  "render_dark_png": "https://storage.googleapis.com/anyplot-images/plots/density-basic/r/ggplot2/plot-dark.png",
  "quality_score": 88.0,
  "license": "MIT",
  "guide": "https://anyplot.ai/llms.txt"
}

Part of Basic Density Plot on anyplot.ai.

Other implementations