{"spec_id":"mosaic-categorical","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nmosaic-categorical: Mosaic Plot for Categorical Association Analysis\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 89/100 | Updated: 2026-05-19\n\"\"\"\n\nimport os\nimport sys\n\n\nsys.path = [p for p in sys.path if \"implementations\" not in p]\n\nimport matplotlib.patches as mpatches\nimport matplotlib.pyplot as plt\nfrom statsmodels.graphics.mosaicplot import mosaic\n\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\nCELL_COLORS = {\"Survived\": \"#009E73\", \"Did Not Survive\": \"#C475FD\"}\n\n# Data: Titanic passenger survival by class (realistic proportions)\ncounts = {\n    (\"First\", \"Survived\"): 136,\n    (\"First\", \"Did Not Survive\"): 64,\n    (\"Second\", \"Survived\"): 87,\n    (\"Second\", \"Did Not Survive\"): 93,\n    (\"Third\", \"Survived\"): 119,\n    (\"Third\", \"Did Not Survive\"): 381,\n}\n\n# Plot: core mosaic via statsmodels\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\nfig, rects = mosaic(\n    counts,\n    ax=ax,\n    gap=0.015,\n    properties=lambda key: {\"facecolor\": CELL_COLORS[key[1]], \"edgecolor\": PAGE_BG, \"linewidth\": 3},\n    labelizer=lambda key: str(counts[key]),\n    title=\"\",\n    axes_label=True,\n    statistic=False,\n)\n\n# Style cell count labels (white for contrast against colored cells)\nfor text in ax.texts:\n    text.set_color(\"white\")\n    text.set_fontsize(20)\n    text.set_fontweight(\"bold\")\n\n# Style\nax.set_title(\n    \"Titanic Passenger Survival · mosaic-categorical · python · matplotlib · anyplot.ai\",\n    fontsize=24,\n    fontweight=\"medium\",\n    color=INK,\n    pad=20,\n)\nax.set_xlabel(\"Passenger Class\", fontsize=20, color=INK, labelpad=12)\nax.set_ylabel(\"Survival Status\", fontsize=20, color=INK, labelpad=12)\nax.tick_params(length=0, labelcolor=INK_SOFT, labelsize=14)\n\nfor spine in ax.spines.values():\n    spine.set_color(INK_SOFT)\n\n# Legend\nlegend_handles = [\n    mpatches.Patch(facecolor=color, edgecolor=INK_SOFT, linewidth=1.5, label=label)\n    for label, color in CELL_COLORS.items()\n]\nleg = ax.legend(handles=legend_handles, loc=\"upper right\", fontsize=16)\nleg.get_frame().set_facecolor(ELEVATED_BG)\nleg.get_frame().set_edgecolor(INK_SOFT)\nplt.setp(leg.get_texts(), color=INK_SOFT)\n\n# Save\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}