Skip to content

Commit 7081223

Browse files
authored
Fix: shifting margins caused by multiple rugplots (#2953)
* Fix: shifting margins caused by multiple rugplots This fix prevents margins from increasing when multiple rugplots are added to the same `ax`, even if `expand_margins` is `False`. As a minimum reproducible example: ```py import seaborn as sns; sns.set() import numpy as np import matplotlib.pyplot as plt values = np.linspace(start=0, stop=1, num=5) ax = sns.lineplot(x=values, y=values) sns.rugplot(x=values, ax=ax) ylim = ax.get_ylim() for _ in range(4): sns.rugplot(x=values, ax=ax, expand_margins=False) if not all(a == b for a, b in zip(ylim, ax.get_ylim())): print(f'{ylim} != {ax.get_ylim()}') plt.suptitle("Example showing that multiple rugplots cause issues") plt.show() ``` Running the above code: ```sh $ pip install seaborn numpy matplotlib; python3 test.py (-0.1, 1.1) != (-0.61051, 1.14641) ``` This bug was caused by how seaborn detects the correct colors to use. In `seaborn/utils.py`, in method `_default_color`, the following line used to resolve to `ax.plot([], [], **kws)`: ```py scout, = method([], [], **kws) ``` But matplotlib has the parameters `scalex` and `scaley` of `ax.plot` set to `True` by default. Matplotlib would see that the rug was already on the `ax` from the previous call to `sns.rugplot`, and so it would rescale the x and y axes. This caused the content of the plot to take up less and less space, with larger and larger margins as more rugplots were added. The fix sets `scalex` and `scaley` both to `False`, since this plot method is a null-plot and is only used to check what colours should be used: ```py scout, = method([], [], scalex=False, scaley=False, **kws) ``` The above line is within an if-elif-else branch, but the other branches do not suffer this bug and so no change is needed for them. An additional unit test was also added to catch this bug: `test_multiple_rugs`. * Update PR based on comments * Remove unused import
1 parent 2c3ea6f commit 7081223

File tree

3 files changed

+13
-1
lines changed

3 files changed

+13
-1
lines changed

doc/whatsnew/v0.12.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ Other updates
100100

101101
- |Fix| Improved robustness to numerical errors in :func:`kdeplot` (:pr:`2862`).
102102

103+
- |Fix| Fixed a bug where :func:`rugplot` was ignoring expand_margins=False (:pr:`2953`).
104+
103105
- |Defaults| The `patch.facecolor` rc param is no longer set by :func:`set_palette` (or :func:`set_theme`). This should have no general effect, because the matplotlib default is now `"C0"` (:pr:`2906`).
104106

105107
- |Deps| Made `scipy` an optional dependency and added `pip install seaborn[stats]` as a method for ensuring the availability of compatible `scipy` and `statsmodels` libraries at install time. This has a few minor implications for existing code, which are explained in the Github pull request (:pr:`2398`).

seaborn/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def _default_color(method, hue, color, kws):
100100

101101
elif method.__name__ == "plot":
102102

103-
scout, = method([], [], **kws)
103+
scout, = method([], [], scalex=False, scaley=False, **kws)
104104
color = scout.get_color()
105105
scout.remove()
106106

tests/test_distributions.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,16 @@ def test_expand_margins(self, flat_array):
302302
assert x1 == x2
303303
assert y1 + height * 2 == pytest.approx(y2)
304304

305+
def test_multiple_rugs(self):
306+
307+
values = np.linspace(start=0, stop=1, num=5)
308+
ax = rugplot(x=values)
309+
ylim = ax.get_ylim()
310+
311+
rugplot(x=values, ax=ax, expand_margins=False)
312+
313+
assert ylim == ax.get_ylim()
314+
305315
def test_matplotlib_kwargs(self, flat_series):
306316

307317
lw = 2

0 commit comments

Comments
 (0)