Repository navigation
Compute series lengths in row order so predict_df handles categorical item ids - #537
Merged
shchur merged 2 commits intoOct 5, 2026
Merged
Conversation
Contributor
Author
|
Hi @shchur @abdulfatir, a gentle ping on this one when you have a moment. It's a small fix, and I'm happy to adjust anything or rebase if needed. Thanks! |
shchur
approved these changes
Oct 5, 2026
shchur
left a comment
Contributor
There was a problem hiding this comment.
Thank you @nicoloangileri for the fix!
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.
Problem
predict_dfgroups rows by item in first-appearance order (normalize_df) and then slices each series using lengths fromdf[id_column].value_counts(sort=False). Those lengths only match the row blocks for some id dtypes:value_countsfollows the category order (sorted by default inpd.Categorical) and also counts categories that have no rows;string[python]ids, which is [BUG] Cannot infer frequency when id_column has string[python] dtype #440.When the lengths do not match the rows, every series gets the wrong slice. With the frequency inferred, this shows up as a misleading error on regular data. With an explicit
freqthere is no error, and the forecasts are attached to the wrong series and dates:With object ids the same data gives ETH
2278.51from 2026-08-25 and BTC74867.05from 2026-09-24.Change
A new
get_series_lengths(df, id_column)indf_utils.pycounts rows per id withpd.factorize+np.bincount: the same first-appearance ordernormalize_dfgroups by, only ids that have rows, and the lengths always sum tolen(df), whatever the id dtype. It replacesvalue_counts(sort=False)at the seven places that computed series lengths:df_utils.py:infer_freq_from_df,make_future_df, thefuture_dfrow-count check invalidate_df, and the deprecatedconvert_df_input_to_list_of_dicts_input(both branches);base.py:BaseChronosPipeline.predict_df, used by Chronos and Chronos-Bolt;chronos2/preprocess.py:from_data_frame, where a comment stated the ordering assumption.Before and after, with categorical ids (Chronos-2 unless noted):
mainValueError: Could not infer frequency for series ...freq="D"future_df, a category without rowsValueError: future_df must contain prediction_length=3 rows per item. Found 1 items ...validate_inputs=FalseValueError: Could not infer frequency ...predict_dfValueError: Could not infer frequency ...Relation to #440 and #470
This also fixes #440: on pandas 2.2.3,
infer_freq_from_dfon the issue's kind of data (many weekly series, hashedstring[python]ids, unequal lengths) raises onmainand returnsW-MONwith this change. It does not reproduce on pandas 3.Credit to @MohammedAlkindi, who noted on #470 that the pattern survived the #507 refactor and listed the same call sites; #470 itself targets functions that no longer exist. Two things differ from that analysis. For categorical ids the
future_dfrow-count check invalidate_dfis affected too, since a category without rows is counted with zero rows. Andgroupby(sort=False).size(), the approach of #470, still counts unused categories on pandas 2.2 ([2, 3, 0]for two series and one empty category), whilefactorize+bincountgives[2, 3].Fixes #440
Tests
test_get_series_lengths_follows_row_order: categorical, categorical with an unused category, andstring[python]ids.test_infer_freq_and_make_future_df_handle_categorical_ids.test_predict_df_with_categorical_item_ids_matches_object_idsfor Chronos-2 and Chronos-Bolt, with inferred and explicitfreq, with and without an unused category. The eight cases fail onmainand pass with this change.pytest: 568 passed, 20 xfailed, on both pandas 3.0.6 and pandas 2.2.3.mypy src test: no issues.