Repository: mwaskom/seaborn

Issue:
Bivariate displot and various bin size does not work in 2D
~~~python
sns.__version__, matplotlib.__version__
('0.11.1', '3.4.2')
~~~

This works

~~~python

import seaborn as sns

titanic = sns.load_dataset("titanic")
sns.displot(
    data=titanic,
    x="age",
    y='fare',
    col="survived",
    common_bins=True,
)
~~~
This does not 

~~~python

import seaborn as sns

titanic = sns.load_dataset("titanic")
sns.displot(
    data=titanic,
    x="age",
    y='fare',
    col="survived",
    common_bins=False,
)

/home/samuel/miniconda3/envs/py38/lib/python3.8/site-packages/numpy/core/fromnumeric.py:87: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  return ufunc.reduce(obj, axis, dtype, out, **passkwargs)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_10645/1850804617.py in <module>
      2 
      3 titanic = sns.load_dataset("titanic")
----> 4 sns.displot(
      5     data=titanic,
      6     x="age",

~/miniconda3/envs/py38/lib/python3.8/site-packages/seaborn/distributions.py in displot(data, x, y, hue, row, col, weights, kind, rug, rug_kws, log_scale, legend, palette, hue_order, hue_norm, color, col_wrap, row_order, col_order, height, aspect, facet_kws, **kwargs)
   2230 
   2231             _assign_default_kwargs(hist_kws, p.plot_bivariate_histogram, histplot)
-> 2232             p.plot_bivariate_histogram(**hist_kws)
   2233 
   2234     elif kind == "kde":

~/miniconda3/envs/py38/lib/python3.8/site-packages/seaborn/distributions.py in plot_bivariate_histogram(self, common_bins, common_norm, thresh, pthresh, pmax, color, legend, cbar, cbar_ax, cbar_kws, estimate_kws, **plot_kws)
    763                 vmax = self._quantile_to_level(full_heights, pmax)
    764             else:
--> 765                 vmax = plot_kws.pop("vmax", np.max(full_heights))
    766         else:
    767             vmax = None

<__array_function__ internals> in amax(*args, **kwargs)

~/miniconda3/envs/py38/lib/python3.8/site-packages/numpy/core/fromnumeric.py in amax(a, axis, out, keepdims, initial, where)
   2703     5
   2704     """
-> 2705     return _wrapreduction(a, np.maximum, 'max', axis, None, out,
   2706                           keepdims=keepdims, initial=initial, where=where)
   2707 

~/miniconda3/envs/py38/lib/python3.8/site-packages/numpy/core/fromnumeric.py in _wrapreduction(obj, ufunc, method, axis, dtype, out, **kwargs)
     85                 return reduction(axis=axis, out=out, **passkwargs)
     86 
---> 87     return ufunc.reduce(obj, axis, dtype, out, **passkwargs)
     88 
     89 

ValueError: could not broadcast input array from shape (16,53) into shape (16)
~~~

I thought asking for different bins size (in a more complicated example) would work, but apparently adding a y variable make stuff blows up. Asking only for a x variable or more rows/columns seems fine though, so I'm wondering if the bivariate case is supposed to 1. work or 2. is allowing something which is not supposed to be working and should instead report a warning/error for that case.

Discussion:
codecov[bot]: # [Codecov](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) Report
> Merging [#2640](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) (e2a7960) into [master](https://codecov.io/gh/mwaskom/seaborn/commit/bfb7a046183647b145ad69600901dded26aa8292?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) (bfb7a04) will **decrease** coverage by `0.46%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/mwaskom/seaborn/pull/2640/graphs/tree.svg?width=650&height=150&src=pr&token=SLuzHnA9Bl&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom)](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom)

```diff
@@            Coverage Diff             @@
##           master    #2640      +/-   ##
==========================================
- Coverage   97.43%   96.97%   -0.47%     
==========================================
  Files          17       17              
  Lines        6405     6373      -32     
==========================================
- Hits         6241     6180      -61     
- Misses        164      193      +29     
```


| [Impacted Files](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) | Coverage Δ | |
|---|---|---|
| [seaborn/distributions.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9kaXN0cmlidXRpb25zLnB5) | `96.06% <100.00%> (-0.35%)` | :arrow_down: |
| [seaborn/\_docstrings.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9fZG9jc3RyaW5ncy5weQ==) | `89.18% <0.00%> (-10.82%)` | :arrow_down: |
| [seaborn/\_statistics.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9fc3RhdGlzdGljcy5weQ==) | `98.46% <0.00%> (-1.54%)` | :arrow_down: |
| [seaborn/regression.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9yZWdyZXNzaW9uLnB5) | `96.65% <0.00%> (-1.23%)` | :arrow_down: |
| [seaborn/matrix.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9tYXRyaXgucHk=) | `94.96% <0.00%> (-0.92%)` | :arrow_down: |
| [seaborn/categorical.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9jYXRlZ29yaWNhbC5weQ==) | `98.01% <0.00%> (-0.53%)` | :arrow_down: |
| [seaborn/utils.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi91dGlscy5weQ==) | `94.27% <0.00%> (-0.34%)` | :arrow_down: |
| [seaborn/\_core.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9fY29yZS5weQ==) | `98.33% <0.00%> (-0.15%)` | :arrow_down: |
| [seaborn/axisgrid.py](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9heGlzZ3JpZC5weQ==) | `95.55% <0.00%> (-0.05%)` | :arrow_down: |
| ... and [2 more](https://codecov.io/gh/mwaskom/seaborn/pull/2640/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom). Last update [bfb7a04...e2a7960](https://codecov.io/gh/mwaskom/seaborn/pull/2640?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom).


Patch:
diff --git a/doc/releases/v0.11.2.txt b/doc/releases/v0.11.2.txt
index 37318252..3c4ae495 100644
--- a/doc/releases/v0.11.2.txt
+++ b/doc/releases/v0.11.2.txt
@@ -36,6 +36,8 @@ This is a minor release that addresses issues in the v0.11 series and adds a sma
 
 - |Fix| 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:`displot`, fixed a bug that caused faceted 2D histograms to error out with `common_bins=False` (:pr:`2640`).
+
 - |Fix| In :func:`rugplot`, fixed a bug that prevented the use of datetime data (:pr:`2458`).
 
 - |Fix| In :func:`relplot` and :func:`displot`, fixed a bug where the dataframe attached to the returned `FacetGrid` object dropped columns that were not used in the plot (:pr:`2623`).
diff --git a/seaborn/distributions.py b/seaborn/distributions.py
index 1b0210b7..08be0408 100644
--- a/seaborn/distributions.py
+++ b/seaborn/distributions.py
@@ -763,7 +763,7 @@ class _DistributionPlotter(VectorPlotter):
             if pmax is not None:
                 vmax = self._quantile_to_level(full_heights, pmax)
             else:
-                vmax = plot_kws.pop("vmax", np.max(full_heights))
+                vmax = plot_kws.pop("vmax", max(map(np.max, full_heights)))
         else:
             vmax = None
 


Test patch:
diff --git a/seaborn/tests/test_distributions.py b/seaborn/tests/test_distributions.py
index d98b3a7d..0f34f9cd 100644
--- a/seaborn/tests/test_distributions.py
+++ b/seaborn/tests/test_distributions.py
@@ -1794,6 +1794,28 @@ class TestHistPlotBivariate:
                 assert path.vertices[0, 0] == x
                 assert path.vertices[0, 1] == y
 
+    def test_mesh_with_col_unique_bins(self, long_df):
+
+        g = displot(long_df, x="x", y="y", col="c", common_bins=False)
+
+        for i, sub_df in long_df.groupby("c"):
+
+            hist = Histogram()
+
+            mesh = g.axes.flat[i].collections[0]
+            mesh_data = mesh.get_array()
+
+            counts, (x_edges, y_edges) = hist(sub_df["x"], sub_df["y"])
+
+            assert_array_equal(mesh_data.data, counts.T.flat)
+            assert_array_equal(mesh_data.mask, counts.T.flat == 0)
+
+            edges = itertools.product(y_edges[:-1], x_edges[:-1])
+            for i, (y, x) in enumerate(edges):
+                path = mesh.get_paths()[i]
+                assert path.vertices[0, 0] == x
+                assert path.vertices[0, 1] == y
+
     def test_mesh_log_scale(self, rng):
 
         x, y = rng.lognormal(0, 1, (2, 1000))