Repository: mwaskom/seaborn

Issue:
shrink parameter in histplot shifts data
The smaller the value of the `shrink` parameter, the more the values in the histogram get shifted towards positive values.

`import seaborn as sns`
`import numpy as np`

`r = np.random.random(100)`


`sns.histplot(r);`

`sns.histplot(r, shrink=0.5);`

![Screen Shot 2021-02-08 at 10 11 43 PM](https://user-images.githubusercontent.com/35338267/107310557-aacb8e80-6a5a-11eb-991e-d4d4cbfd15b7.png)

![Screen Shot 2021-02-08 at 10 15 46 PM](https://user-images.githubusercontent.com/35338267/107310839-36ddb600-6a5b-11eb-9f0d-54ae495f14cc.png)


Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=h1) Report
> Merging [#2477](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=desc) (af47896) into [master](https://codecov.io/gh/mwaskom/seaborn/commit/8f83a4df5edf08867a556af4fc993e4e0b07b80f?el=desc) (8f83a4d) will **decrease** coverage by `0.47%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/mwaskom/seaborn/pull/2477/graphs/tree.svg?width=650&height=150&src=pr&token=SLuzHnA9Bl)](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #2477      +/-   ##
==========================================
- Coverage   97.45%   96.97%   -0.48%     
==========================================
  Files          17       17              
  Lines        6315     6285      -30     
==========================================
- Hits         6154     6095      -59     
- Misses        161      190      +29     
```


| [Impacted Files](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [seaborn/distributions.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9kaXN0cmlidXRpb25zLnB5) | `95.99% <100.00%> (-0.34%)` | :arrow_down: |
| [seaborn/\_docstrings.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9fZG9jc3RyaW5ncy5weQ==) | `89.18% <0.00%> (-10.82%)` | :arrow_down: |
| [seaborn/\_statistics.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9fc3RhdGlzdGljcy5weQ==) | `98.43% <0.00%> (-1.57%)` | :arrow_down: |
| [seaborn/regression.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9yZWdyZXNzaW9uLnB5) | `96.51% <0.00%> (-1.28%)` | :arrow_down: |
| [seaborn/matrix.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9tYXRyaXgucHk=) | `94.94% <0.00%> (-0.92%)` | :arrow_down: |
| [seaborn/categorical.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9jYXRlZ29yaWNhbC5weQ==) | `98.01% <0.00%> (-0.53%)` | :arrow_down: |
| [seaborn/utils.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi91dGlscy5weQ==) | `94.21% <0.00%> (-0.35%)` | :arrow_down: |
| [seaborn/\_core.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9fY29yZS5weQ==) | `98.47% <0.00%> (-0.15%)` | :arrow_down: |
| [seaborn/axisgrid.py](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree#diff-c2VhYm9ybi9heGlzZ3JpZC5weQ==) | `95.57% <0.00%> (-0.05%)` | :arrow_down: |
| ... and [2 more](https://codecov.io/gh/mwaskom/seaborn/pull/2477/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=footer). Last update [8f83a4d...af47896](https://codecov.io/gh/mwaskom/seaborn/pull/2477?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/doc/releases/v0.12.0.txt b/doc/releases/v0.12.0.txt
index fbbc2030..b506c8fd 100644
--- a/doc/releases/v0.12.0.txt
+++ b/doc/releases/v0.12.0.txt
@@ -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`).
diff --git a/seaborn/distributions.py b/seaborn/distributions.py
index 47f59cbf..b227a268 100644
--- a/seaborn/distributions.py
+++ b/seaborn/distributions.py
@@ -459,9 +459,12 @@ class _DistributionPlotter(VectorPlotter):
                 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")
 
@@ -536,9 +539,8 @@ class _DistributionPlotter(VectorPlotter):
                 # 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,


Test patch:
diff --git a/seaborn/tests/test_distributions.py b/seaborn/tests/test_distributions.py
index f78e0669..f4e9c302 100644
--- a/seaborn/tests/test_distributions.py
+++ b/seaborn/tests/test_distributions.py
@@ -1604,10 +1604,21 @@ class TestHistPlotUnivariate(SharedAxesLevelTests):
 
     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):