{"spec_id":"logistic-regression","library":"plotnine","language":"python","code":"\"\"\" anyplot.ai\nlogistic-regression: Logistic Regression Curve Plot\nLibrary: plotnine 0.15.4 | Python 3.13.13\nQuality: 94/100 | Updated: 2026-05-18\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nimport statsmodels.api as sm\nfrom plotnine import (\n    aes,\n    element_line,\n    element_rect,\n    element_text,\n    geom_hline,\n    geom_line,\n    geom_point,\n    geom_ribbon,\n    ggplot,\n    labs,\n    position_jitter,\n    scale_color_manual,\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# imprint semantic anchors\nFAIL_COLOR = \"#AE3030\"  # imprint red - fail\nPASS_COLOR = \"#009E73\"  # imprint green - pass\nCURVE_COLOR = \"#4467A3\"  # imprint blue - regression curve\n\n# Data - Exam score vs Pass/Fail outcome\nnp.random.seed(42)\nn_samples = 150\n\n# Generate exam scores with different distributions for pass/fail\nscores_fail = np.random.normal(45, 12, 60)  # Lower scores tend to fail\nscores_pass = np.random.normal(70, 10, 90)  # Higher scores tend to pass\nscores = np.concatenate([scores_fail, scores_pass])\noutcomes = np.concatenate([np.zeros(60), np.ones(90)])\n\n# Add some noise to outcomes for realism\nflip_indices = np.random.choice(n_samples, size=15, replace=False)\noutcomes[flip_indices] = 1 - outcomes[flip_indices]\n\n# Clip scores to reasonable range\nscores = np.clip(scores, 20, 100)\n\n# Fit logistic regression using statsmodels\nX = sm.add_constant(scores)\nmodel = sm.Logit(outcomes, X).fit(disp=0)\n\n# Create smooth curve for predictions with confidence intervals\nx_curve = np.linspace(20, 100, 200)\nX_curve = sm.add_constant(x_curve)\npredictions = model.get_prediction(X_curve)\ny_pred = predictions.predicted\nconf_int = predictions.conf_int(alpha=0.05)\ny_lower = conf_int[:, 0]\ny_upper = conf_int[:, 1]\n\n# Create dataframes\ndf_points = pd.DataFrame(\n    {\"score\": scores, \"outcome\": outcomes, \"class\": [\"Fail\" if o == 0 else \"Pass\" for o in outcomes]}\n)\n\ndf_curve = pd.DataFrame({\"score\": x_curve, \"probability\": y_pred, \"lower\": y_lower, \"upper\": y_upper})\n\n# Theme\nanyplot_theme = 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),\n    panel_grid_major=element_line(color=INK, size=0.3, alpha=0.08),\n    panel_grid_minor=element_line(color=INK, size=0.2, alpha=0.04),\n    panel_border=element_rect(color=INK_SOFT, fill=None, size=0.5),\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    plot_title=element_text(size=24, color=INK),\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=18, color=INK),\n)\n\n# Create plot\nplot = (\n    ggplot()\n    # Confidence interval ribbon\n    + geom_ribbon(data=df_curve, mapping=aes(x=\"score\", ymin=\"lower\", ymax=\"upper\"), alpha=0.25, fill=CURVE_COLOR)\n    # Fitted logistic curve\n    + geom_line(data=df_curve, mapping=aes(x=\"score\", y=\"probability\"), color=CURVE_COLOR, size=2)\n    # Decision threshold line at p=0.5\n    + geom_hline(yintercept=0.5, linetype=\"dashed\", color=INK_SOFT, size=1, alpha=0.6)\n    # Data points with jitter\n    + geom_point(\n        data=df_points,\n        mapping=aes(x=\"score\", y=\"outcome\", color=\"class\"),\n        size=4,\n        alpha=0.6,\n        position=position_jitter(width=0, height=0.03),\n    )\n    # Colors\n    + scale_color_manual(values={\"Fail\": FAIL_COLOR, \"Pass\": PASS_COLOR})\n    # Labels\n    + labs(\n        title=\"logistic-regression · python · plotnine · anyplot.ai\",\n        x=\"Exam Score (points)\",\n        y=\"Probability of Passing\",\n        color=\"Outcome\",\n    )\n    + theme_minimal()\n    + anyplot_theme\n)\n\n# Save\nplot.save(f\"plot-{THEME}.png\", dpi=300)\n"}