pola-rs/polars · error

not implemented

Error message

not implemented

What it means

The grouped asof-join implementation (join_asof with by= groups) only implements the Backward and Forward strategies; AsofStrategy::Nearest reaches unimplemented!(). Ungrouped asof joins do support nearest, but the per-group state machines for it were never written.

Source

Thrown at crates/polars-ops/src/frame/join/asof/groups.rs:356

    left_by: &mut DataFrame,
    right_by: &mut DataFrame,
    strategy: AsofStrategy,
    allow_eq: bool,
) -> PolarsResult<IdxArr>
where
    for<'a> T::Physical<'a>: TotalOrd,
{
    let right_asof = left_asof.unpack_series_matching_type(right_asof)?;

    let filter = |_a: T::Physical<'_>, _b: T::Physical<'_>| true;
    match strategy {
        AsofStrategy::Backward => dispatch_join_by_type::<T, AsofJoinBackwardState, _>(
            left_asof, right_asof, left_by, right_by, filter, allow_eq,
        ),
        AsofStrategy::Forward => dispatch_join_by_type::<T, AsofJoinForwardState, _>(
            left_asof, right_asof, left_by, right_by, filter, allow_eq,
        ),
        AsofStrategy::Nearest => unimplemented!(),
    }
}

#[allow(clippy::too_many_arguments)]
fn dispatch_join_strategy_numeric<T: PolarsNumericType>(
    left_asof: &ChunkedArray<T>,
    right_asof: &Series,
    left_by: &mut DataFrame,
    right_by: &mut DataFrame,
    strategy: AsofStrategy,
    tolerance: Option<AnyValue<'static>>,
    allow_eq: bool,
) -> PolarsResult<IdxArr> {
    let right_ca = left_asof.unpack_series_matching_type(right_asof)?;

    if let Some(tol) = tolerance {
        let native_tolerance: T::Native = tol.try_extract()?;
        let abs_tolerance = native_tolerance.abs_diff(T::Native::zero());

View on GitHub (pinned to df599052da)

Solutions

  1. Drop the by= argument (sort both frames on the asof key, plus groups if acceptable) so the non-grouped nearest implementation is used
  2. Use strategy='backward' or 'forward' with a tolerance, which are implemented for grouped asof
  3. Emulate nearest per group: for each group slice, run join_asof twice (backward and forward) and pick the closer match, or use search_sorted on the sorted right keys

Example fix

# before
out = left.join_asof(right, on="ts", by="id", strategy="nearest")  # panics

# after (implemented path)
out = left.sort("ts").join_asof(
    right.sort("ts"), on="ts", by="id", strategy="backward"
)
Defensive patterns

Strategy: validation

Validate before calling

def grouped_asof_supported(strategy: str, by: list[str] | None) -> bool:
    return not (by and strategy == "nearest")

Type guard

def grouped_asof_supported(strategy: str, by: list[str] | None) -> bool:
    return not (by and strategy == "nearest")

Prevention

When it happens

Trigger: df.join_asof(other, on="ts", by=["id"], strategy="nearest") - an asof join with both the by parameter and strategy='nearest'.

Common situations: Time-series lookups per entity (sensor per device, quotes per symbol) where the user wants the closest timestamp in each group; code that worked without by= and later added grouping columns.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/3ffd6010d97e3c3c. Report an issue: GitHub.