{"spec_id":"elbow-curve","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nelbow-curve: Elbow Curve for K-Means Clustering\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-10\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    annotate,\n    element_line,\n    element_rect,\n    element_text,\n    geom_line,\n    geom_point,\n    geom_vline,\n    ggplot,\n    labs,\n    scale_x_continuous,\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\", \"#2ABCCD\", \"#954477\"]\nBRAND = IMPRINT[0]  # #009E73 - first series always\nACCENT = IMPRINT[1]  # #C475FD - accent for annotation line\n\n# Data - Simulate realistic K-means inertia values\nnp.random.seed(42)\n\nk_values = list(range(1, 11))\n\n# Simulate inertia values that show clear elbow at k=4\nbase_inertias = [1000, 500, 280, 150, 120, 100, 85, 75, 68, 62]\nnoise = np.random.uniform(-5, 5, len(k_values))\ninertias = [max(10, base + n) for base, n in zip(base_inertias, noise, strict=True)]\n\n# Create DataFrame for plotting\ndf = pd.DataFrame({\"k\": k_values, \"inertia\": inertias})\n\n# Optimal k (elbow point)\noptimal_k = 4\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"k\", y=\"inertia\"))\n    + geom_line(color=BRAND, size=2, alpha=0.9)\n    + geom_point(color=BRAND, size=5, alpha=1.0)\n    + geom_vline(xintercept=optimal_k, linetype=\"dashed\", color=ACCENT, size=1.5, alpha=0.8)\n    + annotate(\n        \"text\",\n        x=optimal_k + 0.5,\n        y=inertias[optimal_k - 1] + 80,\n        label=f\"Optimal k = {optimal_k}\",\n        size=14,\n        color=ACCENT,\n        ha=\"left\",\n        fontweight=\"bold\",\n    )\n    + labs(\n        title=\"elbow-curve · plotnine · anyplot.ai\",\n        x=\"Number of Clusters (k)\",\n        y=\"Inertia (Within-Cluster Sum of Squares)\",\n    )\n    + scale_x_continuous(breaks=list(range(1, 11)))\n    + theme_minimal()\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_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        panel_border=element_rect(color=INK_SOFT, fill=None, size=0.5),\n        plot_title=element_text(size=24, color=INK, weight=\"bold\"),\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, size=0.5),\n        legend_background=element_rect(fill=ELEVATED_BG, color=INK_SOFT),\n        legend_text=element_text(size=16, color=INK_SOFT),\n        legend_title=element_text(size=16, color=INK),\n    )\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=300, verbose=False)\n"}