Repository: mwaskom/seaborn

Issue:
`relplot` `kind='scatter'` incompatible with `units` keyword argument
When calling `seaborn.relplot` with `kind='scatter' and passing a value for `units`, an error is raised:

```python

import seaborn as sns

from matplotlib import pyplot as plt

sns.set_theme(style="ticks")

dots = sns.load_dataset("dots")

# Plot the lines on two facets, successfully:
sns.relplot(
    data=dots,
    x="time",
    y="firing_rate",
    units="coherence",
    kind="line",
    estimator=None
)

plt.show()

# Failure:
sns.relplot(
    data=dots,
    x="time",
    y="firing_rate",
    units="coherence",
    kind="scatter"
)

plt.show()
```

``` shell
Traceback (most recent call last):
  File "/Users/ahalev/miniforge3/envs/forge_rl_env/lib/python3.9/contextlib.py", line 135, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/ahalev/miniforge3/envs/forge_rl_env/lib/python3.9/site-packages/matplotlib/cbook/__init__.py", line 2029, in _setattr_cm
    yield
  File "/Users/ahalev/miniforge3/envs/forge_rl_env/lib/python3.9/site-packages/matplotlib/artist.py", line 1197, in _update_props
    raise AttributeError(
AttributeError: PathCollection.set() got an unexpected keyword argument 'units'
python-BaseException
```

This is a bit of a vague exception in my opinion and is caused by the `units` value getting picked up in `seaborn.relational._ScatterPlotter.get_semantics` and then being passed to the plotter function.

I could be convinced that `units` is incompatible with `kind='scatter'`, but it seems to me like it should be ignored or a clearer exception message should be raised instead of this behavior. A check to pop `units` in a scatter plot could alleviate this.

Discussion:

Patch:
diff --git a/seaborn/relational.py b/seaborn/relational.py
index e0af083d..67a5d4d9 100644
--- a/seaborn/relational.py
+++ b/seaborn/relational.py
@@ -837,9 +837,15 @@ def relplot(
         kwargs.pop("ax")
 
     # Use the full dataset to map the semantics
+    variables = dict(x=x, y=y, hue=hue, size=size, style=style)
+    if kind == "line":
+        variables["units"] = units
+    elif units is not None:
+        msg = "The `units` parameter of `relplot` has no effect with kind='scatter'"
+        warnings.warn(msg, stacklevel=2)
     p = Plotter(
         data=data,
-        variables=dict(x=x, y=y, hue=hue, size=size, style=style, units=units),
+        variables=variables,
         legend=legend,
     )
     p.map_hue(palette=palette, order=hue_order, norm=hue_norm)
@@ -888,15 +894,13 @@ def relplot(
         plot_kws.pop("dashes")
 
     # Add the grid semantics onto the plotter
-    grid_semantics = "row", "col"
-    p.assign_variables(
-        data=data,
-        variables=dict(
-            x=x, y=y,
-            hue=hue, size=size, style=style, units=units,
-            row=row, col=col,
-        ),
+    grid_variables = dict(
+        x=x, y=y, row=row, col=col,
+        hue=hue, size=size, style=style,
     )
+    if kind == "line":
+        grid_variables["units"] = units
+    p.assign_variables(data, grid_variables)
 
     # Define the named variables for plotting on each facet
     # Rename the variables with a leading underscore to avoid
@@ -910,7 +914,7 @@ def relplot(
         # Handle faceting variables that lack name information
         if var in p.variables and p.variables[var] is None:
             p.variables[var] = f"_{var}_"
-    grid_kws = {v: p.variables.get(v) for v in grid_semantics}
+    grid_kws = {v: p.variables.get(v) for v in ["row", "col"]}
 
     # Rename the columns of the plot_data structure appropriately
     new_cols = plot_variables.copy()


Test patch:
diff --git a/tests/_marks/test_line.py b/tests/_marks/test_line.py
index 1339b859..0df9f4d1 100644
--- a/tests/_marks/test_line.py
+++ b/tests/_marks/test_line.py
@@ -181,7 +181,7 @@ class TestPaths:
 
         assert same_color(lines.get_color().squeeze(), m.color)
         assert lines.get_linewidth().item() == m.linewidth
-        assert lines.get_linestyle()[0] == (0, list(m.linestyle))
+        assert lines.get_dashes()[0] == (0, list(m.linestyle))
 
     def test_mapped_properties(self):
 
diff --git a/tests/test_relational.py b/tests/test_relational.py
index 4056fc35..a7204999 100644
--- a/tests/test_relational.py
+++ b/tests/test_relational.py
@@ -666,6 +666,12 @@ class TestRelationalPlotter(Helpers):
         )
         assert g.axes.shape == (1, len(col_data.unique()))
 
+    def test_relplot_scatter_units(self, long_df):
+
+        with pytest.warns(UserWarning, match="The `units` parameter"):
+            g = relplot(long_df, x="x", y="y", units="a")
+        assert g.ax is not None
+
     def test_ax_kwarg_removal(self, long_df):
 
         f, ax = plt.subplots()