Skip to content

Commit

Permalink
Fix histplot shrink with non-discrete bins (#2477)
Browse files Browse the repository at this point in the history
The code for shifting the shrunken bars assumed that discrete binning
was in effect. This is probably the only situation where shrinking
really makes sense, but there was no prevention or warning of getting
an innacurate result when using it with continuous bins.

Fixes #2476

(cherry picked from commit 6183f1e)
  • Loading branch information
mwaskom committed Aug 6, 2021
1 parent d244aca commit 8fb6629
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 7 deletions.
5 changes: 5 additions & 0 deletions doc/releases/v0.12.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ v0.12.0 (Unreleased)
- |Fix| In :func:`histplot` and :func:`kdeplot`, fixed a bug where the `multiple` was ignored when `hue` was provided as a vector without a name (:pr:`2462`).

- |Defaults| In :func:`displot`, the default alpha value now adjusts to a provided `multiple` parameter even when `hue` is not assigned (:pr:`2462`).
- |Fix| In :func:`histplot`, fixed a bug where using `shrink` with non-discrete bins shifted bar positions inaccurately (:pr:`2477`).

- |Fix| In :func:`displot`, fixed a bug where `common_norm` was ignored when `kind="hist"` and faceting was used without assigning `hue` (:pr:`2468`).

- |Defaults| In :func:`displot`, the default alpha value now adjusts to a provided `multiple` parameter even when `hue` is not assigned (:pr:`2462`).

- Made `scipy` an optional dependency and added `pip install seaborn[all]` 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`).

Expand Down
10 changes: 6 additions & 4 deletions seaborn/distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,9 +446,12 @@ def plot_univariate_histogram(
edges = np.power(10, edges)

# Pack the histogram data and metadata together
orig_widths = np.diff(edges)
widths = shrink * orig_widths
edges = edges[:-1] + (1 - shrink) / 2 * orig_widths
index = pd.MultiIndex.from_arrays([
pd.Index(edges[:-1], name="edges"),
pd.Index(np.diff(edges) * shrink, name="widths"),
pd.Index(edges, name="edges"),
pd.Index(widths, name="widths"),
])
hist = pd.Series(heights, index=index, name="heights")

Expand Down Expand Up @@ -551,9 +554,8 @@ def plot_univariate_histogram(
# Use matplotlib bar plotting

plot_func = ax.bar if self.data_variable == "x" else ax.barh
move = .5 * (1 - shrink)
artists = plot_func(
hist["edges"] + move,
hist["edges"],
hist["heights"] - bottom,
hist["widths"],
bottom,
Expand Down
17 changes: 14 additions & 3 deletions seaborn/tests/test_distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1520,10 +1520,21 @@ def test_weights_with_auto_bins(self, long_df):

def test_shrink(self, long_df):

f, (ax1, ax2) = plt.subplots(2)

bw = 2
shrink = .5
ax = histplot(long_df, x="x", binwidth=bw, shrink=shrink)
assert ax.patches[0].get_width() == bw * shrink
shrink = .4

histplot(long_df, x="x", binwidth=bw, ax=ax1)
histplot(long_df, x="x", binwidth=bw, shrink=shrink, ax=ax2)

for p1, p2 in zip(ax1.patches, ax2.patches):

w1, w2 = p1.get_width(), p2.get_width()
assert w2 == pytest.approx(shrink * w1)

x1, x2 = p1.get_x(), p2.get_x()
assert (x2 + w2 / 2) == pytest.approx(x1 + w1 / 2)

def test_log_scale_explicit(self, rng):

Expand Down

0 comments on commit 8fb6629

Please sign in to comment.