Run lightweight feature QA checks for notebook discovery loops.
(
X: Sequence[Sequence[float]] | pl.DataFrame,
y: Sequence[float] | None = None,
*,
feature_names: Sequence[str] | None = None,
min_coverage: float = 0.95,
max_corr: float = 0.95,
)
| 707 | ) |
| 708 | corr_abs_max = _max_abs_offdiag(corr) |
| 709 | ortho_corr = _corr_matrix(x_ortho) |
| 710 | ortho_corr_abs_max = _max_abs_offdiag(ortho_corr) |
| 711 | out["orthogonalized"] = { |
| 712 | "pca": ortho, |
| 713 | "mda": ortho_mda, |
| 714 | "max_abs_corr_before": corr_abs_max, |
| 715 | "max_abs_corr_after": ortho_corr_abs_max, |
| 716 | } |
| 717 | |
| 718 | out["comparison_viz_payload"] = viz.prepare_feature_importance_comparison_payload( |
| 719 | left_labels=base_table["feature"].to_list(), |
| 720 | left_values=base_table["mean"].to_list(), |
| 721 | right_labels=ortho_mda["table"]["feature"].to_list(), |
| 722 | right_values=ortho_mda["table"]["mean"].to_list(), |
| 723 | left_name="mda_raw", |
| 724 | right_name="mda_orthogonalized", |
| 725 | ) |
| 726 | |
| 727 | return out |
| 728 | |
| 729 | |
| 730 | def feature_screen_report( |
| 731 | X: Sequence[Sequence[float]] | pl.DataFrame, |
| 732 | y: Sequence[float] | None = None, |
| 733 | *, |
| 734 | feature_names: Sequence[str] | None = None, |
| 735 | min_coverage: float = 0.95, |
| 736 | max_corr: float = 0.95, |
| 737 | ) -> dict[str, object]: |
| 738 | """Run lightweight feature QA checks for notebook discovery loops.""" |
| 739 | if min_coverage <= 0.0 or min_coverage > 1.0: |
| 740 | raise ValueError("min_coverage must be in (0, 1]") |
| 741 | if max_corr <= 0.0 or max_corr >= 1.0: |
| 742 | raise ValueError("max_corr must be in (0, 1)") |
| 743 | |
| 744 | if isinstance(X, pl.DataFrame): |
| 745 | if X.width == 0 or X.height == 0: |
| 746 | raise ValueError("X cannot be empty") |
| 747 | names = list(feature_names) if feature_names is not None else [str(c) for c in X.columns] |
| 748 | if feature_names is not None and len(names) != X.width: |
| 749 | raise ValueError(f"feature_names length mismatch: expected {X.width}, got {len(names)}") |
| 750 | rows = X.select([pl.col(c) for c in X.columns]).rows() |
| 751 | else: |
| 752 | rows = [list(r) for r in X] |
| 753 | if not rows: |
| 754 | raise ValueError("X cannot be empty") |
| 755 | width = len(rows[0]) |
| 756 | if width == 0: |
| 757 | raise ValueError("X must contain at least one feature") |
| 758 | if any(len(r) != width for r in rows): |
| 759 | raise ValueError("X must be rectangular") |
| 760 | names = _feature_names(width, feature_names) |
| 761 | |
| 762 | n_rows = len(rows) |
| 763 | n_features = len(names) |
| 764 | if y is not None: |
| 765 | y_vals = [float(v) for v in y] |
| 766 | if len(y_vals) != n_rows: |
nothing calls this directly
no test coverage detected