# ROC Curve Analysis

The **ROC (Receiver Operating Characteristic) Curve** evaluates how well a continuous score discriminates between two binary classes across all possible decision thresholds. The **Area Under the Curve (AUC)** summarises overall discriminative performance in a single number.

---

## 📌 When to Use
- A continuous score (biomarker, probability, test result) should be evaluated as a binary classifier
- You want to find the best cut-off threshold
- Comparing the discriminative ability of different predictors for the same outcome

> ✅ No normality assumption — the ROC is rank-based and distribution-free.

---

## 📐 Method

At each threshold $t$, the score is dichotomised into predicted positive/negative:

$$\text{Sensitivity}(t) = \frac{TP}{TP + FN} \qquad \text{Specificity}(t) = \frac{TN}{TN + FP}$$

The curve plots **Sensitivity** (y-axis) vs **1 – Specificity** (x-axis) as $t$ sweeps from high to low.

### AUC
$$AUC = \int_0^1 \text{TPR}(FPR) \, d(FPR)$$

- **AUC = 0.5**: no discrimination (diagonal line, chance)
- **AUC = 1.0**: perfect discrimination
- **AUC < 0.5**: predictions are inverted (swap direction of the score)

### 95% Confidence Interval
Computed using the **Hanley–McNeil formula**:

$$SE_{AUC} = \sqrt{\frac{AUC(1-AUC) + (n_1-1)(Q_1-AUC^2) + (n_0-1)(Q_2-AUC^2)}{n_0 \cdot n_1}}$$

where $Q_1 = AUC / (2 - AUC)$ and $Q_2 = 2AUC^2 / (1 + AUC)$.

### P-value
Tests $H_0$: AUC = 0.5 (no discrimination):

$$z = \frac{AUC - 0.5}{SE_{AUC}}$$

---

## 🔬 What StatInsight Reports
- ROC curve plot with the chance diagonal
- AUC with 95% CI and p-value
- Optimal threshold via **Youden's J** (maximises sensitivity + specificity − 1)
- At the optimal threshold: Sensitivity, Specificity, PPV (Precision), NPV, Accuracy
- N total, N positive, N negative

---

## 🧩 Optimal Threshold (Youden's J)

$$J = \text{Sensitivity} + \text{Specificity} - 1 = TPR - FPR$$

The threshold that maximises $J$ provides the best trade-off between sensitivity and specificity. This point is marked on the curve with a diamond marker.

---

## 🧪 Assumptions
- Continuous (or ordinal) predictor score
- Binary outcome with exactly 2 classes
- Independent observations
- No normality assumption ✅

---

## 🧠 Interpretation

| AUC range | Discrimination |
|-----------|----------------|
| ≥ 0.90 | Excellent |
| 0.80 – 0.89 | Good |
| 0.70 – 0.79 | Acceptable |
| 0.60 – 0.69 | Poor |
| < 0.60 | No useful discrimination |

- **PPV (Positive Predictive Value)**: of all predicted positives, what fraction are truly positive — depends heavily on prevalence
- **NPV (Negative Predictive Value)**: of all predicted negatives, what fraction are truly negative
- **Youden's J = 0**: the threshold does nothing; **J = 1**: perfect separation at that cut-off

---

## 🐍 Python Implementation

```python
from sklearn.metrics import roc_curve, roc_auc_score
import numpy as np

fpr, tpr, thresholds = roc_curve(y_true, y_score)
auc = roc_auc_score(y_true, y_score)

# Optimal threshold (Youden's J)
youden_j = tpr - fpr
optimal_idx = np.argmax(youden_j)
optimal_threshold = thresholds[optimal_idx]
```

---

## 📎 Related Tests

[Multiple Logistic Regression](../regression/logistic.md) — model that produces predicted probabilities suitable as ROC input

[Kaplan–Meier Survival Analysis](../survival/kaplan-meier.md) — time-to-event analysis with binary event

[Automatic Predictor Selection](../predictors/auto-predictor-selection.md) — ranks predictors by AUC when the outcome is binary
