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

Offen
#5,765 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

Bewertung

Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Anfängerfreundlichkeit
35/100
Issue-Typ
Bug
Klarheit
Klar beschrieben
Aktivitätsstatus
Aktiv
Tech-Stack
python

Rechercherichtung

Beginne in plotly/express/_core.py bei process_dataframe_hierarchy und verfolge die group_by-Aufrufe, die für pfadbasierte Diagramme verwendet werden. Vergleiche die Hierarchie-Reihenfolge von Polars, pandas und PyArrow und untersuche anschließend den vom Reporter beigefügten oder vorgeschlagenen Regressionstest. Als abgeschlossen gilt die Aufgabe, wenn wiederholte Polars-Ausführungen eine stabile Reihenfolge nach dem ersten Auftreten erzeugen, die mit den anderen unterstützten Eingaben übereinstimmt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Beschreibung

Description

When path= is used with a Polars DataFrame, px.sunburst, px.treemap and px.icicle build their ids / labels / parents / values arrays in a different order every time the script is run. The same data as a pandas DataFrame or a PyArrow table always gives the same order: the order in which the sectors first appear in the data.

The cause is in process_dataframe_hierarchy (plotly/express/_core.py). Each level of the hierarchy is built with df.group_by(path[i:]).agg(...). With pandas (narwhals uses sort=False) and PyArrow the groups come back in order of first appearance, but Polars' group_by does not guarantee any order, so the order of the output changes from run to run.

Consequences:

  • fig.to_json() / fig.write_html() output is not reproducible with Polars input (snapshot tests, caching, diffs of generated HTML).
  • With sort=False, or when sectors have equal values, the chart itself is laid out differently on each run.
  • Polars results differ from pandas / PyArrow results for identical data.
Screenshots/Video

N/A: the difference is in the figure data; see the output below.

Steps to reproduce
import plotly
import plotly.express as px
import polars as pl

df = pl.DataFrame(
    {
        "region": ["South", "North", "South", "West", "North", "West"],
        "sector": ["Tech", "Finance", "Finance", "Tech", "Tech", "Finance"],
        "sales": [1, 2, 3, 4, 5, 6],
    }
)
fig = px.sunburst(df, path=["region", "sector"], values="sales")
print(plotly.__version__, pl.__version__, list(fig.data[0].ids))

Running the script three times (plotly 7.1.0, polars 1.44.2):

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

With pd.DataFrame(...) instead, every run prints:

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

I have a small fix with a regression test and will open a PR for it.

Vorherrschende Sprache
Python
Sterne
18.8k
Forks
2.8k
Ø Merge
16 Std. 26 Min.
Gemergte PRs (30 T.)
21

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
  3. Forken Sie das Repository und arbeiten Sie in einem Branch.
  4. Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.

Mehr aus plotly/plotly.py

Alle Issues in plotly/plotly.py

Ähnliche Issues

Weitere Issues zu Python

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.