From 05c725710c1bb3740b611e5387a295bb22cee618 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:56:50 -0500 Subject: [PATCH 01/16] do not assign offsetgroup to traces in px for bar, violin, box, and histogram traces --- packages/python/plotly/plotly/express/_core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 0e71f41becf..ae35bc46237 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2194,8 +2194,6 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): legendgroup=trace_name, showlegend=(trace_name != "" and trace_name not in trace_names), ) - if trace_spec.constructor in [go.Bar, go.Violin, go.Box, go.Histogram]: - trace.update(alignmentgroup=True, offsetgroup=trace_name) trace_names.add(trace_name) # Init subplot row/col From b127443c88ca2b7d2fae7003fed935bf12ecd06d Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:40:49 -0500 Subject: [PATCH 02/16] set offsetgroup only in group barmode --- packages/python/plotly/plotly/express/_core.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index ae35bc46237..0555511c9df 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2194,6 +2194,12 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): legendgroup=trace_name, showlegend=(trace_name != "" and trace_name not in trace_names), ) + # Set 'offsetgroup' only in group barmode + if ( + trace_spec.constructor in [go.Bar, go.Violin, go.Box, go.Histogram] + and args["barmode"] == "group" + ): + trace.update(alignmentgroup=True, offsetgroup=trace_name) trace_names.add(trace_name) # Init subplot row/col From 4e76f589d47fbb5c20804c9ca44b92a42577ece5 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:52:58 -0500 Subject: [PATCH 03/16] Limit offsetgroup to Histogram and Bar traces --- packages/python/plotly/plotly/express/_core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 0555511c9df..0bdde1a8f52 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2196,8 +2196,8 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): ) # Set 'offsetgroup' only in group barmode if ( - trace_spec.constructor in [go.Bar, go.Violin, go.Box, go.Histogram] - and args["barmode"] == "group" + trace_spec.constructor in [go.Bar, go.Histogram] + and args.get("barmode") == "group" ): trace.update(alignmentgroup=True, offsetgroup=trace_name) trace_names.add(trace_name) From 762f17bf0b38866a871d5b3b01fc4c6d8ebf579a Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:03:00 -0500 Subject: [PATCH 04/16] also set offsetgroup if no barmode is set --- packages/python/plotly/plotly/express/_core.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 1caec00386a..7855bb10211 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2558,10 +2558,11 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): legendgroup=trace_name, showlegend=(trace_name != "" and trace_name not in trace_names), ) - # Set 'offsetgroup' only in group barmode + # Set 'offsetgroup' only in group barmode (or if no barmode is set) + barmode = args.get("barmode") if ( - trace_spec.constructor in [go.Bar, go.Histogram] - and args.get("barmode") == "group" + trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] + and barmode == "group" or barmode is None ): trace.update(alignmentgroup=True, offsetgroup=trace_name) trace_names.add(trace_name) From ac8af46ed4d947a9ccaa48cfdbee8c6167518bda Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 13:14:20 -0500 Subject: [PATCH 05/16] boolean order of operations... --- packages/python/plotly/plotly/express/_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 7855bb10211..324405dd449 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2562,7 +2562,7 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): barmode = args.get("barmode") if ( trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] - and barmode == "group" or barmode is None + and (barmode == "group" or barmode is None) ): trace.update(alignmentgroup=True, offsetgroup=trace_name) trace_names.add(trace_name) From e41dc36d35c428b00ccece05e994ae6aaea94a6b Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:14:55 -0500 Subject: [PATCH 06/16] handle barmode/offsetgroup edge cases --- packages/python/plotly/plotly/express/_core.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 324405dd449..1b38f2ae182 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -652,8 +652,6 @@ def set_cartesian_axis_opts(args, axis, letter, orders): def configure_cartesian_marginal_axes(args, fig, orders): - if "histogram" in [args["marginal_x"], args["marginal_y"]]: - fig.layout["barmode"] = "overlay" nrows = len(fig._grid_ref) ncols = len(fig._grid_ref[0]) @@ -2147,6 +2145,9 @@ def process_dataframe_timeline(args): args["x"] = args["x_end"] args["base"] = args["x_start"] del args["x_start"], args["x_end"] + + args["barmode"] = "relative" + return args @@ -2558,8 +2559,13 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): legendgroup=trace_name, showlegend=(trace_name != "" and trace_name not in trace_names), ) + + # With marginal histogram, if barmode is not set, set to "overlay" + if "histogram" in [args.get("marginal_x"), args.get("marginal_y")] and "barmode" not in args: + layout_patch["barmode"] = "overlay" + # Set 'offsetgroup' only in group barmode (or if no barmode is set) - barmode = args.get("barmode") + barmode = args.get("barmode") or layout_patch.get("barmode") if ( trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] and (barmode == "group" or barmode is None) From 2b98ccedd6db593b9fff5a0fa9d072073d6ca249 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:22:59 -0500 Subject: [PATCH 07/16] formatting --- .../python/plotly/plotly/express/_core.py | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 1b38f2ae182..20d1735e3e9 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -652,7 +652,6 @@ def set_cartesian_axis_opts(args, axis, letter, orders): def configure_cartesian_marginal_axes(args, fig, orders): - nrows = len(fig._grid_ref) ncols = len(fig._grid_ref[0]) @@ -1495,17 +1494,14 @@ def build_dataframe(args, constructor): # If data_frame is provided, we parse it into a narwhals DataFrame, while accounting # for compatibility with pandas specific paths (e.g. Index/MultiIndex case). if df_provided: - # data_frame is pandas-like DataFrame (pandas, modin.pandas, cudf) if nw.dependencies.is_pandas_like_dataframe(args["data_frame"]): - columns = args["data_frame"].columns # This can be multi index args["data_frame"] = nw.from_native(args["data_frame"], eager_only=True) is_pd_like = True # data_frame is pandas-like Series (pandas, modin.pandas, cudf) elif nw.dependencies.is_pandas_like_series(args["data_frame"]): - args["data_frame"] = nw.from_native( args["data_frame"], series_only=True ).to_frame() @@ -1859,7 +1855,6 @@ def _check_dataframe_all_leaves(df: nw.DataFrame) -> None: for row_idx, row in zip( null_indices_mask, null_mask.filter(null_indices_mask).iter_rows() ): - i = row.index(True) if not all(row[i:]): @@ -1988,7 +1983,6 @@ def process_dataframe_hierarchy(args): if args["color"]: if discrete_color: - discrete_aggs.append(args["color"]) agg_f[args["color"]] = nw.col(args["color"]).max() agg_f[f'{args["color"]}{n_unique_token}'] = ( @@ -2043,7 +2037,6 @@ def post_agg(dframe: nw.LazyFrame, continuous_aggs, discrete_aggs) -> nw.LazyFra ).drop([f"{col}{n_unique_token}" for col in discrete_aggs]) for i, level in enumerate(path): - dfg = ( df.group_by(path[i:], drop_null_keys=True) .agg(**agg_f) @@ -2561,14 +2554,16 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): ) # With marginal histogram, if barmode is not set, set to "overlay" - if "histogram" in [args.get("marginal_x"), args.get("marginal_y")] and "barmode" not in args: + if ( + "histogram" in [args.get("marginal_x"), args.get("marginal_y")] + and "barmode" not in args + ): layout_patch["barmode"] = "overlay" # Set 'offsetgroup' only in group barmode (or if no barmode is set) barmode = args.get("barmode") or layout_patch.get("barmode") - if ( - trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] - and (barmode == "group" or barmode is None) + if trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] and ( + barmode == "group" or barmode is None ): trace.update(alignmentgroup=True, offsetgroup=trace_name) trace_names.add(trace_name) @@ -2864,9 +2859,7 @@ def _spacing_error_translator(e, direction, facet_arg): e.args = ( e.args[0] + """ -Use the {facet_arg} argument to adjust this spacing.""".format( - facet_arg=facet_arg - ), +Use the {facet_arg} argument to adjust this spacing.""".format(facet_arg=facet_arg), ) raise e From e7f3756f7c9707c73a116bef67aa47d4e78c9d9d Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:33:00 -0500 Subject: [PATCH 08/16] formatting --- packages/python/plotly/plotly/express/_core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 20d1735e3e9..62d0ecffc7b 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2859,7 +2859,9 @@ def _spacing_error_translator(e, direction, facet_arg): e.args = ( e.args[0] + """ -Use the {facet_arg} argument to adjust this spacing.""".format(facet_arg=facet_arg), +Use the {facet_arg} argument to adjust this spacing.""".format( + facet_arg=facet_arg + ), ) raise e From 3110baa5474d872e1cc4d883b4408c8856dbe90d Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:56:05 -0500 Subject: [PATCH 09/16] don't need this --- packages/python/plotly/plotly/express/_core.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 62d0ecffc7b..08374119216 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2139,8 +2139,6 @@ def process_dataframe_timeline(args): args["base"] = args["x_start"] del args["x_start"], args["x_end"] - args["barmode"] = "relative" - return args From ab08bd4e11e963e9cf91b05d2e710855b980decf Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 11:57:36 -0500 Subject: [PATCH 10/16] formatting --- packages/python/plotly/plotly/express/_core.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 08374119216..430a0d5db7f 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2138,7 +2138,6 @@ def process_dataframe_timeline(args): args["x"] = args["x_end"] args["base"] = args["x_start"] del args["x_start"], args["x_end"] - return args From db1e0d9f870ebae623e6f9407bf38253509223b3 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:02:51 -0500 Subject: [PATCH 11/16] move set barmode outside trace loop --- packages/python/plotly/plotly/express/_core.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 430a0d5db7f..ae3dc8cffa9 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2478,6 +2478,13 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): constructor = go.Bar args = process_dataframe_timeline(args) + # With marginal histogram, if barmode is not set, set to "overlay" + if ( + "histogram" in [args.get("marginal_x"), args.get("marginal_y")] + and "barmode" not in args + ): + layout_patch["barmode"] = "overlay" + trace_specs, grouped_mappings, sizeref, show_colorbar = infer_config( args, constructor, trace_patch, layout_patch ) @@ -2550,13 +2557,6 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): showlegend=(trace_name != "" and trace_name not in trace_names), ) - # With marginal histogram, if barmode is not set, set to "overlay" - if ( - "histogram" in [args.get("marginal_x"), args.get("marginal_y")] - and "barmode" not in args - ): - layout_patch["barmode"] = "overlay" - # Set 'offsetgroup' only in group barmode (or if no barmode is set) barmode = args.get("barmode") or layout_patch.get("barmode") if trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] and ( From 298f5ce9e59daa6a726718a7fbbedda716eec3f7 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:06:14 -0500 Subject: [PATCH 12/16] we only need to check barmode in layout_patch, not args --- packages/python/plotly/plotly/express/_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index ae3dc8cffa9..21a6d5c4623 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2558,7 +2558,7 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): ) # Set 'offsetgroup' only in group barmode (or if no barmode is set) - barmode = args.get("barmode") or layout_patch.get("barmode") + barmode = layout_patch.get("barmode") if trace_spec.constructor in [go.Bar, go.Box, go.Violin, go.Histogram] and ( barmode == "group" or barmode is None ): From ac3177c6c67d7214d5e5b63412a0043303a24a0d Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:13:28 -0500 Subject: [PATCH 13/16] change args to layout_patch --- packages/python/plotly/plotly/express/_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 21a6d5c4623..735e4dd80d2 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2481,7 +2481,7 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): # With marginal histogram, if barmode is not set, set to "overlay" if ( "histogram" in [args.get("marginal_x"), args.get("marginal_y")] - and "barmode" not in args + and "barmode" not in layout_patch ): layout_patch["barmode"] = "overlay" From b195c2e4cb4b2461ecfa5b265c604b802622a578 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:54:19 -0500 Subject: [PATCH 14/16] don't need this --- packages/python/plotly/plotly/express/_core.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 735e4dd80d2..af249e926c3 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2481,7 +2481,6 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): # With marginal histogram, if barmode is not set, set to "overlay" if ( "histogram" in [args.get("marginal_x"), args.get("marginal_y")] - and "barmode" not in layout_patch ): layout_patch["barmode"] = "overlay" From b3470773dc3ca0c4e4432f0e182734305d106f1e Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:31:14 -0500 Subject: [PATCH 15/16] formatting --- packages/python/plotly/plotly/express/_core.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index af249e926c3..07b26055b0f 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2479,9 +2479,7 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): args = process_dataframe_timeline(args) # With marginal histogram, if barmode is not set, set to "overlay" - if ( - "histogram" in [args.get("marginal_x"), args.get("marginal_y")] - ): + if "histogram" in [args.get("marginal_x"), args.get("marginal_y")]: layout_patch["barmode"] = "overlay" trace_specs, grouped_mappings, sizeref, show_colorbar = infer_config( From 48b8d06854b381129fae553c70053288d214f169 Mon Sep 17 00:00:00 2001 From: Emily Kellison-Linn <4672118+emilykl@users.noreply.github.com> Date: Fri, 15 Nov 2024 19:30:43 -0500 Subject: [PATCH 16/16] update comment --- packages/python/plotly/plotly/express/_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/python/plotly/plotly/express/_core.py b/packages/python/plotly/plotly/express/_core.py index 07b26055b0f..ddaa14a57c0 100644 --- a/packages/python/plotly/plotly/express/_core.py +++ b/packages/python/plotly/plotly/express/_core.py @@ -2478,7 +2478,7 @@ def make_figure(args, constructor, trace_patch=None, layout_patch=None): constructor = go.Bar args = process_dataframe_timeline(args) - # With marginal histogram, if barmode is not set, set to "overlay" + # If we have marginal histograms, set barmode to "overlay" if "histogram" in [args.get("marginal_x"), args.get("marginal_y")]: layout_patch["barmode"] = "overlay"