{"spec_id":"waffle-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\nwaffle-basic: Basic Waffle Chart\nLibrary: letsplot 4.9.0 | Python 3.13.13\nQuality: 93/100 | Updated: 2026-05-05\n\"\"\"\n\nimport os\n\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    coord_fixed,\n    element_blank,\n    element_rect,\n    element_text,\n    geom_tile,\n    ggplot,\n    ggsize,\n    labs,\n    scale_fill_manual,\n    theme,\n    theme_void,\n)\nfrom lets_plot.export import ggsave\n\n\nLetsPlot.setup_html()\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\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# Okabe-Ito palette (first series ALWAYS #009E73)\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\"]\n\n# Data - Survey results on voting preferences (values sum to 100%)\ncategories = [\"Very Likely\", \"Likely\", \"Neutral\", \"Unlikely\"]\nvalues = [45, 28, 18, 9]  # Percentages\n\n# Build 10x10 waffle grid (100 squares, each = 1%)\ngrid_data = []\nsquare_idx = 0\n\nfor cat, val in zip(categories, values, strict=True):\n    for _ in range(val):\n        row = 9 - (square_idx // 10)\n        col = square_idx % 10\n        grid_data.append({\"x\": col, \"y\": row, \"category\": cat})\n        square_idx += 1\n\ndf = pd.DataFrame(grid_data)\ndf[\"category\"] = pd.Categorical(df[\"category\"], categories=categories, ordered=True)\n\n# Create legend labels with percentages\nlegend_labels = {cat: f\"{cat} ({val}%)\" for cat, val in zip(categories, values, strict=True)}\ndf[\"legend_label\"] = df[\"category\"].map(legend_labels)\ndf[\"legend_label\"] = pd.Categorical(\n    df[\"legend_label\"], categories=[legend_labels[cat] for cat in categories], ordered=True\n)\n\n# Theme-adaptive custom theme\nanyplot_theme = theme(\n    plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n    panel_background=element_rect(fill=PAGE_BG),\n    plot_title=element_text(size=24, color=INK, hjust=0.5),\n    legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n    legend_title=element_text(size=18, color=INK),\n    legend_text=element_text(size=16, color=INK_SOFT),\n    axis_title=element_blank(),\n    axis_text=element_blank(),\n    axis_line=element_blank(),\n)\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"x\", y=\"y\", fill=\"legend_label\"))\n    + geom_tile(width=0.88, height=0.88, size=0)\n    + coord_fixed(ratio=1)\n    + scale_fill_manual(values=IMPRINT)\n    + labs(title=\"waffle-basic · letsplot · anyplot.ai\", fill=\"Preference\")\n    + theme_void()\n    + anyplot_theme\n    + ggsize(1600, 900)\n)\n\n# Save outputs\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=3)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}