Skip to content

Commit efd34d4

Browse files
committed
Fix Plotly Express mutating lists passed to x or y in wide mode
args['wide_variable'] aliased the user-supplied x/y list, and process_args_into_dataframe replaces its elements with column-name strings in place. Copy it into a fresh list (this also accepts tuples, which previously failed on item assignment). Fixes #4117
1 parent 2e2d1f0 commit efd34d4

3 files changed

Lines changed: 17 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1111
### Fixed
1212
- Fix `mpl_to_plotly` not setting `paper_bgcolor` and `plot_bgcolor` from the matplotlib figure and axes backgrounds, so converted figures match the source figure's background colors [[#5285](https://github.com/plotly/plotly.py/pull/5285)], with thanks to @robertoffmoura for the contribution!
1313
- Fix rendering issue causing a too-large div when calling `Figure.show()` in Google Colab [[#5718](https://github.com/plotly/plotly.py/pull/5718)]
14+
- Fix Plotly Express mutating lists passed to the `x` or `y` arguments in wide mode [[#4117](https://github.com/plotly/plotly.py/issues/4117)]
1415

1516
### Updated
1617
- Update plotly.js from version 4.0.0 to version 4.1.0 [[#5722](https://github.com/plotly/plotly.py/pull/5722)]. See the [plotly.js release notes](https://github.com/plotly/plotly.js/releases/tag/v4.1.0) for details. Notable changes include:

plotly/express/_core.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,8 +1687,9 @@ def build_dataframe(args, constructor):
16871687
args["wide_variable"] = args["y"] if wide_y else args["x"]
16881688
if df_provided and is_pd_like and args["wide_variable"] is columns:
16891689
var_name = columns.name
1690-
if is_pd_like and isinstance(args["wide_variable"], native_namespace.Index):
1691-
args["wide_variable"] = list(args["wide_variable"])
1690+
# copy into a new list so that the list provided by the user for
1691+
# x or y is not mutated when wide_variable's entries are replaced
1692+
args["wide_variable"] = list(args["wide_variable"])
16921693
if var_name in [None, "value", "index"] or (
16931694
df_provided and var_name in columns
16941695
):

tests/test_optional/test_px/test_px_wide.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,3 +890,16 @@ def test_no_pd_perf_warning():
890890
if issubclass(warn.category, pd.errors.PerformanceWarning)
891891
]
892892
assert len(performance_warnings) == 0, "PerformanceWarning(s) raised!"
893+
894+
895+
def test_wide_mode_does_not_mutate_x_or_y():
896+
# https://github.com/plotly/plotly.py/issues/4117
897+
df = pd.DataFrame(dict(a=[1, 2, 3], b=[4, 5, 6], c=[7, 8, 9]))
898+
for arg in ["x", "y"]:
899+
cols = ["a", "b"]
900+
px.bar(df, **{arg: cols})
901+
assert cols == ["a", "b"]
902+
cols = [0, 1]
903+
df_int = pd.DataFrame([[1, 2], [3, 4]])
904+
px.histogram(df_int, x=cols)
905+
assert cols == [0, 1]

0 commit comments

Comments
 (0)