{"spec_id":"logistic-regression","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nlogistic-regression: Logistic Regression Curve Plot\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 94/100 | Updated: 2026-05-18\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nfrom matplotlib.lines import Line2D\nfrom matplotlib.patches import Patch\nfrom scipy.special import expit\nfrom sklearn.linear_model import LogisticRegression\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\nCOLOR_CLASS_0 = \"#009E73\"\nCOLOR_CLASS_1 = \"#C475FD\"\n\n# Data\nnp.random.seed(42)\nn_samples = 200\n\nx = np.random.uniform(-3, 3, n_samples)\ntrue_prob = expit(1.5 * x + 0.5)\ny = (np.random.random(n_samples) < true_prob).astype(int)\n\nX_train = x.reshape(-1, 1)\nmodel = LogisticRegression()\nmodel.fit(X_train, y)\n\nx_curve = np.linspace(-3.5, 3.5, 300)\nX_curve = x_curve.reshape(-1, 1)\nprob_curve = model.predict_proba(X_curve)[:, 1]\n\nn_bootstrap = 100\nbootstrap_probs = np.zeros((n_bootstrap, len(x_curve)))\nfor i in range(n_bootstrap):\n    idx = np.random.choice(n_samples, n_samples, replace=True)\n    X_boot = x[idx].reshape(-1, 1)\n    y_boot = y[idx]\n    model_boot = LogisticRegression()\n    model_boot.fit(X_boot, y_boot)\n    bootstrap_probs[i] = model_boot.predict_proba(X_curve)[:, 1]\n\nci_lower = np.percentile(bootstrap_probs, 2.5, axis=0)\nci_upper = np.percentile(bootstrap_probs, 97.5, axis=0)\n\ny_jittered = y + np.random.uniform(-0.05, 0.05, n_samples)\n\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Create plot\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\nax.set_facecolor(PAGE_BG)\n\n# Confidence interval\nax.fill_between(x_curve, ci_lower, ci_upper, alpha=0.25, color=COLOR_CLASS_0)\n\n# Logistic curve\nax.plot(x_curve, prob_curve, color=COLOR_CLASS_0, linewidth=3, zorder=5)\n\n# Data points\nclass_0_mask = y == 0\nclass_1_mask = y == 1\n\nax.scatter(\n    x[class_0_mask],\n    y_jittered[class_0_mask],\n    s=150,\n    alpha=0.6,\n    color=COLOR_CLASS_0,\n    edgecolors=PAGE_BG,\n    linewidth=0.5,\n    zorder=4,\n)\nax.scatter(\n    x[class_1_mask],\n    y_jittered[class_1_mask],\n    s=150,\n    alpha=0.6,\n    color=COLOR_CLASS_1,\n    edgecolors=PAGE_BG,\n    linewidth=0.5,\n    zorder=4,\n)\n\n# Decision threshold line\nax.axhline(y=0.5, color=INK_SOFT, linestyle=\"--\", linewidth=2, zorder=3)\n\n# Legend\nlegend_elements = [\n    Line2D([0], [0], color=COLOR_CLASS_0, linewidth=3, label=\"Logistic Curve\"),\n    Patch(facecolor=COLOR_CLASS_0, alpha=0.25, label=\"95% CI\"),\n    Line2D([0], [0], color=INK_SOFT, linestyle=\"--\", linewidth=2, label=\"Decision Threshold (p=0.5)\"),\n    Line2D(\n        [0],\n        [0],\n        marker=\"o\",\n        color=\"w\",\n        markerfacecolor=COLOR_CLASS_0,\n        markersize=12,\n        label=\"Class 0\",\n        markeredgecolor=PAGE_BG,\n        markeredgewidth=0.5,\n    ),\n    Line2D(\n        [0],\n        [0],\n        marker=\"o\",\n        color=\"w\",\n        markerfacecolor=COLOR_CLASS_1,\n        markersize=12,\n        label=\"Class 1\",\n        markeredgecolor=PAGE_BG,\n        markeredgewidth=0.5,\n    ),\n]\nax.legend(handles=legend_elements, fontsize=16, loc=\"upper left\")\n\n# Model info annotation\naccuracy = model.score(X_train, y)\ncoef = model.coef_[0][0]\nintercept = model.intercept_[0]\nax.annotate(\n    f\"Accuracy: {accuracy:.1%}\\nCoef: {coef:.2f}, Intercept: {intercept:.2f}\",\n    xy=(0.98, 0.02),\n    xycoords=\"axes fraction\",\n    fontsize=14,\n    ha=\"right\",\n    va=\"bottom\",\n    bbox={\"boxstyle\": \"round\", \"facecolor\": ELEVATED_BG, \"edgecolor\": INK_SOFT, \"alpha\": 0.9},\n    color=INK,\n)\n\n# Styling\nax.set_xlabel(\"Predictor Variable (X)\", fontsize=20, color=INK)\nax.set_ylabel(\"Probability\", fontsize=20, color=INK)\nax.set_title(\"logistic-regression · python · seaborn · anyplot.ai\", fontsize=24, color=INK)\nax.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax.set_ylim(-0.1, 1.1)\nax.set_xlim(-3.5, 3.5)\n\n# Remove top and right spines\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\nax.spines[\"left\"].set_color(INK_SOFT)\nax.spines[\"bottom\"].set_color(INK_SOFT)\n\n# Subtle grid\nax.grid(True, alpha=0.10, axis=\"y\", linewidth=0.8)\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}