plotly / plotly/plotly.py

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

未关闭
#5,765 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
Python
星标
18.8k
派生
2.8k
平均合并
16 小时 26 分钟
30 天内合并 PR
21

描述

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.

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 plotly/express/_core.py 中的 process_dataframe_hierarchy 开始,跟踪用于基于路径的图表的 group_by 调用。比较 Polars、pandas 和 PyArrow 的层级顺序,然后检查报告者附带或提议的回归测试。当重复运行 Polars 能产生稳定的首次出现顺序,并且与其他受支持的输入一致时,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
data-visualization
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
活跃
描述清晰度
描述清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。