Compute precision and recall from binary labels and predictions.
Start with the concrete trace below. It shows the state the algorithm must carry as it runs.
Problem trace
Binary Precision and Recall: Build TP, FP, and FN with elementwise Boolean masks, then divide TP by predicted-positive and actual-positive totals with zero-denominator guards.
| index | label | prediction | cell |
|---|---|---|---|
| 0 | 1 | 1 | TP |
| 1 | 0 | 1 | FP |
| 2 | 1 | 0 | FN |
| 3 | 0 | 0 | TN |
| index | label | prediction | cell |
|---|---|---|---|
| 0 | 1 | 1 | TP |
| 1 | 0 | 1 | FP |
| 2 | 1 | 0 | FN |
| 3 | 0 | 0 | TN |
| index | label | prediction | cell |
|---|---|---|---|
| 0 | 1 | 1 | TP |
| 1 | 0 | 1 | FP |
| 2 | 1 | 0 | FN |
| 3 | 0 | 0 | TN |
| index | label | prediction | cell |
|---|---|---|---|
| 0 | 1 | 1 | TP |
| 1 | 0 | 1 | FP |
| 2 | 1 | 0 | FN |
| 3 | 0 | 0 | TN |
| metric | numerator | denominator meaning | total |
|---|---|---|---|
| precision | TP=1 | TP+FP | 2 |
| recall | TP=1 | TP+FN | 2 |
| metric | guard | division | value |
|---|---|---|---|
| precision | 2 != 0 | 1 / 2 | 0.5 |
| recall | 2 != 0 | 1 / 2 | 0.5 |
- Recognize it
- Use these masks when binary labels and predictions must be reduced into precision and recall, whose denominators answer different conditional questions.
- Keep true
- After each index, TP, FP, and FN equal the counts of their Boolean conjunctions over the processed prefix; TN affects neither precision nor recall numerator or denominator.
- Reuse it
- Define classification metrics as Boolean event counts first, then name each denominator population and guard empty populations before division.
Pattern: Boolean masks and safe division.
Simple idea: Count true positives, false positives, and false negatives with Boolean array operations. Return zero when a denominator is zero.
import numpy as np
def binary_metrics(labels: np.ndarray, predictions: np.ndarray) -> dict[str, float]:
true_positive = int(np.sum((labels == 1) & (predictions == 1)))
false_positive = int(np.sum((labels == 0) & (predictions == 1)))
false_negative = int(np.sum((labels == 1) & (predictions == 0)))
precision_total = true_positive + false_positive
recall_total = true_positive + false_negative
precision = true_positive / precision_total if precision_total else 0.0
recall = true_positive / recall_total if recall_total else 0.0
return {"precision": precision, "recall": recall}
Cost: time and temporary Boolean arrays.