Skip to content

Missing

missing

Missing-indicator discovery. 'no_evidence' semantics live in bases.transform.

discover_missing_indicators

discover_missing_indicators(X: DataFrame, y: ndarray, task: str, min_support: int, fdr_alpha: float) -> list[MissingIndicatorBasis]

One candidate per feature; BH across features (one test each).

Source code in src/flaggam/missing.py
def discover_missing_indicators(
    X: pd.DataFrame, y: np.ndarray, task: str, min_support: int, fdr_alpha: float
) -> list[MissingIndicatorBasis]:
    """One candidate per feature; BH across features (one test each)."""
    candidates: list[tuple[str, int, float]] = []
    for col in X.columns:
        miss = X[col].isna().to_numpy()
        n_miss = int(miss.sum())
        if n_miss < min_support or (len(miss) - n_miss) < min_support:
            continue
        if task == "binary":
            k1, k0 = int(y[miss].sum()), int(y[~miss].sum())
            p = two_proportion_test(k1, n_miss, k0, len(miss) - n_miss)
        else:
            p = chi_square_test(y[miss], y[~miss])
        candidates.append((col, n_miss, p))
    if not candidates:
        return []
    p_adj = bh_adjust(np.array([c[2] for c in candidates]))
    out = []
    for (col, n_miss, p), pa in zip(candidates, p_adj, strict=False):
        if pa <= fdr_alpha:
            out.append(
                MissingIndicatorBasis(
                    feature=col,
                    support=n_miss,
                    effect_size=float("nan"),
                    p_value=p,
                    p_adj=float(pa),
                    enriched_class=None,
                )
            )
    return out