{"spec_id":"errorbar-asymmetric","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' errorbar-asymmetric: Asymmetric Error Bars Plot\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 86/100 | Created: 2026-09-05\n\nlibrary(ggplot2)\nlibrary(dplyr)\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(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                     \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\")\nBRAND <- IMPRINT_PALETTE[1]\n\n# --- Data ---------------------------------------------------------------\n# Annual rainfall is right-skewed (occasional very wet years pull the upper\n# tail out further than the lower tail), so the 10th-90th percentile range\n# around the median is naturally asymmetric.\nstations <- c(\"Manaus\", \"Singapore\", \"Mumbai\", \"Miami\", \"Bangkok\", \"Lagos\",\n              \"Jakarta\", \"Houston\", \"Tokyo\", \"Sydney\", \"Cairo\", \"Phoenix\")\ntypical_mm <- c(2200, 2100, 1900, 1500, 1450, 1350,\n                1750, 1200, 1500, 850, 30, 200)\n\nstation_quantiles <- lapply(seq_along(stations), function(i) {\n  samples <- rlnorm(2000, meanlog = log(typical_mm[i]), sdlog = 0.28)\n  quantile(samples, probs = c(0.10, 0.50, 0.90))\n})\n\ndf <- tibble::tibble(\n  station   = stations,\n  p10       = vapply(station_quantiles, `[[`, numeric(1), 1),\n  median_mm = vapply(station_quantiles, `[[`, numeric(1), 2),\n  p90       = vapply(station_quantiles, `[[`, numeric(1), 3)\n) %>%\n  mutate(\n    error_lower = median_mm - p10,\n    error_upper = p90 - median_mm,\n    station     = factor(station, levels = stations[order(median_mm)])\n  )\n\noverall_median <- median(df$median_mm)\n\n# --- Plot -----------------------------------------------------------------\n# A dashed reference line at the cross-station median gives readers an\n# anchor to judge each station's rainfall against, beyond the sorted order.\np <- ggplot(df, aes(x = station, y = median_mm)) +\n  geom_hline(\n    yintercept = overall_median, linetype = \"dashed\",\n    color = INK_SOFT, linewidth = 0.5, alpha = 0.7\n  ) +\n  geom_errorbar(\n    aes(ymin = median_mm - error_lower, ymax = median_mm + error_upper),\n    color = BRAND, width = 0.3, linewidth = 0.8\n  ) +\n  geom_point(color = BRAND, size = 2.8) +\n  annotate(\n    \"text\", x = 12.5, y = overall_median,\n    label = sprintf(\"All-station median: %s mm\", label_comma()(round(overall_median))),\n    hjust = 0.5, vjust = 0, size = 2.6, color = INK_SOFT, fontface = \"italic\"\n  ) +\n  coord_flip(clip = \"off\") +\n  scale_y_continuous(labels = label_comma()) +\n  labs(\n    title    = \"errorbar-asymmetric · r · ggplot2 · anyplot.ai\",\n    subtitle = \"Median annual rainfall with 10th–90th percentile range\",\n    x        = NULL,\n    y        = \"Annual rainfall (mm)\"\n  ) +\n  theme_minimal(base_size = 7) +\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  = element_line(color = alpha(INK, 0.15), linewidth = 0.4),\n    panel.grid.minor  = element_blank(),\n    panel.grid.major.y = element_blank(),\n    axis.line.x       = element_line(color = INK_SOFT),\n    axis.ticks        = element_blank(),\n    axis.title        = element_text(color = INK, size = 10),\n    axis.text         = element_text(color = INK_SOFT, size = 8),\n    plot.title        = element_text(color = INK, size = 12, face = \"bold\"),\n    plot.subtitle     = element_text(color = INK_SOFT, size = 9),\n    plot.margin       = margin(22, 16, 12, 12)\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"}