{"spec_id":"violin-grouped-swarm","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nviolin-grouped-swarm: Grouped Violin Plot with Swarm Overlay\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 89/100 | Updated: 2026-05-18\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    element_line,\n    element_rect,\n    element_text,\n    geom_jitter,\n    geom_violin,\n    ggplot,\n    guides,\n    labs,\n    position_dodge,\n    scale_color_manual,\n    scale_fill_manual,\n    theme,\n)\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\n\n# Okabe-Ito palette\nIMPRINT = [\"#009E73\", \"#C475FD\"]\n\n# Data - Response times (ms) across task types and expertise levels\nnp.random.seed(42)\n\ncategories = [\"Simple\", \"Moderate\", \"Complex\"]\ngroups = [\"Novice\", \"Expert\"]\nn_per_combination = 40\n\ndata = []\nfor category in categories:\n    for group in groups:\n        base = {\"Simple\": 400, \"Moderate\": 700, \"Complex\": 1100}[category]\n        if group == \"Expert\":\n            base -= 150\n        spread = {\"Simple\": 60, \"Moderate\": 100, \"Complex\": 150}[category]\n        values = np.random.normal(base, spread, n_per_combination)\n        values = np.clip(values, base - 3 * spread, base + 3 * spread)\n        for v in values:\n            data.append({\"task_type\": category, \"expertise\": group, \"response_time\": v})\n\ndf = pd.DataFrame(data)\ndf[\"task_type\"] = pd.Categorical(df[\"task_type\"], categories=categories, ordered=True)\ndf[\"expertise\"] = pd.Categorical(df[\"expertise\"], categories=groups, ordered=True)\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"task_type\", y=\"response_time\", fill=\"expertise\"))\n    + geom_violin(position=position_dodge(width=0.8), alpha=0.5, size=0.8)\n    + geom_jitter(aes(color=\"expertise\"), position=position_dodge(width=0.8), size=2.5, alpha=0.8)\n    + scale_fill_manual(values=IMPRINT, name=\"Expertise\")\n    + scale_color_manual(values=IMPRINT, name=\"Expertise\")\n    + guides(color=\"none\")\n    + labs(title=\"violin-grouped-swarm · Python · plotnine · anyplot.ai\", x=\"Task Type\", y=\"Response Time (ms)\")\n    + theme(\n        figure_size=(16, 9),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_border=element_rect(color=INK_SOFT, fill=None),\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        axis_title=element_text(size=20, color=INK),\n        axis_text=element_text(size=16, color=INK_SOFT),\n        axis_line=element_line(color=INK_SOFT),\n        plot_title=element_text(size=24, color=INK),\n        legend_background=element_rect(fill=PAGE_BG, color=INK_SOFT),\n        legend_text=element_text(size=16, color=INK_SOFT),\n        legend_title=element_text(size=18, color=INK),\n        text=element_text(size=14),\n    )\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=300, verbose=False)\n"}