This package now follows a two-layer execution model for derived variables:
compehndly.polars.kernels
- Polars-native series kernels for external
map_batchesusage. - Contract:
kernel(*series: pl.Series, **params) -> pl.Series
compehndly.polars.adapters
- Frame adapters that apply kernels to:
polars.DataFrame(eager kernel path)polars.LazyFrame(expression path)
External integrations (already have a lazy orchestrator like apply_map):
from compehndly import get_map_fn
map_fn = get_map_fn("summation", all_required=True)For config/YAML path-based loading, use stable wrappers in compehndly.entrypoints:
map_fn: compehndly.entrypoints.summation
# or
map_fn: compehndly.entrypoints.normalize_specific_gravityDirect usage (you want this package to add a derived column):
from compehndly import with_derived_column
out = with_derived_column(
frame=df_or_lf,
function_name="summation",
input_columns=["a", "b"],
output_column="sum_col",
all_required=True,
)
# For non-commutative functions use a named mapping
out = with_derived_column(
frame=df_or_lf,
function_name="normalize_specific_gravity",
input_columns={"measured": "measurement_col", "sg_measured": "sg_col"},
output_column="normalized",
sg_ref=1.024,
)Discover available functions:
from compehndly import list_functions
print(list_functions())Direct series/expression application:
from compehndly import apply
out_series = apply("summation", df["a"], df["b"], all_required=False)
out_expr = apply("summation", pl.col("a"), pl.col("b"), all_required=False)
# Named data kwargs are supported
out_named = apply(
"normalize_specific_gravity",
measured=df["measured"],
sg_measured=df["sg_measured"],
sg_ref=1.024,
)
# Flexible kwargs-only fallback order
out_coalesced = apply(
"coalesce_by_priority",
primary=df["primary"],
secondary=df["secondary"],
fallback=df["fallback"],
priority=("primary", "secondary", "fallback"),
)The pattern is applied to:
derived_variables.summationderived_variables.correctionderived_variables.imputation
Shared test vectors live in:
shared/conformance/derived_variables_cases.json
Python and R should both execute this same file to verify parity. The Python runner is in:
python/tests/test_conformance_shared_vectors.py
Add one module in compehndly.derived_variables and do only:
- Implement one kernel:
def my_kernel(*series: pl.Series, scalar_a: float, ...) -> pl.Series
- Implement one expression builder:
def my_expr(*exprs: pl.Expr, scalar_a: float, ...) -> pl.Expr
Then expose one of:
FUNCTION_SPEC = DerivedFunctionSpec(
name="my_function",
kernel=my_kernel,
expr_builder=my_expr,
)FUNCTION_SPECS = [
DerivedFunctionSpec(...),
DerivedFunctionSpec(...),
]compehndly.api auto-discovers FUNCTION_SPEC / FUNCTION_SPECS, so there
is no central registry file to edit.
No per-function adapter wrappers are required.