{"spec_id":"line-pca-variance-cumulative","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nline-pca-variance-cumulative: Cumulative Explained Variance for PCA Component Selection\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-29\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom plotnine import (\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_col,\n    geom_hline,\n    geom_line,\n    geom_point,\n    geom_segment,\n    geom_text,\n    ggplot,\n    labs,\n    scale_x_continuous,\n    scale_y_continuous,\n    theme,\n    theme_minimal,\n)\nfrom sklearn.datasets import load_wine\nfrom sklearn.decomposition import PCA\nfrom sklearn.preprocessing import StandardScaler\n\n\n# Theme tokens — Imprint palette, theme-adaptive chrome\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\"\n\n# Imprint palette\nBRAND = \"#009E73\"  # Imprint position 1 — ALWAYS first series\nIMPRINT_RED = \"#AE3030\"  # Imprint matte red — semantic anchor for elbow emphasis\n\n# Data — PCA on the Wine dataset (13 features)\nX_scaled = StandardScaler().fit_transform(load_wine().data)\npca = PCA().fit(X_scaled)\n\nn_components = np.arange(1, len(pca.explained_variance_ratio_) + 1)\ncumulative_var = np.cumsum(pca.explained_variance_ratio_) * 100\nindividual_var = pca.explained_variance_ratio_ * 100\n\ndf = pd.DataFrame({\"component\": n_components, \"cumulative\": cumulative_var, \"individual\": individual_var})\n\n# Elbow detection via maximum second-derivative change\ndiffs = np.diff(cumulative_var)\nelbow_idx = int(np.argmax(np.abs(np.diff(diffs)))) + 1\nelbow_c = int(n_components[elbow_idx])\nelbow_v = cumulative_var[elbow_idx]\nelbow_df = pd.DataFrame(\n    {\"component\": [elbow_c], \"cumulative\": [elbow_v], \"label\": [f\"Elbow: {elbow_c} components\\n({elbow_v:.1f}%)\"]}\n)\n\n# Threshold reference lines\nthresholds = pd.DataFrame({\"y\": [90.0, 95.0, 99.0], \"label\": [\"90%\", \"95%\", \"99%\"], \"x\": [12.5, 12.5, 12.5]})\n\n# Title fontsize — scaled by length per plot-generator.md formula\ntitle_str = \"line-pca-variance-cumulative · python · plotnine · anyplot.ai\"\nn = len(title_str)\nratio = 67 / n if n > 67 else 1.0\ntitle_fontsize = max(8, round(12 * ratio))\n\n# Plot\nplot = (\n    ggplot(df, aes(x=\"component\", y=\"cumulative\"))\n    # Threshold dashed reference lines (structural chrome — INK_SOFT)\n    + geom_hline(yintercept=90.0, linetype=\"dashed\", color=INK_SOFT, size=0.5, alpha=0.6)\n    + geom_hline(yintercept=95.0, linetype=\"dashed\", color=INK_SOFT, size=0.5, alpha=0.6)\n    + geom_hline(yintercept=99.0, linetype=\"dashed\", color=INK_SOFT, size=0.5, alpha=0.6)\n    # Individual variance as translucent bars — contextual background layer\n    + geom_col(aes(y=\"individual\"), fill=BRAND, width=0.5, alpha=0.15, show_legend=False)\n    # Vertical drop-line from elbow to x-axis\n    + geom_segment(\n        data=elbow_df,\n        mapping=aes(x=\"component\", xend=\"component\", y=0, yend=\"cumulative\"),\n        linetype=\"dotted\",\n        color=IMPRINT_RED,\n        size=0.6,\n        alpha=0.6,\n    )\n    # Main cumulative variance line\n    + geom_line(color=BRAND, size=1.0)\n    # Data point markers — PAGE_BG fill for theme-adaptive white circles\n    + geom_point(color=BRAND, size=2.5, fill=PAGE_BG, stroke=1.2, shape=\"o\")\n    # Highlighted elbow point\n    + geom_point(\n        data=elbow_df,\n        mapping=aes(x=\"component\", y=\"cumulative\"),\n        color=IMPRINT_RED,\n        size=5.0,\n        fill=IMPRINT_RED,\n        stroke=1.5,\n        shape=\"o\",\n        alpha=0.9,\n    )\n    # Elbow annotation\n    + geom_text(\n        data=elbow_df,\n        mapping=aes(x=\"component\", y=\"cumulative\", label=\"label\"),\n        ha=\"left\",\n        va=\"bottom\",\n        size=3.0,\n        color=IMPRINT_RED,\n        fontweight=\"bold\",\n        nudge_x=0.4,\n        nudge_y=2.5,\n    )\n    # Threshold labels\n    + geom_text(\n        data=thresholds,\n        mapping=aes(x=\"x\", y=\"y\", label=\"label\"),\n        ha=\"right\",\n        va=\"bottom\",\n        size=2.5,\n        color=INK_MUTED,\n        nudge_y=0.5,\n    )\n    # Scales\n    + scale_x_continuous(breaks=n_components, labels=[str(i) for i in n_components], expand=(0.02, 0.4))\n    + scale_y_continuous(\n        limits=(0, 102), breaks=[0, 20, 40, 60, 80, 100], labels=[\"0%\", \"20%\", \"40%\", \"60%\", \"80%\", \"100%\"]\n    )\n    + labs(x=\"Number of Principal Components\", y=\"Cumulative Explained Variance (%)\", title=title_str)\n    + theme_minimal()\n    + theme(\n        figure_size=(8, 4.5),\n        text=element_text(size=7, color=INK_SOFT),\n        axis_title=element_text(size=10, color=INK),\n        axis_text=element_text(size=8, color=INK_SOFT),\n        plot_title=element_text(size=title_fontsize, color=INK, ha=\"left\"),\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n        panel_grid_major_y=element_line(color=INK, size=0.3, alpha=0.12),\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_border=element_rect(color=INK_SOFT, fill=None),\n        axis_line_x=element_line(color=INK_SOFT, size=0.4),\n        axis_ticks_major_x=element_line(color=INK_SOFT, size=0.3),\n        plot_margin=0.02,\n    )\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=400, width=8, height=4.5, units=\"in\", verbose=False)\n"}