{"spec_id":"marimekko-basic","library":"ggplot2","language":"r","code":"#' anyplot.ai\n#' marimekko-basic: Basic Marimekko Chart\n#' Library: ggplot2 3.5.1 | R 4.4.1\n#' Quality: 92/100 | Created: 2026-07-24\n\nlibrary(ggplot2)\nlibrary(dplyr)\nlibrary(ragg)\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\"\nLABEL_INK <- \"#FFFDF6\"  # near-white text sits on top of every saturated fill below\n\n# Imprint palette (see prompts/default-style-guide.md) — first series always green\nIMPRINT_PALETTE <- c(\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\",\n                     \"#AE3030\", \"#2ABCCD\", \"#954477\", \"#99B314\")\n\n# --- Data: global software revenue mix, region x product line (USD millions) -\nrevenue <- tibble::tribble(\n  ~region,          ~product,    ~revenue_musd,\n  \"North America\",  \"Software\",  420,\n  \"North America\",  \"Hardware\",  310,\n  \"North America\",  \"Services\",  180,\n  \"North America\",  \"Support\",    90,\n  \"Asia Pacific\",   \"Software\",  300,\n  \"Asia Pacific\",   \"Hardware\",  380,\n  \"Asia Pacific\",   \"Services\",  140,\n  \"Asia Pacific\",   \"Support\",    60,\n  \"Europe\",         \"Software\",  260,\n  \"Europe\",         \"Hardware\",  240,\n  \"Europe\",         \"Services\",  150,\n  \"Europe\",         \"Support\",    70,\n  \"Latin America\",  \"Software\",   90,\n  \"Latin America\",  \"Hardware\",  110,\n  \"Latin America\",  \"Services\",   60,\n  \"Latin America\",  \"Support\",    30,\n  \"Middle East\",    \"Software\",   70,\n  \"Middle East\",    \"Hardware\",   90,\n  \"Middle East\",    \"Services\",   40,\n  \"Middle East\",    \"Support\",    20\n)\n\nproduct_levels <- c(\"Software\", \"Hardware\", \"Services\", \"Support\")\nrevenue <- revenue %>% mutate(product = factor(product, levels = product_levels))\n\n# Column widths ~ total revenue per region, widest region first, small gaps\n# between columns so the mosaic reads as distinct bars rather than one block.\ncol_totals <- revenue %>%\n  group_by(region) %>%\n  summarise(total = sum(revenue_musd), .groups = \"drop\") %>%\n  arrange(desc(total)) %>%\n  mutate(xmax_raw = cumsum(total), xmin_raw = lag(xmax_raw, default = 0))\n\ngap <- max(col_totals$xmax_raw) * 0.008\ncol_totals <- col_totals %>%\n  mutate(xmin = xmin_raw + gap, xmax = xmax_raw - gap, xmid = (xmin + xmax) / 2)\n\nregion_levels <- col_totals$region\n\n# Segment heights ~ share of the column total, stacked in a fixed product\n# order so a given color occupies a comparable band across every column.\nmarimekko <- revenue %>%\n  mutate(region = factor(region, levels = region_levels)) %>%\n  left_join(col_totals, by = \"region\") %>%\n  arrange(region, product) %>%\n  group_by(region) %>%\n  mutate(\n    share    = revenue_musd / total,\n    ymax     = cumsum(share),\n    ymin     = lag(ymax, default = 0),\n    label_y  = (ymin + ymax) / 2,\n    seg_area = (xmax - xmin) * (ymax - ymin)\n  ) %>%\n  ungroup()\n\narea_threshold <- sum(col_totals$total) * 0.05\n\n# --- Callout: Asia Pacific is the only region where Hardware outsells Software\napac_col  <- col_totals %>% filter(region == \"Asia Pacific\")\napac_hw   <- marimekko  %>% filter(region == \"Asia Pacific\", product == \"Hardware\")\n\n# --- Title (fontsize scales with length; see default-style-guide.md) --------\nplot_title <- \"Global Software Revenue Mix · marimekko-basic · r · ggplot2 · anyplot.ai\"\ntitle_fontsize <- max(8, round(12 * min(1, 67 / nchar(plot_title))))\n\n# --- Plot ---------------------------------------------------------------------\np <- ggplot(marimekko) +\n  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, fill = product),\n            color = PAGE_BG, linewidth = 0.6) +\n  geom_text(\n    data = filter(marimekko, seg_area > area_threshold),\n    aes(x = xmid, y = label_y, label = paste0(\"$\", revenue_musd, \"M\")),\n    color = LABEL_INK, size = 3.2, fontface = \"bold\"\n  ) +\n  scale_x_continuous(\n    breaks = col_totals$xmid, labels = col_totals$region,\n    expand = expansion(mult = c(0, 0.015))\n  ) +\n  scale_y_continuous(\n    breaks = seq(0, 1, 0.25), labels = scales::percent_format(accuracy = 1),\n    expand = expansion(mult = c(0, 0.16))\n  ) +\n  scale_fill_manual(values = IMPRINT_PALETTE[seq_along(product_levels)], name = \"Product line\") +\n  annotate(\n    \"curve\", x = apac_col$xmid, xend = apac_col$xmid,\n    y = 1.13, yend = apac_hw$ymax + 0.02,\n    curvature = 0, linewidth = 0.4, color = INK_SOFT,\n    arrow = arrow(length = unit(0.1, \"cm\"), type = \"closed\")\n  ) +\n  annotate(\n    \"text\", x = apac_col$xmid, y = 1.15,\n    label = \"Only region where Hardware\\noutsells Software\",\n    color = INK_SOFT, size = 2.5, fontface = \"italic\",\n    lineheight = 0.9, vjust = 0\n  ) +\n  labs(\n    title = plot_title,\n    x = \"Region (bar width ∝ total revenue)\",\n    y = \"Share of regional revenue\"\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        = element_blank(),\n    axis.title        = element_text(color = INK, size = 10),\n    axis.text.x       = element_text(color = INK_SOFT, size = 8, angle = 25, hjust = 1),\n    axis.text.y       = element_text(color = INK_SOFT, size = 8),\n    axis.ticks        = element_blank(),\n    axis.line         = element_blank(),\n    plot.title        = element_text(color = INK, size = title_fontsize),\n    plot.margin       = margin(t = 16, r = 30, b = 16, l = 16),\n    legend.background = element_rect(fill = PAGE_BG, color = NA),\n    legend.key        = element_rect(fill = PAGE_BG, color = NA),\n    legend.text       = element_text(color = INK_SOFT, size = 8),\n    legend.title      = element_text(color = INK, size = 10),\n    legend.position   = \"top\"\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"}