Rare-label pruning

q.label.prune_labels iteratively removes classes below a minimum sample fraction and returns an audit report. Fractions are recomputed after each removal, and min_classes prevents the target from silently collapsing to one class.

Tied rare classes are removed in first-observed order. The function preserves the original event index for all retained labels.

import pandas as pd

import qrt as q

close = q.data.datasets.load("spy")["close"]
close = close.loc[close.index.max() - pd.DateOffset(years=5) :]
volatility = close.pct_change(fill_method=None).ewm(span=20, min_periods=20).std()
events = q.label.cusum_filter(close, volatility.mul(0.5).where(volatility.gt(0)))
outcomes = q.label.fixed_horizon(close, 5, events=events, threshold=0.02)
retained, report = q.label.prune_labels(outcomes["label"], min_fraction=0.20)
report
initial_count initial_fraction final_count final_fraction dropped drop_step
label
0 523 0.664549 523 0.781764 False <NA>
-1 118 0.149936 0 0.0 True 1
1 146 0.185515 146 0.218236 False <NA>

Apply the retained event index

The returned Series is filtered rather than recoded. Use its index to align all event-level features, endpoints, and weights to the same surviving sample.

training_outcomes = outcomes.loc[retained.index].assign(label=retained)
pd.DataFrame({
    "before": outcomes["label"].value_counts().sort_index(),
    "after": training_outcomes["label"].value_counts().sort_index(),
}).fillna(0).astype(int)
before after
label
-1 118 0
0 523 523
1 146 146
Back to top