{"spec_id":"bar-pareto","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nbar-pareto: Pareto Chart with Cumulative Line\nLibrary: plotly 6.8.0 | Python 3.13.14\nQuality: 90/100 | Updated: 2026-06-20\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport plotly.graph_objects as go\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\nGRID = \"rgba(26,26,23,0.15)\" if THEME == \"light\" else \"rgba(240,239,232,0.15)\"\n\n# Imprint categorical palette\nBRAND = \"#009E73\"  # position 1 — Vital Few bars\nBLUE = \"#4467A3\"  # position 3 — cumulative line\n\n# Data — manufacturing defect types (Pareto principle applied to quality control)\ncategories = [\n    \"Scratches\",\n    \"Dents\",\n    \"Misalignment\",\n    \"Cracks\",\n    \"Discoloration\",\n    \"Burrs\",\n    \"Warping\",\n    \"Contamination\",\n    \"Chipping\",\n    \"Porosity\",\n]\ncounts = np.array([142, 118, 87, 64, 53, 38, 29, 21, 15, 9])\n\nsort_idx = np.argsort(-counts)\ncategories = [categories[i] for i in sort_idx]\ncounts = counts[sort_idx]\n\ncumulative_pct = np.cumsum(counts) / counts.sum() * 100\nthreshold_idx = int(np.searchsorted(cumulative_pct, 80, side=\"right\")) + 1\n\n# Plot\nfig = go.Figure()\n\n# Vital Few bars (Imprint brand green — categories driving 80% of defects)\nfig.add_trace(\n    go.Bar(\n        x=categories[:threshold_idx],\n        y=counts[:threshold_idx],\n        marker={\"color\": BRAND, \"line\": {\"width\": 0}},\n        name=\"Vital Few\",\n        yaxis=\"y\",\n    )\n)\n\n# Trivial Many bars (muted — lower-priority defect categories)\nfig.add_trace(\n    go.Bar(\n        x=categories[threshold_idx:],\n        y=counts[threshold_idx:],\n        marker={\"color\": INK_MUTED, \"line\": {\"width\": 0}},\n        name=\"Trivial Many\",\n        yaxis=\"y\",\n    )\n)\n\n# Cumulative percentage line (Imprint blue)\nfig.add_trace(\n    go.Scatter(\n        x=categories,\n        y=cumulative_pct,\n        mode=\"lines+markers+text\",\n        marker={\"size\": 14, \"color\": BLUE, \"line\": {\"width\": 2.5, \"color\": PAGE_BG}},\n        line={\"width\": 3.5, \"color\": BLUE, \"shape\": \"linear\"},\n        text=[f\"{v:.0f}%\" if i == threshold_idx - 1 else \"\" for i, v in enumerate(cumulative_pct)],\n        textposition=\"top center\",\n        textfont={\"size\": 12, \"color\": BLUE},\n        name=\"Cumulative %\",\n        yaxis=\"y2\",\n    )\n)\n\n# 80% reference line\nfig.add_hline(y=80, line={\"color\": INK_SOFT, \"width\": 2, \"dash\": \"dot\"}, yref=\"y2\")\nfig.add_annotation(\n    x=0.99,\n    y=80,\n    xref=\"paper\",\n    yref=\"y2\",\n    text=\"<b>80% threshold</b>\",\n    showarrow=False,\n    font={\"size\": 12, \"color\": INK_SOFT},\n    xanchor=\"right\",\n    yanchor=\"bottom\",\n    yshift=6,\n)\n\n# Vital few region shading (subtle green tint)\nfig.add_vrect(x0=-0.5, x1=threshold_idx - 0.5, fillcolor=\"rgba(0,158,115,0.06)\", line_width=0, layer=\"below\")\n\n# Value labels on top 3 bars\nfor i in range(min(3, len(counts))):\n    fig.add_annotation(\n        x=categories[i],\n        y=counts[i],\n        text=f\"<b>{counts[i]}</b>\",\n        showarrow=False,\n        font={\"size\": 12, \"color\": BRAND},\n        yshift=12,\n    )\n\ntitle = \"bar-pareto · python · plotly · anyplot.ai\"\n\n# Style\nfig.update_layout(\n    autosize=False,\n    title={\"text\": title, \"font\": {\"size\": 16, \"color\": INK}, \"x\": 0.5, \"xanchor\": \"center\", \"y\": 0.97},\n    xaxis={\n        \"title\": {\"text\": \"Defect Type\", \"font\": {\"size\": 12, \"color\": INK}, \"standoff\": 15},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showline\": False,\n        \"showgrid\": False,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Frequency\", \"font\": {\"size\": 12, \"color\": INK}, \"standoff\": 10},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"showgrid\": True,\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"zeroline\": False,\n        \"showline\": False,\n    },\n    yaxis2={\n        \"title\": {\"text\": \"Cumulative Percentage (%)\", \"font\": {\"size\": 12, \"color\": INK}, \"standoff\": 10},\n        \"tickfont\": {\"size\": 10, \"color\": INK_SOFT},\n        \"overlaying\": \"y\",\n        \"side\": \"right\",\n        \"range\": [0, 108],\n        \"showgrid\": False,\n        \"ticksuffix\": \"%\",\n        \"zeroline\": False,\n        \"linecolor\": INK_SOFT,\n    },\n    legend={\n        \"font\": {\"size\": 10, \"color\": INK_SOFT},\n        \"x\": 0.68,\n        \"y\": 0.35,\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n    },\n    bargap=0.12,\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    margin={\"t\": 80, \"b\": 60, \"l\": 80, \"r\": 90},\n    barmode=\"overlay\",\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=800, height=450, scale=4)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}