{"spec_id":"line-stepwise","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' line-stepwise: Step Line Plot\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 80/100 | Created: 2026-09-05\n\nlibrary(ggplot2)\nlibrary(scales)\nlibrary(ragg)\n\nset.seed(42)\n\n# --- Theme tokens -------------------------------------------------------\nTHEME <- Sys.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG <- if (THEME == \"light\") \"#FAF8F1\" else \"#1A1A17\"\nINK <- if (THEME == \"light\") \"#1A1A17\" else \"#F0EFE8\"\nINK_SOFT <- if (THEME == \"light\") \"#4A4A44\" else \"#B8B7B0\"\nIMPRINT_PALETTE <- c(\n  \"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n  \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\"\n)\nBRAND <- IMPRINT_PALETTE[1]\n\n# --- Data -----------------------------------------------------------------\n# An elevator's floor position over an extended service period: it holds a\n# floor while passengers board or alight, then jumps instantly to the next\n# requested floor. The value is only known at each stop and is constant in\n# between.\nn_stops <- 90\nfloor_num <- integer(n_stops)\nfloor_num[1] <- sample(1:12, 1)\nfor (i in 2:n_stops) {\n  repeat {\n    candidate <- sample(1:12, 1)\n    if (candidate != floor_num[i - 1]) break\n  }\n  floor_num[i] <- candidate\n}\nwait_min <- round(runif(n_stops, 1, 6), 1)\nelapsed_min <- cumsum(c(0, wait_min[-n_stops]))\n\ndf <- tibble::tibble(elapsed_min = elapsed_min, floor_num = floor_num)\n\n# Call out the single largest floor change: this is the moment the elevator\n# travels farthest in one hop, giving the plot a focal point beyond the raw\n# step shape.\nfloor_diff <- diff(floor_num)\njump_idx <- which.max(abs(floor_diff))\njump_size <- floor_diff[jump_idx]\njump_x <- elapsed_min[jump_idx + 1]\njump_y <- floor_num[jump_idx + 1]\n\n# --- Plot -------------------------------------------------------------------\ntitle_text <- \"Elevator Floor Position · line-stepwise · r · ggplot2 · anyplot.ai\"\n\np <- ggplot(df, aes(x = elapsed_min, y = floor_num)) +\n  geom_step(color = BRAND, linewidth = 1.1, direction = \"hv\") +\n  geom_point(color = BRAND, size = 2.2, alpha = 0.9) +\n  geom_vline(xintercept = jump_x, color = INK_SOFT, linetype = \"dashed\", linewidth = 0.4) +\n  geom_point(\n    data = data.frame(x = jump_x, y = jump_y),\n    mapping = aes(x = x, y = y),\n    shape = 21, size = 4.5, fill = BRAND, color = PAGE_BG, stroke = 1.2,\n    inherit.aes = FALSE\n  ) +\n  scale_y_continuous(breaks = breaks_width(2)) +\n  labs(\n    title = title_text,\n    x = \"Elapsed Time (minutes)\",\n    y = \"Floor\",\n    caption = sprintf(\n      \"Largest single change: %+d floors at %.0f min elapsed\",\n      jump_size, jump_x\n    )\n  ) +\n  theme_minimal(base_size = 8) +\n  theme(\n    plot.background = element_rect(fill = PAGE_BG, color = PAGE_BG),\n    panel.background = element_rect(fill = PAGE_BG, color = NA),\n    panel.grid.major.y = element_line(color = INK, linewidth = 0.3),\n    panel.grid.major.x = element_blank(),\n    panel.grid.minor = element_blank(),\n    axis.title = element_text(color = INK, size = 10),\n    axis.text = element_text(color = INK_SOFT, size = 8),\n    axis.line = element_line(color = INK_SOFT),\n    axis.ticks = element_blank(),\n    plot.title = element_text(color = INK, size = 12),\n    plot.caption = element_text(color = INK_SOFT, size = 7, hjust = 0),\n    panel.border = element_blank()\n  )\n\n# --- Save -------------------------------------------------------------------\nggsave(\n  filename = sprintf(\"plot-%s.png\", THEME),\n  plot = p,\n  device = ragg::agg_png,\n  width = 8,\n  height = 4.5,\n  units = \"in\",\n  dpi = 400\n)\n"}