From 2ce6fdb53f953bf966e1aa2155f0efe425381516 Mon Sep 17 00:00:00 2001 From: Hassan Kibirige Date: Wed, 15 Jul 2026 19:20:32 +0300 Subject: [PATCH] fix(geom_rect): draw each rectangle as its own polygon in non-linear coords In a non-linear coord, rectangles are drawn as polygons grouped by the `group` aesthetic. A stacked bar shares one group across its segments, so they merged into a single open path and coord.munch bent the join between consecutive rectangles into a triangular spike. Regroup into one polygon per rectangle so each is closed independently. --- doc/changelog.qmd | 5 +++++ plotnine/geoms/geom_rect.py | 5 +++++ .../coord_trans_stacked_bars_have_no_spikes.png | Bin 0 -> 2903 bytes tests/test_coords.py | 10 ++++++++++ 4 files changed, 20 insertions(+) create mode 100644 tests/baseline_images/test_coords/coord_trans_stacked_bars_have_no_spikes.png diff --git a/doc/changelog.qmd b/doc/changelog.qmd index 46f687e24..0afaea656 100644 --- a/doc/changelog.qmd +++ b/doc/changelog.qmd @@ -116,6 +116,11 @@ title: Changelog the closing edge of a polygon is now curved along with the rest of its boundary instead of being drawn as a straight chord. +- Stacked bars in a non-linear coordinate system (e.g. + [](:class:`~plotnine.coord_trans`)) no longer show triangular spikes; each + rectangle is now drawn as its own polygon instead of merging a bar's + segments into a single path. + - The space between facet panels now accounts for the margins of the axis text, so with free scales large margins no longer push the tick labels into the neighbouring panel. diff --git a/plotnine/geoms/geom_rect.py b/plotnine/geoms/geom_rect.py index eecae786c..9b52ecf8e 100644 --- a/plotnine/geoms/geom_rect.py +++ b/plotnine/geoms/geom_rect.py @@ -54,6 +54,11 @@ def draw_panel( """ if not coord.is_linear: data = _rectangles_to_polygons(data) + # Each rectangle is its own closed polygon. Grouping by the + # `group` aesthetic would merge a stacked bar's segments into one + # open path, and coord.munch would then bend the join between + # consecutive rectangles into a spurious spike. + data["group"] = np.repeat(np.arange(len(data) // 4), 4) for _, gdata in data.groupby("group"): gdata.reset_index(inplace=True, drop=True) geom_polygon.draw_group( diff --git a/tests/baseline_images/test_coords/coord_trans_stacked_bars_have_no_spikes.png b/tests/baseline_images/test_coords/coord_trans_stacked_bars_have_no_spikes.png new file mode 100644 index 0000000000000000000000000000000000000000..d3894ff21916fc0856b37eaf7c333c78f24e2c1a GIT binary patch literal 2903 zcmaJ?2Uru?7ETBqSrUT?sPyi`5C~d^0B}kDL5tgDX;3B<6 zDFRXjLNTElL=8ni1O$0O(Oq`G_h!DiXU@Gdr`-SC|HNK0&}L=kW(EKNthzc#BLIK~ z0{{SL7^xEgaKmi{s$lZevG4%^SfB?F5RjF_Nqu3`MXHt=29 zAH|6*?vh$*3Y0$-mQ9xF_CKh4z^0q?J;xs1iB8iNWw{Z+IzA159B`pm%qqw?pXyG9 z?k-Aw)?dSZc%Y{s_IWOtmXR9#r89R?vX+)y=7pD5-C9CH=+j($YQ;8SJ{nq}0CfWn z^ZUQzO;xr0#dRK(TfLEqMOD~Z1FL6S{HDlraZX?a0K&%z{)Z4yJ2d}KfotxI^{(&X z)uey3h5~JO740svRhm57MLDRI!c;=GTXfV3iHa-i2`)z>o6(fDG7(gRJ$m-PJpMb3 zZ|VKrzg@gl5Yj%$IS8ppcbgiu>+f2|$tdd1+;R-d=fek%Rx3z9m^pC$_rIuHw53YF zfb%!CcFp`!%wT^DVLF1q_ciA2bhLJy2+C>lbqqk5jY#8*Jl=k`%=P6}S44mgpzPVNmd|kxd&Lj zxT}FklS8OB1_dONlwi1*e;?LJI!fFSLCdf6pt3*0C;ES z!!#>(>-Br+oKwAXB91_*smmd3aWC>f%yNTiV*u(H#(xV4-*`^f0+MDULBZhJ;rbRw zLN0`ofXRj6WxtmhnD6GA;>@YfNMu_gLro_1)fS6+6XoeCr`*-I%4SrZarLaC|MceI zr|ACr-kfAD3=H9M3bnZFG<2W@sfG~C;zM^+)1ZA!*JfwbY-+N(K z4UxsG$c^{81lYTr%DEcty+`;M5yq2bXvke{Aur)2F(s!0{8+p^-RS?oQR3cLa@|0+{Q_ z+O^C^*ovZyTh7KfUFxRf0V`X94Dyr^iEd|;M40{0gMX0KIREG`rG7dc!&1~i_Q&ks zm@FD1T`dz)Y^!t`TSOIqRq|0{DX=V9%F;2W4xY?f7#n>?syQPLm-C*iR7f(wX6sfH zFg3Gvx}S`Dlw7`PMliO*1@AP~xMN-9sz4%_GUWz?`H#wky&z@Yx%upF2nsbNxPAG! z`AI561!>v@$vu9#dkl2Q+nZ5Oeog6%B^s@+rx;5e4UvYnc8>Ubv*sf4d5y#`W8d1| z5xS3|W|PM!_q~4}8o~+T!!@gL zaMMDL8PjZ0>uI-gowNAjVv3yO{d$4l0b^7eZ0bR$yn4PtT!;xrBYX3p!>=D=J>F1} z9?Tk@@87UBBP6%)`}YXf|L#)Mo@_T_VW4Nzlr1mKp zcHwF_qcN|6mUFZ7xL`&CiQ zxB?h5FG_TtD~o%ac>Qsbs-U~l%nVb!;MCXcNKlbwUFalAxgzA+{vIxYQ+0iHy+UP^ z#J0Te-i|l3j*ZFuZLB>c#&}h9bnOPVOb@#Z6Yh?cp-=UX+HW%)Fyx@%ge2bzcej&Q zLZoJ63+EZy_S+g3fY7(>Xytt+Uz~j)p_Ams3O^U6BrTj6;H1$$5;N8cUI`ua)7<@3 z$SGZ8dso+o`RhsvgAq%4p6yOIewTqKCyeWBxU}p^5a_c!eF>6SBbcQ8?A3m#XA=FS zGfg4SR{smB6PcY6lVNZrTQDHqy+58a-MsQPdBYtqRM&Q1ntwJ}=+PYuoM58W!==jf#9 zgb#)#eViii(9JNXip(+!6&$p6m%Cc$5^g7Ia38Qy)`c^IgvZXg_nN fIZan!qXqz|%@;;9@|U#%sF$v$0kZtOO~iiz#T3