Skip to content

Make px.sunburst/treemap/icicle sector order deterministic for Polars input - #5766

Open
Irahan2 wants to merge 1 commit into
plotly:mainfrom
Irahan2:fix-hierarchy-group-order
Open

Irahan2 wants to merge 1 commit into
plotly:mainfrom
Irahan2:fix-hierarchy-group-order

Conversation

@Irahan2

@Irahan2 Irahan2 commented Sep 18, 2026

Copy link
Copy Markdown

Link to issue

Closes #5765

Description of change

process_dataframe_hierarchy now adds a temporary row-index column, takes its minimum in each group, and sorts every level of the hierarchy by it after the group_by. Sectors are therefore always listed in order of first appearance for every dataframe backend. pandas and PyArrow already produced that order; Polars, whose group_by does not keep row order, produced a different order on every run.

Demo

Before, three runs of the script from the issue with a Polars DataFrame:

['West/Tech', 'West/Finance', 'North/Finance', 'South/Finance', 'North/Tech', 'South/Tech', 'South', 'North', 'West']
['South/Tech', 'West/Tech', 'North/Tech', 'South/Finance', 'North/Finance', 'West/Finance', 'West', 'North', 'South']
['South/Tech', 'West/Tech', 'North/Tech', 'North/Finance', 'South/Finance', 'West/Finance', 'West', 'South', 'North']

After, every run (and pandas / PyArrow):

['South/Tech', 'North/Finance', 'South/Finance', 'West/Tech', 'North/Tech', 'West/Finance', 'South', 'North', 'West']

Testing strategy

Added test_sunburst_treemap_with_path_order, parametrized over all the dataframe constructors and over px.sunburst, px.treemap and px.icicle. It checks the exact order of ids and values. It fails for the Polars constructor on main and passes with this change. The rest of tests/test_optional/test_px passes locally, apart from 3 tests that fail the same way on unmodified main in my Windows environment (test_timezones and test_date_in_hover for the PyArrow constructor, and one test_imshow_source_dtype_zmax case). The hierarchy tests also pass with the minimum supported narwhals (1.15.1).

Additional information (optional)

  • pandas output does not change: it already used first-appearance order (narwhals' group_by uses sort=False). This matches how Plotly Express orders categories elsewhere (unique(maintain_order=True)).
  • Only the hierarchy code path is affected. The other group_by in _core.py is only used for key lookups, and trace order there already comes from unique(maintain_order=True).
  • AI disclosure: I used Claude Code (Claude Opus 5) to help find this bug (by comparing Plotly Express output for pandas, Polars and PyArrow inputs) and to draft the fix and the test. I have reviewed the changes and run the tests myself.

Guidelines

process_dataframe_hierarchy groups each level of the path with group_by,
whose output order is not guaranteed: pandas and PyArrow return groups in
order of first appearance, but Polars returns them in a different order on
every run. Track the original row index, aggregate its minimum per group
and sort each level by it, so that sunburst, treemap and icicle sectors
follow their order of first appearance for all dataframe backends.

Closes plotly#5765
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.

[BUG]: px.sunburst / px.treemap / px.icicle with path give a different sector order on every run for Polars DataFrames

1 participant