Repository: mwaskom/seaborn

Issue:
seaborn.objects: facet doesn't show x tick labels for the bottom subplots in each column if the corresponding last row is empty
See the title. In the example below, I would expect the subplots H and I show the x tick labels, just like subplot J. Thank you. 

```python
import seaborn as sns
import seaborn.objects as so

diamonds = sns.load_dataset("diamonds")

p = so.Plot(diamonds, x="carat", y="price").add(so.Dots())
p.facet("color", wrap=3)
```
![test](https://github.com/mwaskom/seaborn/assets/47764802/2684b871-4ee7-4ff2-af47-1e186881c647)



Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/mwaskom/seaborn/pull/3600?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`b49e595`)](https://app.codecov.io/gh/mwaskom/seaborn/commit/b49e595360ae8c065410691f9f507b7464157ad5?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) 98.52% compared to head [(`e196f40`)](https://app.codecov.io/gh/mwaskom/seaborn/pull/3600?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) 98.52%.

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/mwaskom/seaborn/pull/3600/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://app.codecov.io/gh/mwaskom/seaborn/pull/3600?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    #3600   +/-   ##
=======================================
  Coverage   98.52%   98.52%           
=======================================
  Files          75       75           
  Lines       24701    24708    +7     
=======================================
+ Hits        24336    24343    +7     
  Misses        365      365           
```


| [Files](https://app.codecov.io/gh/mwaskom/seaborn/pull/3600?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom) | Coverage Δ | |
|---|---|---|
| [seaborn/\_core/plot.py](https://app.codecov.io/gh/mwaskom/seaborn/pull/3600?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-c2VhYm9ybi9fY29yZS9wbG90LnB5) | `99.15% <100.00%> (+<0.01%)` | :arrow_up: |
| [tests/\_core/test\_plot.py](https://app.codecov.io/gh/mwaskom/seaborn/pull/3600?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Michael+Waskom#diff-dGVzdHMvX2NvcmUvdGVzdF9wbG90LnB5) | `98.84% <100.00%> (+<0.01%)` | :arrow_up: |

</details>

Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 85df393f..11ab24f9 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -16,6 +16,7 @@ env:
   NB_KERNEL: python
   MPLBACKEND: Agg
   SEABORN_DATA: ${{ github.workspace }}/seaborn-data
+  PYDEVD_DISABLE_FILE_VALIDATION: 1
 
 jobs:
   build-docs:
@@ -35,7 +36,8 @@ jobs:
 
       - name: Install pandoc
         run: |
-          sudo apt-get install pandoc
+          wget https://github.com/jgm/pandoc/releases/download/3.1.11/pandoc-3.1.11-1-amd64.deb
+          sudo dpkg -i pandoc-3.1.11-1-amd64.deb
 
       - name: Cache datasets
         run: |
diff --git a/doc/whatsnew/v0.13.1.rst b/doc/whatsnew/v0.13.1.rst
new file mode 100644
index 00000000..b4bc52ef
--- /dev/null
+++ b/doc/whatsnew/v0.13.1.rst
@@ -0,0 +1,16 @@
+v0.13.1 (Unreleased)
+--------------------
+
+- |Feature| Added support for weighted mean estimation (with boostrap CIs) in :func:`lineplot`, :func:`barplot`, :func:`pointplot`, and :class:`objects.Est` (:pr:`3580`, :pr:`3586`).
+
+- |Feature| Added the `extent` option to :meth:`Plot.layout` (:pr:`3552`).
+
+- |Fix| Fixed a bug in :func:`catplot` where a blank legend would be added when `hue` was redundantly assigned (:pr:`3540`).
+
+- |Fix| Fixed a bug in :func:`catplot` where the `edgecolor` parameter was ignored with `kind="bar"` (:pr:`3547`).
+
+- |Fix| Fixed a bug in :func:`boxplot` where an exception was raised when using the matplotlib `bootstrap` option (:pr:`3562`).
+
+- |Fix| Fixed a bug in :func:`lineplot` where an exception was raised when `hue` was assigned with an empty dataframe (:pr:`3569`).
+
+- |Fix| Fixed a regression in v0.13.0 that triggered an exception when working with non-numpy data types (:pr:`3516`).
diff --git a/seaborn/_core/plot.py b/seaborn/_core/plot.py
index 39ccd2e0..a563b651 100644
--- a/seaborn/_core/plot.py
+++ b/seaborn/_core/plot.py
@@ -1177,6 +1177,8 @@ class Plotter:
                     )
                 )
                 for group in ("major", "minor"):
+                    side = {"x": "bottom", "y": "left"}[axis]
+                    axis_obj.set_tick_params(**{f"label{side}": show_tick_labels})
                     for t in getattr(axis_obj, f"get_{group}ticklabels")():
                         t.set_visible(show_tick_labels)
 
diff --git a/seaborn/categorical.py b/seaborn/categorical.py
index 2e12141a..ab9f9680 100644
--- a/seaborn/categorical.py
+++ b/seaborn/categorical.py
@@ -392,6 +392,11 @@ class _CategoricalPlotter(VectorPlotter):
 
     def _dodge(self, keys, data):
         """Apply a dodge transform to coordinates in place."""
+        if "hue" not in self.variables:
+            # Short-circuit if hue variable was not assigned
+            # We could potentially warn when hue=None, dodge=True, user may be confused
+            # But I think it's fine to just treat it as a no-op.
+            return
         hue_idx = self._hue_map.levels.index(keys["hue"])
         n = len(self._hue_map.levels)
         data["width"] /= n
diff --git a/seaborn/distributions.py b/seaborn/distributions.py
index 4953f01d..e3d57c9a 100644
--- a/seaborn/distributions.py
+++ b/seaborn/distributions.py
@@ -1593,7 +1593,7 @@ def kdeplot(
     # Handle (past) deprecation of `data2`
     if "data2" in kwargs:
         msg = "`data2` has been removed (replaced by `y`); please update your code."
-        TypeError(msg)
+        raise TypeError(msg)
 
     # Handle deprecation of `vertical`
     vertical = kwargs.pop("vertical", None)
diff --git a/seaborn/rcmod.py b/seaborn/rcmod.py
index 978dc175..de238323 100644
--- a/seaborn/rcmod.py
+++ b/seaborn/rcmod.py
@@ -336,9 +336,8 @@ def plotting_context(context=None, font_scale=1, rc=None):
     """
     Get the parameters that control the scaling of plot elements.
 
-    This affects things like the size of the labels, lines, and other elements
-    of the plot, but not the overall style. This is accomplished using the
-    matplotlib rcParams system.
+    These parameters correspond to label size, line thickness, etc. For more
+    information, see the :doc:`aesthetics tutorial <../tutorial/aesthetics>`.
 
     The base context is "notebook", and the other contexts are "paper", "talk",
     and "poster", which are version of the notebook parameters scaled by different
@@ -437,9 +436,9 @@ def set_context(context=None, font_scale=1, rc=None):
     """
     Set the parameters that control the scaling of plot elements.
 
-    This affects things like the size of the labels, lines, and other elements
-    of the plot, but not the overall style. This is accomplished using the
-    matplotlib rcParams system.
+    These parameters correspond to label size, line thickness, etc.
+    Calling this function modifies the global matplotlib `rcParams`. For more
+    information, see the :doc:`aesthetics tutorial <../tutorial/aesthetics>`.
 
     The base context is "notebook", and the other contexts are "paper", "talk",
     and "poster", which are version of the notebook parameters scaled by different
diff --git a/seaborn/regression.py b/seaborn/regression.py
index 5a16fc96..5e5503a4 100644
--- a/seaborn/regression.py
+++ b/seaborn/regression.py
@@ -574,7 +574,7 @@ _regression_docs.update(_facet_docs)
 
 
 def lmplot(
-    data=None, *,
+    data, *,
     x=None, y=None, hue=None, col=None, row=None,
     palette=None, col_wrap=None, height=5, aspect=1, markers="o",
     sharex=None, sharey=None, hue_order=None, col_order=None, row_order=None,


Test patch:
diff --git a/tests/_core/test_plot.py b/tests/_core/test_plot.py
index 97e55e55..cdf3e52c 100644
--- a/tests/_core/test_plot.py
+++ b/tests/_core/test_plot.py
@@ -1852,6 +1852,12 @@ class TestLabelVisibility:
         for s in subplots[1:]:
             ax = s["ax"]
             assert ax.xaxis.get_label().get_visible()
+            # mpl3.7 added a getter for tick params, but both yaxis and xaxis return
+            # the same entry of "labelleft" instead of  "labelbottom" for xaxis
+            if not _version_predates(mpl, "3.7"):
+                assert ax.xaxis.get_tick_params()["labelleft"]
+            else:
+                assert len(ax.get_xticklabels()) > 0
             assert all(t.get_visible() for t in ax.get_xticklabels())
 
         for s in subplots[1:-1]:
@@ -1876,6 +1882,12 @@ class TestLabelVisibility:
         for s in subplots[-2:]:
             ax = s["ax"]
             assert ax.xaxis.get_label().get_visible()
+            # mpl3.7 added a getter for tick params, but both yaxis and xaxis return
+            # the same entry of "labelleft" instead of  "labelbottom" for xaxis
+            if not _version_predates(mpl, "3.7"):
+                assert ax.xaxis.get_tick_params()["labelleft"]
+            else:
+                assert len(ax.get_xticklabels()) > 0
             assert all(t.get_visible() for t in ax.get_xticklabels())
 
         for s in subplots[:-2]:
diff --git a/tests/test_categorical.py b/tests/test_categorical.py
index 98764529..eaca2e78 100644
--- a/tests/test_categorical.py
+++ b/tests/test_categorical.py
@@ -999,6 +999,16 @@ class TestBoxPlot(SharedAxesLevelTests, SharedPatchArtistTests):
                 widths.append(np.ptp(coords))
         assert np.std(widths) == approx(0)
 
+    def test_dodge_without_hue(self, long_df):
+
+        ax = boxplot(long_df, x="a", y="y", dodge=True)
+        bxp, = ax.containers
+        levels = categorical_order(long_df["a"])
+        for i, level in enumerate(levels):
+            data = long_df.loc[long_df["a"] == level, "y"]
+            self.check_box(bxp[i], data, "x", i)
+            self.check_whiskers(bxp[i], data, "x", i)
+
     @pytest.mark.parametrize("orient", ["x", "y"])
     def test_log_data_scale(self, long_df, orient):
 
diff --git a/tests/test_distributions.py b/tests/test_distributions.py
index e5f5c4aa..0df1a15b 100644
--- a/tests/test_distributions.py
+++ b/tests/test_distributions.py
@@ -920,6 +920,10 @@ class TestKDEPlotUnivariate(SharedAxesLevelTests):
 
         assert ax.legend_ is None
 
+    def test_replaced_kws(self, long_df):
+        with pytest.raises(TypeError, match=r"`data2` has been removed"):
+            kdeplot(data=long_df, x="x", data2="y")
+
 
 class TestKDEPlotBivariate: