Repository navigation
Conversation
|
Thanks for the PR! Our team will review and follow up. |
chrikrah
left a comment
There was a problem hiding this comment.
@vineoy blocking: with this branch, the discrete-color Gantt example in doc/python/gantt.md:69-76 lists its tasks bottom-up, the opposite of what that page promises.
# df = the three-task Resource frame at doc/python/gantt.md:69-73
>>> px.timeline(df, x_start="Start", x_end="Finish", y="Task").layout.yaxis.categoryarray
None # 85cb798 and main d586d22
>>> px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource").layout.yaxis.categoryarray
('Job C', 'Job B', 'Job A') # 85cb798
None # main d586d22
>>> px.bar(x=[1,2,3,4], y=list("abcd"), color=list("ppqq"), orientation="h").layout.yaxis.categoryarray
('d', 'c', 'b', 'a') # 85cb798
None # main d586d22
The page pairs that call with autorange="reversed" so tasks read top-down. The new default goes through the y reversal at _core.py:639, and the two reversals cancel. A colored horizontal bar flips the same way, even where the groups do not interleave. #3291 asked for the x order to be set internally, and it said nothing about y. Two ways out:
- Apply the default to
xonly. - Keep
y, and store its default so that the reversal at_core.py:639gives back the bottom-up order.
The x-axis fix itself holds: the two data-order tests fail with _core.py from main and pass on the branch.
$ pytest -q tests/test_optional/test_px/test_px.py # 85cb798
3 failed, 331 passed, 4 warnings in 29.64s
$ pytest -q tests/test_optional/test_px/test_px.py # main d586d22
3 failed, 328 passed, 4 warnings in 27.27s
$ cp <main>/plotly/express/_core.py plotly/express/ && pytest -q tests/test_optional/test_px/test_px.py -k "data_order or no_default_category"
2 failed, 1 passed, 331 deselected, 4 warnings in 0.82s
The three failures on both commits are test_render_mode, which needs statsmodels.
@camdecoster would you take fix 1 or fix 2 here?
Address review on plotly#5776: y categoricals stay untouched so the autorange=reversed pattern from doc/python/gantt.md keeps listing tasks top-down instead of double-reversing. Adds guard test that px.timeline and horizontal px.bar with color emit no y categoryarray, while x data-order fix for plotly#3198/plotly#3291 is kept.
|
Thanks @chrikrah for catching the y axis double reversal. I took fix 1 and scoped the default to x only. y categoricals are now untouched, so the autorange reversed pattern in doc/python/gantt.md keeps listing tasks top down. Pushed d6ddc2a. It limits _default_category_orders_for_axes to x with a note on why y is excluded, keeps the x data order fix for #3198 and #3291, adds test_no_default_category_array_for_y_with_color for px.timeline and horizontal px.bar with color, and updates CHANGELOG to say x axis. Verified locally. The x repros still give ('A','B','C','D','E') and ('a','b','c','d'). The y timeline and y bar h cases now give None, matching main. test_px.py gives 3 failed (pre existing test_render_mode statsmodels gap) and 332 passed. Ruff check is clean. @camdecoster please let me know if you would rather have fix 2. |
Address review on plotly#5776: y categoricals stay untouched so the autorange=reversed pattern from doc/python/gantt.md keeps listing tasks top-down instead of double-reversing. Adds guard test that px.timeline and horizontal px.bar with color emit no y categoryarray, while x data-order fix for plotly#3198/plotly#3291 is kept.
d6ddc2a to
16ab376
Compare
chrikrah
left a comment
There was a problem hiding this comment.
@vineoy the Gantt flip is fixed at 16ab376, so I am approving. The y axis gets no default order, and the x data-order fix still holds.
# df = the three-task Resource frame at doc/python/gantt.md:69-73
>>> px.timeline(df, x_start="Start", x_end="Finish", y="Task", color="Resource").layout.yaxis.categoryarray
None # 16ab376 and main 3f8a650
>>> px.bar(x=[1,2,3,4], y=list("abcd"), color=list("ppqq"), orientation="h").layout.yaxis.categoryarray
None # 16ab376 and main 3f8a650
>>> px.bar(x=list("abcd"), y=[1,2,3,4], color=list("pqpq")).layout.xaxis.categoryarray
('a', 'b', 'c', 'd') # 16ab376
None # main 3f8a650
The uncolored timeline stays None on both. Each new test also fails without its part of the change:
$ pytest -q tests/test_optional/test_px/test_px.py # head 16ab376
3 failed, 332 passed, 4 warnings in 33.23s
$ pytest -q tests/test_optional/test_px/test_px.py # main 3f8a650
3 failed, 328 passed, 4 warnings in 28.49s
$ cp <3f8a650>/plotly/express/_core.py plotly/express/ && pytest -q tests/test_optional/test_px/test_px.py -k "data_order or no_default_category"
2 failed, 2 passed, 331 deselected, 4 warnings in 0.86s # both data_order tests
# the x-and-y loop from 85cb798 spliced into _core.py, same -k
1 failed, 3 passed, 331 deselected, 4 warnings in 0.83s # test_no_default_category_array_for_y_with_color
# Python 3.12, pytest 9.1.1; the 3 failures on both commits are test_render_mode, which needs statsmodels
# not run: the rest of tests/test_optional
non-blocking: CHANGELOG.md now has ## [7.1.0] - 2026-09-15 twice, at lines 22 and 24. The new entry sits under Unreleased and an empty 7.1.0 section follows it. Drop the added heading.
@camdecoster from my side this is ready to merge. The y axis can follow in its own PR if you want it.
Link to issue
Fixes #3198, fixes #3291.
Description of change
When Plotly Express splits data into several traces (e.g. via \color), plotly.js orders categories by first appearance across traces (default \categoryorder). Because each trace only carries its own rows (None-padded), that order can differ from the order in the underlying data — contradicting the documented behavior that Plotly Express lays out categorical data in the order in which it appears in the data.
This change records the data-appearance order of string categorical \x/\y\ columns in \make_figure\ (new _default_category_orders_for_axes\ helper in \plotly/express/_core.py), but only when the data is actually split into more than one trace and the user did not supply an explicit \category_orders\ entry. The existing \set_cartesian_axis_opts\ then emits \categoryorder=array\ + \categoryarray, so:
Explicit user \category_orders, single-trace figures, and numeric/datetime axes are untouched.
Testing strategy
uff==0.11.12 check\ clean.