{"spec_id":"histogram-cumulative","library":"makie","language":"julia","code":"# anyplot.ai\n# histogram-cumulative: Cumulative Histogram\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 91/100 | Created: 2026-09-05\n\nusing CairoMakie\nusing Colors\nusing Random\nusing Statistics\n\nRandom.seed!(42)\n\n# --- Theme tokens ------------------------------------------------------------\nconst THEME    = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG  = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK      = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst BRAND    = colorant\"#009E73\"  # Imprint palette position 1 — ALWAYS first series\n\n# --- Data ----------------------------------------------------------------\n# Parcel delivery times (hours) for an e-commerce carrier — a right-skewed\n# lead-time distribution typical of logistics data.\nn_orders = 1400\ndelivery_hours = exp.(0.45 .* randn(n_orders) .+ log(28.0))\n\nn_bins = 28\nedges = range(0.0, quantile(delivery_hours, 0.99), length = n_bins + 1)\ncounts = zeros(Int, n_bins)\nfor t in delivery_hours\n    # Values past the 99th-percentile edge fall into the last bin, so the\n    # tail is still counted while the axis stays focused on the bulk of it.\n    idx = clamp(searchsortedlast(edges, t), 1, n_bins)\n    counts[idx] += 1\nend\ncum_proportion = cumsum(counts) ./ n_orders\n\n# Ogive polyline: flat within each bin at its cumulative level, with a\n# vertical rise at every bin edge — the standard cumulative-histogram step.\nstep_x = Float64[edges[1]]\nstep_y = Float64[0.0]\nfor i in 1:n_bins\n    push!(step_x, edges[i]); push!(step_y, cum_proportion[i])\n    push!(step_x, edges[i + 1]); push!(step_y, cum_proportion[i])\nend\n\n# --- Plot ----------------------------------------------------------------\nfig = Figure(\n    size            = (1600, 900),\n    fontsize        = 14,\n    backgroundcolor = PAGE_BG,\n)\n\nax = Axis(\n    fig[1, 1];\n    title             = \"histogram-cumulative · julia · makie · anyplot.ai\",\n    titlesize         = 20,\n    titlecolor        = INK,\n    xlabel            = \"Delivery Time (hours)\",\n    ylabel            = \"Cumulative Proportion of Orders\",\n    xlabelsize        = 14,\n    ylabelsize        = 14,\n    xlabelcolor       = INK,\n    ylabelcolor       = INK,\n    xticklabelsize    = 12,\n    yticklabelsize    = 12,\n    xticklabelcolor   = INK_SOFT,\n    yticklabelcolor   = INK_SOFT,\n    xtickcolor        = INK_SOFT,\n    ytickcolor        = INK_SOFT,\n    backgroundcolor   = PAGE_BG,\n    topspinevisible   = false,\n    rightspinevisible = false,\n    leftspinecolor    = INK_SOFT,\n    bottomspinecolor  = INK_SOFT,\n    xgridvisible      = false,\n    ygridcolor        = RGBAf(INK.r, INK.g, INK.b, 0.15),\n    yminorgridvisible = false,\n    yticks            = 0:0.25:1.0,\n)\n\nband!(ax, step_x, zeros(length(step_x)), step_y; color = (BRAND, 0.12))\n\n# The step LINE itself uses Makie's native `stairs!` recipe (step = :pre)\n# rather than a hand-drawn polyline — `:pre` jumps to each bin's cumulative\n# level right at its left edge, reproducing the same ogive shape as step_x/\n# step_y above while showcasing a Makie-distinctive step-plot primitive.\nstairs!(ax, edges, vcat(0.0, cum_proportion); step = :pre, color = BRAND, linewidth = 3.5)\n\nxlims!(ax, edges[1], edges[end])\nylims!(ax, 0.0, 1.02)\n\n# --- Median reference guide ------------------------------------------------\n# The spec calls out percentile-reading as a primary application; a dashed\n# median guide with an inline label lets the viewer read a concrete value\n# off the curve instead of eyeballing the shape alone.\nmedian_hours = quantile(delivery_hours, 0.5)\nlines!(ax, [median_hours, median_hours], [0.0, 0.5]; color = INK_SOFT, linestyle = :dash, linewidth = 1.5)\nlines!(ax, [edges[1], median_hours], [0.5, 0.5]; color = INK_SOFT, linestyle = :dash, linewidth = 1.5)\ntext!(\n    ax, median_hours, 0.5;\n    text = \"Median: $(round(median_hours, digits = 1))h\",\n    align = (:left, :bottom),\n    offset = (8, 6),\n    color = INK,\n    fontsize = 13,\n)\n\n# --- Save ----------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}