Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: shifting margins caused by multiple rugplots #2953

Merged
merged 3 commits into from
Aug 13, 2022
Merged

Fix: shifting margins caused by multiple rugplots #2953

merged 3 commits into from
Aug 13, 2022

Conversation

beyarkay
Copy link
Contributor

@beyarkay beyarkay commented Aug 12, 2022

This fix prevents margins from increasing when multiple rugplots are
added to the same ax, even if expand_margins is False.

Screenshot 2022-08-12 at 22 11 42

As a minimum reproducible example (which is similar to the added unit test):

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:

$ 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):

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:

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.

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`.
@beyarkay
Copy link
Contributor Author

I saw that the unit test doesn't quite fit the format of the others, so let me know if I should change that. I'm happy to do so if it'll leave you with a more consistent code base (:

Copy link
Owner

@mwaskom mwaskom left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great sleuthing, and thanks for the fix!

Basic structure of the test looks totally fine, just left a couple of comments about keeping it as simple as possible.

Pleas also add an entry to the v0.12 release notes, e.g. "Fixed a bug where :func:rugplot was ignoring expand_margins=False". This should be categorized as a |Fix|, and please link back to the PR so you get credit!

tests/test_distributions.py Outdated Show resolved Hide resolved
tests/test_distributions.py Outdated Show resolved Hide resolved
tests/test_distributions.py Outdated Show resolved Hide resolved
tests/test_distributions.py Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Aug 12, 2022

Codecov Report

Merging #2953 (4328e90) into master (2c3ea6f) will increase coverage by 0.00%.
The diff coverage is 100.00%.

❗ Current head 4328e90 differs from pull request most recent head 1552b5f. Consider uploading reports for the commit 1552b5f to get more accurate results

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2953   +/-   ##
=======================================
  Coverage   98.31%   98.31%           
=======================================
  Files          69       69           
  Lines       23030    23039    +9     
=======================================
+ Hits        22641    22650    +9     
  Misses        389      389           
Impacted Files Coverage Δ
seaborn/utils.py 95.08% <100.00%> (ø)
tests/test_distributions.py 99.79% <100.00%> (+<0.01%) ⬆️

@beyarkay
Copy link
Contributor Author

And thank you for the entire friggin' library!😁

It's getting late at my local time so I'll respond properly in the morning, but I don't see any remarks that I disagree with.

@beyarkay
Copy link
Contributor Author

Hang on, I forgot to remove the import.

@beyarkay
Copy link
Contributor Author

There we go, let me know if there are any other changes 😄

As a side note, is there a release date planned for v0.12? I came across this bug while working on a university project so it would be nice to see the update roll out.

@mwaskom
Copy link
Owner

mwaskom commented Aug 13, 2022

Thanks again!

is there a release date planned for v0.12?

No specific date planned, but I would expect v0.12.0 by the end of the month.

@mwaskom mwaskom merged commit 7081223 into mwaskom:master Aug 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants