Conversation
The base of the forecasting transformers takes pandas and polars dataframes. With pandas the index keeps ordering the rows in time; with polars the rows are used in the order given, sort_index does not apply and freq raises an error. The base now provides transform() and transform_x_y() on top of an _add_features() hook for the subclasses. Also sets AGENTS.md's priorities to speed, readability and simplicity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
WindowFeatures takes pandas and polars dataframes. With pandas it keeps rolling on the index, including time-span windows, freq and all rolling functions; it now calls the rolling methods instead of agg(), which is faster with many variables. With polars the rows are used in the order given, windows are numbers of rows, and mean, sum, std, var and count use narwhals, while min, max, median, skew and kurt use polars expressions. Time-span windows, other functions and min_periods=0 raise a clear error with polars. Also stops return_empty=True from failing with lists of windows or functions when there are no numerical variables. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #1065 (time series base). Until #1065 is merged, this diff also shows its commit; the WindowFeatures change is the last commit.
Summary
WindowFeaturestakes pandas and polars dataframes._add_features(nw_X).transform()keeps its docstring and callssuper().transform(X), and the temporary.to_native()from Migrate BaseForecastTransformer to narwhals, add polars support #1065 is gone.drop_original,drop_naandtransform_x_ycome from the base."3D",freq,min_periods(passed torolling(), as in Pass min_periods to rolling() in WindowFeatures #1043) and every rolling function. It now calls the rolling methods (rolling.mean(), ...) instead ofrolling.agg(functions), which is faster with many variables (numbers below), and the output is identical.windowis a number of rows and the features are shifted byperiodsrows, as with pandas.mean,sum,std,varuse narwhals' rolling expressions withmin_samples;countis a narwhals rolling sum of the non-null mask.min,max,median,skew,kurtuse polars expressions (rolling_min, ...rolling_skew(bias=False),rolling_kurtosis(bias=False)), because narwhals has no such expressions and polars beat numpy by a wide margin. std/var use ddof=1, andmin_periods=Nonemeans the full window, both as in pandas._check_index(X)callssuper()._check_index(X). Then, when the input isn't pandas, it raisesNotImplementedErrorin the same style as the base'sfreqmessage for:sem,first,last,nunique,rank, ...), with the list of the supported ones;min_periods=0, which narwhals rejects and which would give different sums on all-null windows.Benchmarks
Median times in ms. The machine was heavily loaded by other jobs (load average about 40), so the ratios are noisy. Where they differ, the direction was the same in every run.
pandas, whole
transform(): base ref (rolling().agg()) vs this PR (rolling methods). The base ref'stransform()ran in the same process, alternating with the new one:pandas
rolling().agg()vs the rolling methods alone, on the rolling step only, with 3 functions: 10k x 10: 23.3 vs 10.5; 100k x 10: 98.0 vs 74.0; 500k x 10: 470 vs 411. The same step through narwhals' rolling expressions on pandas was about as fast as the methods (100k x 10 mean+std: pandas agg 92.6, narwhals 82.6). Narwhals can't do time spans,freqor min/max/median, so pandas keeps its own path.polars, functions narwhals lacks (min/max/median), including
shift:Polars won or tied everywhere except
window=3with 1 variable. There the shifts version was a little faster, but it scales with the window size.polars, narwhals + polars expressions (this PR) vs all polars expressions in one
with_columns:See "Needs decision" 2.
polars, whole
transform()(this PR): 500k x 10, w=[3,7,14] mean,std,max: 98 ms; 2M x 10: 415 ms; 500k x 10, w=[3,7] median,min: 81.5 ms.Behaviour
assert_frame_equal, exact, plus column index dtype) in 375 of 377 recorded cases. The cases cover windows (int, list, time spans), functions (mean; mean+std; all 15 rolling functions),min_periodsNone/1/2,periods,freq,drop_original,drop_na,sort_indexon shuffled rows,transform_x_y, integer column names, NaN in the data, variable subsets andreturn_empty. The 2 differences:return_empty=Truewith no numerical variables and a list of windows or functions used to raiseValueError: No objects to concatenate. It now returns the dataframe unchanged, asreturn_emptydocuments. This is a bug fix; the test fails on the base ref."pizza"still raisesAttributeError, but the message is now pandas''Rolling' object has no attribute 'pizza'instead of'pizza' is not a valid function for 'Rolling' object."mean"and all 10 supported functions,min_periodsNone/0/1/2,periods1/3,drop_original,drop_na, missing data, and shuffled rows. The rest:min_periods=0, which raises on polars on purpose.skewwith missing data. After a window with fewer than 3 values, pandas 3.0.3's rollingskewreturns NaN for the rest of the series. polars matchesscipy.stats.skew(bias=False), so this is a pandas bug.sum/min/maxof an integer column stay integers, while pandas returns floats. The values are the same.NaN(not null) is a value in polars, so it propagates through the windows. pandas treats NaN as missing. This only matters withmissing_values="ignore", because the NaN check catches it otherwise.Tests
tests/test_time_series/test_forecasting/test_window_features.pyis rewritten to the conventions:# init parameters: one test per error message, with wrong values and types, andtest_init_param_assignment.# fit and transform:make_dftests on both backends, with plain-dict data and explicit expected values. They cover every polars-supported function,periods,min_periods(including the Pass min_periods to rolling() in WindowFeatures #1043 cases), missing data,drop_original,drop_na,transform_x_ywithmake_series,return_empty, andget_feature_names_outand its errors.freq, time-span windows, pandas-only functions,sort_index,yaligned on the index, and integer column names.drop_original/drop_nainit-error tests were removed becausetest_base_forecast_transformer.pycovers them.The old test file still passes against the new code (36/36).
tests/test_time_series: base ref 189 passed, 0 failed; this PR 230 passed, 0 failed. No other test folder imports WindowFeatures.flake8 feature_engine testsis clean, andmypy feature_engineshows the same 2 errors as the base ref.Needs decision
min_samples=, which polars 1.21 introduced (before that it wasmin_periods).rolling_skewandrolling_kurtosisare marked unstable in polars, androlling_kurtosisis recent. Thetestsextra sayspolars>=1.0.0. narwhals handles this for mean/sum/std/var but not for these five. The options are:min_periodsormin_samplesdepending on the polars version;with_columnsof polars expressions was up to about 1.5x faster, and it was equal with 10 variables. It would also remove the reorderselect. Should I switch?_check_indexnow validateswindow,functionsandmin_periodsfor non-pandas input, because it is the one hook the base calls in bothfitandtransformwith the native X. The name no longer fits. A base change could rename it (for example to_check_input).Pre-existing issues, not fixed
windowandmin_periodsaren't validated at init. For example,window=0ormin_periods > windowraise pandas' or polars' own errors at transform.functions="corr"or"cov"return pairwise rolling results, which duplicates the rows (same as before)._get_new_features_name's docstring says "lag features".