{"spec_id":"logistic-regression","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nlogistic-regression: Logistic Regression Curve Plot\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-18\n\"\"\"\n\nimport os\nimport sys\n\n\nsys.path = [p for p in sys.path if \"implementations\" not in p]\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom sklearn.linear_model import LogisticRegression\nfrom sklearn.metrics import accuracy_score\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 (first series is brand green)\nBRAND = \"#009E73\"\nSECONDARY = \"#C475FD\"\n\n# Data - Credit risk scoring: probability of loan approval based on credit score\nnp.random.seed(42)\nn_points = 200\n\n# Generate credit scores (300-850 range, typical credit score range)\ncredit_scores = np.concatenate([np.random.normal(550, 80, n_points // 2), np.random.normal(700, 60, n_points // 2)])\ncredit_scores = np.clip(credit_scores, 300, 850)\n\n# Generate binary outcomes with logistic probability\ntrue_probs = 1 / (1 + np.exp(-0.02 * (credit_scores - 620)))\ny = (np.random.random(n_points) < true_probs).astype(int)\n\n# Fit logistic regression model\nX = credit_scores.reshape(-1, 1)\nmodel = LogisticRegression()\nmodel.fit(X, y)\n\n# Generate smooth curve for predictions\nx_curve = np.linspace(300, 850, 300)\ny_probs = model.predict_proba(x_curve.reshape(-1, 1))[:, 1]\n\n# Calculate confidence intervals (using standard error approximation)\np = y_probs\nse = np.sqrt(p * (1 - p) / n_points) * 2\nci_lower = np.clip(y_probs - 1.96 * se, 0, 1)\nci_upper = np.clip(y_probs + 1.96 * se, 0, 1)\n\n# Calculate accuracy\ny_pred = model.predict(X)\naccuracy = accuracy_score(y, y_pred)\n\n# Jitter y values for visibility\ny_jittered = y + np.random.uniform(-0.03, 0.03, n_points)\n\n# Plot\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Confidence interval band\nax.fill_between(x_curve, ci_lower, ci_upper, alpha=0.25, color=BRAND, label=\"95% CI\")\n\n# Logistic curve\nax.plot(x_curve, y_probs, color=BRAND, linewidth=3.5, label=\"Logistic Fit\", zorder=3)\n\n# Decision threshold line\nax.axhline(y=0.5, color=INK_SOFT, linestyle=\"--\", linewidth=2, label=\"Decision Threshold (0.5)\")\n\n# Data points - class 0 (rejected)\nmask_0 = y == 0\nax.scatter(\n    credit_scores[mask_0],\n    y_jittered[mask_0],\n    s=120,\n    alpha=0.6,\n    color=SECONDARY,\n    label=\"Rejected (0)\",\n    edgecolors=PAGE_BG,\n    linewidth=0.5,\n    zorder=2,\n)\n\n# Data points - class 1 (approved)\nmask_1 = y == 1\nax.scatter(\n    credit_scores[mask_1],\n    y_jittered[mask_1],\n    s=120,\n    alpha=0.6,\n    color=BRAND,\n    label=\"Approved (1)\",\n    edgecolors=PAGE_BG,\n    linewidth=0.5,\n    zorder=2,\n)\n\n# Model annotation with theme-adaptive styling\ncoef = model.coef_[0][0]\nintercept = model.intercept_[0]\nannotation_text = f\"Accuracy: {accuracy:.1%}\\nCoef: {coef:.4f}\\nIntercept: {intercept:.2f}\"\nax.annotate(\n    annotation_text,\n    xy=(0.03, 0.97),\n    xycoords=\"axes fraction\",\n    fontsize=14,\n    color=INK,\n    verticalalignment=\"top\",\n    bbox={\"boxstyle\": \"round,pad=0.5\", \"facecolor\": ELEVATED_BG, \"alpha\": 0.9, \"edgecolor\": INK_SOFT},\n)\n\n# Labels and styling\nax.set_xlabel(\"Credit Score\", fontsize=20, color=INK)\nax.set_ylabel(\"Probability of Approval\", fontsize=20, color=INK)\nax.set_title(\"logistic-regression · python · matplotlib · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK)\nax.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax.set_xlim(300, 850)\nax.set_ylim(-0.08, 1.08)\nax.set_yticks([0, 0.25, 0.5, 0.75, 1.0])\n\n# Spine styling\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nfor s in (\"left\", \"bottom\"):\n    ax.spines[s].set_color(INK_SOFT)\n\n# Grid styling\nax.grid(True, alpha=0.15, linestyle=\"-\", linewidth=0.8, color=INK_SOFT)\nax.set_axisbelow(True)\n\n# Legend styling\nleg = ax.legend(fontsize=16, loc=\"lower right\")\nif leg:\n    leg.get_frame().set_facecolor(ELEVATED_BG)\n    leg.get_frame().set_edgecolor(INK_SOFT)\n    leg.get_frame().set_linewidth(0.8)\n    for text in leg.get_texts():\n        text.set_color(INK_SOFT)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}