column
Column-based trial inclusion filter.
Module
Functions
normalize_column_name
def normalize_column_name(name: str) ‑> str:Normalize a column name for case/space-insensitive comparison.
Lower-cases and strips spaces so "totalgaarea" matches "Total GA Area".
The single source of truth for how a column name is resolved — matched_column
(and grain resolution in criteria_matching.functions) call this so they
cannot drift apart.
Arguments
name: The raw column name.
Returns The normalized name.
resolve_column
def resolve_column(name: str, columns: typing.Iterable[str]) ‑> str | None:Resolve name to the actual column in columns, case/space-insensitively.
Prefers an exact match (fast path), then falls back to a normalized match via
normalize_column_name so "totalgaarea" resolves "Total GA Area". This is
the shared resolution both ColumnFilter and MethodFilter use so that a
criterion whose configured column name differs only in casing/spacing from the
produced frame column reads the right cell instead of treating it as missing.
Arguments
name: The column name to resolve (e.g. from acolumn_criteriaentry).columns: The actual column names to resolve against (a frame's columns or a row's index).
Returns
The matching column name from columns, or None if none matches.
Classes
ColumnFilter
class ColumnFilter( column: str, operator: str, value: str | int | float | list[str | int | float], how: PartialMatchingType = 'all', config_field: str | None = None, output_field: str | None = None, grain: CriterionGrain = scan, family: CriterionFamily | None = None, tree_node_id: str | None = None,):Dataclass for basic single column filtering.
Arguments
column: The column name on which the filter will be applied.operator: The operator for the filtering operation.value: The value for the filter.how: Partial matching type ("any" or "all").config_field: OriginatingCriteriaMatchConfigfield name, orNoneif this filter was not built from a config (e.g. constructed directly in a test).output_field: Logical field name this filter's outcome is reported under (typically the filter'scolumn), orNoneif unset.grain: Whether this filter is evaluated perscanor perpatient. Defaults toCriterionGrain.SCAN. This is the grain (cardinality) axis, not provenance — a criterion's data source is resolved from its column inbuild_criterion_outcomes, not set here.family: The semantic criterion family this filter belongs to (seeCriterionFamily), declared by the build site inbuild_eligibility_filters. Pod-internal: a task config authoring aColumnFilterby hand leaves it unset, which is why it is optional rather than required.Nonetherefore means "not built bybuild_eligibility_filters", and the served criterion reports no family.tree_node_id: Thecriteria_treeleaf id this filter was built from, orNonefor a filter not built from a tree leaf. Stamped onto the resultingCriterionOutcomebybuild_criterion_outcomes.
A ColumnFilter is one declarative, self-describing scalar comparison: a single column compared against a scalar value (or, for in/not in, a value-set) with an operator, evaluated vectorized over the column. Use it whenever the criterion is a single-column scalar comparison. For anything that is not — multi-column rules, list/collection-valued cells, glob/regex matching — use a MethodFilter instead. A produced CriterionOutcome from a ColumnFilter carries kind="column".
Variables
- static
column : str
- static
config_field : str | None
- static
family : CriterionFamily | None
- static
grain : CriterionGrain
- static
how : Literal['any', 'all']
- static
operator : str
- static
output_field : str | None
- static
tree_node_id : str | None
- static
value : str | int | float | list[str | int | float]
identifier : str- Identifying string for this filter to use in logs.
Methods
apply_filter
def apply_filter( self, df: pd.DataFrame, rename_columns: typing.Mapping[str, str] | None = None,) ‑> pandas.core.frame.DataFrame:Apply self filter to a dataframe.
evaluate_row
def evaluate_row( self, row: pd.Series, matched: str | None,) ‑> CriterionOutcome:Evaluate this filter against one row, returning a structured outcome.
Self-contained: computes pass/fail directly from the operator (mirroring
apply_filter's op(value) & notnull), so it does not depend on
apply_filter having written any column. An absent target column or a
NaN value yields unknown; absent_column distinguishes the two so
the regenerated "not found" reason can render the raw column name
(absent) rather than its display rename (present but NaN), matching
apply_filter.
Arguments
row: The df row.matched: The resolved df column (frommatched_column), orNone.
Returns
The CriterionOutcome for this filter on this row.
matched_column
def matched_column(self, df: pd.DataFrame) ‑> str | None:Resolve the actual df column this filter targets, or None.
Matching is case- and space-insensitive (e.g. "totalgaarea" matches
"Total GA Area"), mirroring the resolution apply_filter performs.
Arguments
df: The DataFrame whose columns are searched.
Returns
The matching column name, or None if no column matches.
result_column
def result_column(self, matched: str) ‑> str:The per-filter boolean column name apply_filter writes.
Arguments
matched: The resolved df column name (frommatched_column).
Returns The column name holding this filter's per-row pass/fail bool.