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
  • Loading branch information
mwaskom authored Feb 10, 2021
1 parent b1dc1bc commit 6183f1e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
2 changes: 2 additions & 0 deletions doc/releases/v0.12.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ 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`).

- |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`).
Expand Down
10 changes: 6 additions & 4 deletions seaborn/distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -459,9 +459,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 @@ -536,9 +539,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 @@ -1604,10 +1604,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 6183f1e

Please sign in to comment.