{"spec_id":"count-basic","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\ncount-basic: Basic Count Plot\nLibrary: matplotlib 3.11.1 | Python 3.13.14\nQuality: 94/100 | Updated: 2026-08-11\n\"\"\"\n\nimport os\nimport sys\n\n\nsys.path.pop(0)\nimport matplotlib.patheffects as path_effects\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.colors import to_rgba\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\nBRAND = \"#009E73\"  # Imprint palette position 1 — ALWAYS first series\n\n# Data - Survey responses with varying frequencies\nnp.random.seed(42)\ncategories = [\"Strongly Agree\", \"Agree\", \"Neutral\", \"Disagree\", \"Strongly Disagree\"]\nweights = [0.15, 0.35, 0.25, 0.18, 0.07]\nresponses = np.random.choice(categories, size=200, p=weights)\n\n# Count occurrences\nunique, counts = np.unique(responses, return_counts=True)\n\n# Sort by frequency (descending)\nsort_idx = np.argsort(counts)[::-1]\nunique = unique[sort_idx]\ncounts = counts[sort_idx]\ntotal = counts.sum()\npercentages = counts / total * 100\n\n# Plot\nfig, ax = plt.subplots(figsize=(8, 4.5), dpi=400, facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Rank-graded opacity on the single brand hue — draws the eye to the leading\n# response without introducing a second color (single-series data stays one series).\nfade = np.linspace(1.0, 0.5, len(counts))\nbar_colors = [to_rgba(BRAND, alpha=a) for a in fade]\nbars = ax.bar(unique, counts, color=bar_colors, edgecolor=PAGE_BG, linewidth=1.5, width=0.62)\n\n# Average reference line for storytelling context (how far each bar sits from the mean)\navg = counts.mean()\nax.axhline(avg, color=INK_MUTED, linewidth=1.2, linestyle=(0, (5, 4)), zorder=1)\nax.text(\n    0.985,\n    avg,\n    f\"avg {avg:.0f}\",\n    transform=ax.get_yaxis_transform(),\n    ha=\"right\",\n    va=\"bottom\",\n    fontsize=9,\n    color=INK_MUTED,\n)\n\n# Direct value + share labels replace the y-axis (matplotlib's bar_label API\n# returns the created Text artists, letting the leading category stand out).\nvalue_labels = ax.bar_label(\n    bars,\n    labels=[f\"{c}\\n{p:.0f}%\" for c, p in zip(counts, percentages, strict=True)],\n    padding=10,\n    fontsize=10,\n    color=INK,\n    linespacing=1.3,\n)\nvalue_labels[0].set_fontsize(13)\nvalue_labels[0].set_fontweight(\"bold\")\n# Path-effect stroke on the leading label — a matplotlib-specific text-rendering\n# trick (draws a background-colored outline pass under the glyphs) that makes the\n# winner pop a little further without adding a second color or a heavier box.\nvalue_labels[0].set_path_effects([path_effects.withStroke(linewidth=4, foreground=PAGE_BG)])\n# Mask the average line where a label would otherwise cross it\nfor lbl in value_labels:\n    lbl.set_bbox({\"facecolor\": PAGE_BG, \"edgecolor\": \"none\", \"pad\": 3})\n\n# Style — minimalist: no y-axis labels, values are direct-labeled on the bars instead\nax.set_xlabel(\"Survey Response\", fontsize=11, color=INK)\nax.set_title(\"count-basic · python · matplotlib · anyplot.ai\", fontsize=13, fontweight=\"medium\", color=INK)\nax.tick_params(axis=\"x\", labelsize=10, colors=INK_SOFT)\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"left\"].set_visible(False)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Headroom for the two-line bar labels above the tallest bar\nax.set_ylim(0, counts.max() * 1.35)\n\n# Faint reference gridlines (no numeric labels) give returning readers a scale\n# anchor without reintroducing a full y-axis — the direct bar labels stay the\n# primary reading mode.\nax.set_yticks(np.linspace(0, counts.max() * 1.35, 5))\nax.set_yticklabels([])\nax.tick_params(axis=\"y\", length=0)\nax.yaxis.grid(True, color=INK, alpha=0.08, linewidth=0.8, zorder=0)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=400, facecolor=PAGE_BG)\n"}