Skip to content

feat(base): migrate MiniBatch* class signatures to narwhals-agnostic types - #1989

Open
tiyaagarwal wants to merge 4 commits into
online-ml:mainfrom
tiyaagarwal:feat/narwhals-base-minibatch-signatures
Open

feat(base): migrate MiniBatch* class signatures to narwhals-agnostic types#1989
tiyaagarwal wants to merge 4 commits into
online-ml:mainfrom
tiyaagarwal:feat/narwhals-base-minibatch-signatures

Conversation

@tiyaagarwal

Copy link
Copy Markdown

Summary

Addresses the base-class items from #1919:

  • base/classifier.pyMiniBatchClassifier
  • base/regressor.pyMiniBatchRegressor
  • base/transformer.pyMiniBatchTransformer and MiniBatchSupervisedTransformer

Changes

  • Replace pd.DataFrame / pd.Series parameter and return type hints with IntoDataFrame / IntoSeries from narwhals.stable.v2.typing across all four mini-batch base classes.
  • Remove the import pandas as pd guard inside TYPE_CHECKING blocks; replace with the narwhals typing imports.
  • Rewrite the MiniBatchClassifier.predict_many default body so it no longer relies on pandas-only .empty / .idxmax(axis="columns"): it now wraps the output of predict_proba_many with narwhals, extracts a numpy argmax, and rebuilds the result through to_native_series — matching the backend (and pandas index) of the input X.
  • Update all affected docstrings to mention that any narwhals-supported eager backend (pandas, polars, PyArrow, etc.) is accepted.

Approach

Follows the same narwhals pattern introduced in #1900 and used across linear_model, preprocessing, anomaly, etc.

Testing

uvx ruff check river/base/classifier.py river/base/regressor.py river/base/transformer.py

All checks passed.

Closes part of #1919 (base class items).

🤖 Generated with Claude Code

Update MiniBatchClassifier, MiniBatchRegressor, MiniBatchTransformer,
and MiniBatchSupervisedTransformer to accept any narwhals-supported
eager backend (pandas, polars, PyArrow, etc.) in place of the
previously hard-coded pd.DataFrame / pd.Series type hints.

- Replace `pd.DataFrame` / `pd.Series` parameter and return annotations
  with `IntoDataFrame` / `IntoSeries` from narwhals.stable.v2.typing
- Rewrite MiniBatchClassifier.predict_many default body with narwhals
  so it no longer calls pandas-only .empty / .idxmax(axis="columns")
- Update all docstrings to note backend-agnostic support

Part of online-ml#1919.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codspeed-hq

codspeed-hq Bot commented Aug 24, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 98 untouched benchmarks
⏩ 16 skipped benchmarks1


Comparing tiyaagarwal:feat/narwhals-base-minibatch-signatures (9f323b2) with main (64285b9)

Open in CodSpeed

Footnotes

  1. 16 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

tiyaagarwal and others added 3 commits August 24, 2026 18:35
…migration

- Remove `from river.utils.dataframe import to_native_series` from the
  `MiniBatchClassifier.predict_many` body: `river.base -> river.utils`
  is not an allowed dependency edge (breaks the lint-imports DAG contract).
  Replace with inline narwhals calls (nw.get_native_namespace / nw.new_series).

- Use native-frame columns instead of narwhals `.columns` for label lookup so
  non-string class labels (e.g. integer class IDs in GaussianNB) are preserved
  in the output Series without dtype coercion to object.

- Guard the empty-frame path against both 0 rows and 0 columns: an untrained
  classifier returns a DataFrame with N rows but 0 class columns, which caused
  `arr.argmax(axis=1)` to raise ValueError on an empty sequence.

- Remove typing.cast() calls flagged by mypy as redundant.

- Guard `compose/union.py` MiniBatchSupervisedTransformer.learn_many call
  with `y is not None` so mypy does not flag the NativeSeries | None → NativeSeries
  argument mismatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- When predict_proba_many returns an empty frame (no classes seen yet,
  e.g. untrained model), return proba_native directly instead of building
  a new empty series. This preserves the caller's backend, index, and the
  expected DataFrame shape that test_learn_many_not_fit asserts.

- Add typing.cast() around the .to_native() call so mypy does not flag
  [no-any-return]; .to_native() is typed as Any in narwhals stubs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant