{"spec_id":"box-notched","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nbox-notched: Notched Box Plot\nLibrary: plotnine 0.15.8 | Python 3.13.15\nQuality: 90/100 | Updated: 2026-08-18\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_boxplot,\n    ggplot,\n    labs,\n    scale_fill_manual,\n    stat_summary,\n    theme,\n    theme_minimal,\n)\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\nIMPRINT = [\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\"]\n\n# Data - clinical trial outcomes across treatment groups\nnp.random.seed(42)\n\ngroups = [\"Control\", \"Treatment A\", \"Treatment B\", \"Treatment C\", \"Long-term\"]\nn_per_group = [120, 105, 110, 95, 100]\n\ndata = []\n# Control: baseline, modest median\ndata.extend([{\"group\": \"Control\", \"score\": v} for v in np.random.normal(65, 12, n_per_group[0])])\n# Treatment A: moderate improvement\ndata.extend([{\"group\": \"Treatment A\", \"score\": v} for v in np.random.normal(72, 11, n_per_group[1])])\n# Treatment B: strong improvement\ndata.extend([{\"group\": \"Treatment B\", \"score\": v} for v in np.random.normal(78, 10, n_per_group[2])])\n# Treatment C: variable response, some outliers\ntreatment_c = np.concatenate([np.random.normal(70, 13, 70), np.random.normal(88, 6, 25)])\ndata.extend([{\"group\": \"Treatment C\", \"score\": v} for v in treatment_c])\n# Long-term: sustained benefit\ndata.extend([{\"group\": \"Long-term\", \"score\": v} for v in np.random.normal(75, 9, n_per_group[4])])\n\ndf = pd.DataFrame(data)\ndf[\"group\"] = pd.Categorical(df[\"group\"], categories=groups, ordered=True)\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"group\", y=\"score\", fill=\"group\"))\n    + geom_boxplot(notch=True, notchwidth=0.5, outlier_size=2.5, outlier_alpha=0.7, size=0.7)\n    # Mean markers (diamond) layered over the median-based box — a plotnine-native\n    # way to expose the mean-vs-median gap that notches alone don't show.\n    + stat_summary(fun_y=np.mean, geom=\"point\", shape=\"D\", size=2.5, color=INK, alpha=0.9)\n    + scale_fill_manual(values=IMPRINT)\n    + labs(x=\"Treatment Group\", y=\"Clinical Score\", title=\"box-notched · plotnine · anyplot.ai\")\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\n        text=element_text(size=7),\n        axis_title=element_text(size=10, color=INK),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        plot_title=element_text(size=12, color=INK),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_grid_major=element_line(color=INK, size=0.3, alpha=0.10),\n        panel_grid_minor=element_line(color=INK, size=0.2, alpha=0.05),\n        # L-shaped spine (bottom + left only) instead of a full panel box —\n        # a leaner frame that keeps focus on the boxes/notches.\n        panel_border=element_blank(),\n        axis_line=element_line(color=INK_SOFT),\n        legend_position=\"none\",\n    )\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}