{"spec_id":"marimekko-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nmarimekko-basic: Basic Marimekko Chart\nLibrary: letsplot 4.11.0 | Python 3.13.14\nQuality: 96/100 | Updated: 2026-07-24\n\"\"\"\n\nimport os\n\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_label,\n    geom_rect,\n    geom_segment,\n    geom_text,\n    ggplot,\n    ggsave,\n    ggsize,\n    labs,\n    layer_tooltips,\n    scale_fill_manual,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\n\n\nLetsPlot.setup_html()\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\n\n# Theme-adaptive chrome tokens (Imprint)\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Imprint categorical palette — product lines are abstract categories, canonical order applies\nIMPRINT_PALETTE = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\n\n# Data - Market share by region and product line\n# Regions as x-categories (bar widths), product lines as y-categories (stacked segments)\nregions = [\"North America\", \"Europe\", \"Asia Pacific\", \"Latin America\"]\nproducts = [\"Electronics\", \"Apparel\", \"Home Goods\", \"Food & Beverage\"]\n\n# Values in millions - each row is a product, each column is a region\nvalues = {\n    \"North America\": [120, 85, 65, 45],  # Total: 315\n    \"Europe\": [95, 110, 55, 60],  # Total: 320\n    \"Asia Pacific\": [180, 70, 90, 85],  # Total: 425\n    \"Latin America\": [40, 35, 25, 30],  # Total: 130\n}\n\nregion_totals = {region: sum(vals) for region, vals in values.items()}\ngrand_total = sum(region_totals.values())\nregion_widths = {region: total / grand_total * 100 for region, total in region_totals.items()}\nlargest_region = max(region_totals, key=region_totals.get)\n\n# Build rectangle coordinates for each segment\n# xmin/xmax: horizontal position (variable width = region's share of the total market)\n# ymin/ymax: vertical position (stacked from 0 to 100% = share within the region)\nrects = []\nx_pos = 0\n\nfor region in regions:\n    region_width = region_widths[region]\n    region_vals = values[region]\n    region_total = region_totals[region]\n\n    y_pos = 0\n    for i, product in enumerate(products):\n        product_value = region_vals[i]\n        segment_height = (product_value / region_total) * 100\n        # Visual area proxy (width% x height%) — only label segments large enough to hold text cleanly\n        area = region_width * segment_height\n\n        rects.append(\n            {\n                \"region\": region,\n                \"product\": product,\n                \"value\": product_value,\n                \"share\": round(segment_height, 1),\n                \"region_total\": region_total,\n                \"xmin\": x_pos,\n                \"xmax\": x_pos + region_width,\n                \"ymin\": y_pos,\n                \"ymax\": y_pos + segment_height,\n                \"x_center\": x_pos + region_width / 2,\n                \"y_center\": y_pos + segment_height / 2,\n                \"label\": f\"${product_value}M\" if area >= 300 else \"\",\n            }\n        )\n        y_pos += segment_height\n\n    x_pos += region_width\n\ndf = pd.DataFrame(rects)\n\n# One row per region for the total-size annotation above each bar and the \"largest market\" callout\ntotals_df = df.drop_duplicates(subset=\"region\")[[\"region\", \"x_center\", \"region_total\"]].copy()\ntotals_df[\"label\"] = totals_df[\"region_total\"].apply(lambda v: f\"${v}M total\")\ncallout_df = totals_df[totals_df[\"region\"] == largest_region].copy()\ncallout_df[\"label\"] = \"Largest market\"\n\nplot = (\n    ggplot(df)\n    + geom_rect(\n        aes(xmin=\"xmin\", xmax=\"xmax\", ymin=\"ymin\", ymax=\"ymax\", fill=\"product\"),\n        color=PAGE_BG,\n        size=0.6,\n        tooltips=layer_tooltips().line(\"@region\").line(\"@product: $@value M\").line(\"Share of region: @share%\"),\n    )\n    + geom_text(aes(x=\"x_center\", y=\"y_center\", label=\"label\"), size=3.6, color=\"#FFFFFF\", fontface=\"bold\")\n    # Region-total annotation above each bar — surfaces the variable that actually sets bar width\n    + geom_text(\n        data=totals_df, mapping=aes(x=\"x_center\", label=\"label\"), y=105, size=3.2, color=INK_SOFT, fontface=\"italic\"\n    )\n    # Leader line connecting the callout down to the top of its bar, so the association is explicit\n    + geom_segment(\n        data=callout_df, mapping=aes(x=\"x_center\", xend=\"x_center\"), y=113, yend=101, color=INK_SOFT, size=0.5\n    )\n    # Callout on the largest market by total value — sized up from the region-total annotations for a\n    # clear two-tier hierarchy (primary value labels > callout > region totals > tick labels)\n    + geom_label(\n        data=callout_df,\n        mapping=aes(x=\"x_center\", label=\"label\"),\n        y=117,\n        size=4.2,\n        color=INK,\n        fill=ELEVATED_BG,\n        fontface=\"bold\",\n        label_padding=0.4,\n    )\n    + scale_fill_manual(values=IMPRINT_PALETTE, name=\"Product Line\")\n    + scale_x_continuous(\n        name=\"Market Size Distribution\",\n        breaks=[df[df[\"region\"] == r][\"x_center\"].iloc[0] for r in regions],\n        labels=regions,\n        limits=[-2, 102],\n    )\n    + scale_y_continuous(\n        name=\"Share within Region (%)\",\n        breaks=[0, 25, 50, 75, 100],\n        labels=[\"0%\", \"25%\", \"50%\", \"75%\", \"100%\"],\n        limits=[0, 124],\n    )\n    + labs(title=\"marimekko-basic · python · letsplot · anyplot.ai\")\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_grid_major=element_blank(),\n        panel_grid_minor=element_blank(),\n        axis_line=element_line(color=INK_SOFT),\n        plot_title=element_text(size=16, color=INK, hjust=0.5),\n        axis_title=element_text(size=12, color=INK),\n        axis_text_x=element_text(size=10, color=INK_SOFT, angle=10),\n        axis_text_y=element_text(size=10, color=INK_SOFT),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_title=element_text(size=12, color=INK),\n        legend_text=element_text(size=10, color=INK_SOFT),\n        legend_position=\"right\",\n    )\n    + ggsize(800, 450)\n)\n\nggsave(plot, f\"plot-{THEME}.png\", scale=4, path=\".\")\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}