{"spec_id":"bar-pareto","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nbar-pareto: Pareto Chart with Cumulative Line\nLibrary: seaborn 0.13.2 | Python 3.13.14\nQuality: 89/100 | Updated: 2026-06-20\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\n\n\n# Theme tokens (Imprint palette — theme-adaptive chrome)\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\"\nBRAND = \"#009E73\"  # Imprint palette position 1 — dominant bars (≤80%)\nLINE_COLOR = \"#AE3030\"  # Imprint semantic red — cumulative threshold line\n\n# Apply seaborn theme with explicit RC overrides, then context for font hierarchy\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.15,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\nsns.set_context(\"notebook\", font_scale=0.8)\n\n# Data — 10 surface-quality defect categories (paint/surface/rework domain), descending frequency\ndata = pd.DataFrame(\n    {\n        \"defect\": [\n            \"Paint blistering\",\n            \"Surface scratches\",\n            \"Dents\",\n            \"Weld flaws\",\n            \"Cracks\",\n            \"Rework marks\",\n            \"Discoloration\",\n            \"Contamination\",\n            \"Burrs\",\n            \"Edge chips\",\n        ],\n        \"count\": [156, 124, 93, 71, 58, 37, 24, 16, 10, 7],\n    }\n)\n\n# Cumulative percentage\ncumulative_pct = np.cumsum(data[\"count\"]) / data[\"count\"].sum() * 100\n\n# Bar colors via seaborn palette API: dominant (≤80%) → brand green; tail → muted\nbar_color_list = [BRAND if cum <= 80 else INK_MUTED for cum in cumulative_pct]\nbar_palette = sns.color_palette(bar_color_list)\n\n# Canvas — 3200 × 1800 px landscape (hard contract: figsize=(8,4.5) × dpi=400)\nfig, ax1 = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax1.set_facecolor(PAGE_BG)\n\n# Bars\nsns.barplot(data=data, x=\"defect\", y=\"count\", hue=\"defect\", palette=bar_palette, legend=False, width=0.72, ax=ax1)\n\n# Count annotations above each bar (fontsize=8 for safer mobile readability)\nfor i, (_, row) in enumerate(data.iterrows()):\n    ax1.text(\n        i,\n        row[\"count\"] + 3,\n        str(int(row[\"count\"])),\n        ha=\"center\",\n        va=\"bottom\",\n        fontsize=8,\n        fontweight=\"bold\",\n        color=BRAND if cumulative_pct.iloc[i] <= 80 else INK_MUTED,\n    )\n\n# Primary axis styling\nax1.set_xlabel(\"Defect Type\", fontsize=10, color=INK)\nax1.set_ylabel(\"Frequency (Count)\", fontsize=10, color=INK)\nax1.tick_params(axis=\"x\", labelsize=7, colors=INK_SOFT, rotation=28)\nax1.tick_params(axis=\"y\", labelsize=8, colors=INK_SOFT)\nax1.yaxis.grid(True, alpha=0.15, linewidth=0.8)\nax1.set_axisbelow(True)\nax1.set_ylim(0, data[\"count\"].max() * 1.22)\nsns.despine(ax=ax1, top=True, right=True)\n\n# Secondary y-axis — cumulative percentage\nax2 = ax1.twinx()\nax2.patch.set_alpha(0)  # transparent so ax1 background shows through\n\n# Cumulative line — seaborn lineplot with DataFrame, explicit sort/estimator control\nline_df = pd.DataFrame({\"x\": range(len(data)), \"cumulative_pct\": cumulative_pct})\nsns.lineplot(\n    data=line_df,\n    x=\"x\",\n    y=\"cumulative_pct\",\n    color=LINE_COLOR,\n    marker=\"o\",\n    markersize=5,\n    linewidth=2.5,\n    sort=False,\n    estimator=None,\n    ax=ax2,\n)\nfor line in ax2.get_lines():\n    line.set_markeredgecolor(PAGE_BG)\n    line.set_markeredgewidth(1.5)\n\nax2.set_ylabel(\"Cumulative %\", fontsize=10, color=LINE_COLOR)\nax2.set_ylim(0, 110)\nax2.tick_params(axis=\"y\", labelsize=8, colors=LINE_COLOR)\nax2.yaxis.grid(False)\nsns.despine(ax=ax2, top=True, left=True, right=False)\nax2.spines[\"right\"].set_color(LINE_COLOR)\n\n# 80% reference line\nax2.axhline(y=80, color=LINE_COLOR, linestyle=\"--\", linewidth=1.2, alpha=0.55)\nax2.text(len(data) - 0.5, 82, \"80%\", fontsize=8, color=LINE_COLOR, ha=\"right\", va=\"bottom\")\n\n# Narrative annotation: 4 categories drive 75% of defects — Pareto insight at crossover\nax2.text(\n    3.5,\n    88,\n    \"top 4 → 75% of defects\",\n    fontsize=7.5,\n    color=LINE_COLOR,\n    ha=\"center\",\n    va=\"bottom\",\n    alpha=0.85,\n    style=\"italic\",\n)\n\n# Title\ntitle = \"bar-pareto · python · seaborn · anyplot.ai\"\nax1.set_title(title, fontsize=12, fontweight=\"medium\", color=INK, pad=12)\n\nfig.subplots_adjust(left=0.08, right=0.88, top=0.93, bottom=0.22)\n\n# Save — no bbox_inches so figsize × dpi lands on exact 3200 × 1800\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\nplt.close()\n"}