Repository: arviz-devs/arviz

Issue:
plot_posterior doesn' accept label as kwarg
I think this is related to how we pass kwargs downstream to plot_dist or plot_kde... will look into it at some point unless someone beats me to it. My hunch is that plot_dist and plot_kde have a `label` argument and pass it explicitly to matplotlib instead of doing `setdefault` so if a label is passed via kwargs too it becomes a duplicated argument and errors out

Fixing this would allow using plot_posterior to overlay multiple distributions while having a legend.



Discussion:
https://github.com/arviz-devs/arviz/blob/bd0b786e6ab6ea5767110cf46fe0650c869d02f2/arviz/plots/backends/matplotlib/posteriorplot.py#L311-L321

As label is not added here, it will be considering default value of label (i.e. None).
Would None value of label still be conflicting with label passed via kwargs?
`plot_posterior` does not set the label but `plot_kde` does:

https://github.com/arviz-devs/arviz/blob/1997afe0cf92d32e6ee71a94226fc458ace22313/arviz/plots/backends/matplotlib/kdeplot.py#L147

it should be set as `setdefault` to `plot_kwargs` or `fill_kwargs` or the corresponding kwargs (which one may depend on the type of plot so be careful here). Otherwise, if label is passed via kwargs, matplotlib gets two different instances of the same keyword argument and errors out.
Sure, then `label` shouldn't be pass as an individual argument in the `plot()` because it would already be there in kwargs. Right?
Exactly, more or less like with linewidth:

https://github.com/arviz-devs/arviz/blob/1997afe0cf92d32e6ee71a94226fc458ace22313/arviz/plots/backends/matplotlib/kdeplot.py#L86

with the main difference that linewidth always goes into `plot_kwargs` and `label` may go to fill kwargs or so depending on other arguments

Resolving patch:
diff --git a/arviz/plots/backends/bokeh/kdeplot.py b/arviz/plots/backends/bokeh/kdeplot.py
--- a/arviz/plots/backends/bokeh/kdeplot.py
+++ b/arviz/plots/backends/bokeh/kdeplot.py
@@ -147,6 +147,8 @@ def plot_kde(
                     patch = ax.patch(patch_y, patch_x, **fill_kwargs)
                 glyphs.append(patch)
 
+            if label is not None:
+                plot_kwargs.setdefault("legend_label", label)
             if not rotated:
                 line = ax.line(x, density, **plot_kwargs)
             else:
diff --git a/arviz/plots/backends/matplotlib/kdeplot.py b/arviz/plots/backends/matplotlib/kdeplot.py
--- a/arviz/plots/backends/matplotlib/kdeplot.py
+++ b/arviz/plots/backends/matplotlib/kdeplot.py
@@ -144,11 +144,13 @@ def plot_kde(
         else:
             fill_kwargs.setdefault("alpha", 0)
             if fill_kwargs.get("alpha") == 0:
-                ax.plot(x, density, label=label, **plot_kwargs)
+                label = plot_kwargs.setdefault("label", label)
+                ax.plot(x, density, **plot_kwargs)
                 fill_func(fill_x, fill_y, **fill_kwargs)
             else:
+                label = fill_kwargs.setdefault("label", label)
                 ax.plot(x, density, **plot_kwargs)
-                fill_func(fill_x, fill_y, label=label, **fill_kwargs)
+                fill_func(fill_x, fill_y, **fill_kwargs)
         if legend and label:
             ax.legend()
     else:


Test patch:
diff --git a/arviz/tests/base_tests/test_plots_bokeh.py b/arviz/tests/base_tests/test_plots_bokeh.py
--- a/arviz/tests/base_tests/test_plots_bokeh.py
+++ b/arviz/tests/base_tests/test_plots_bokeh.py
@@ -992,7 +992,7 @@ def test_plot_ppc_ax(models, kind):
         {"point_estimate": "mode"},
         {"point_estimate": "median"},
         {"point_estimate": None},
-        {"hdi_prob": "hide"},
+        {"hdi_prob": "hide", "legend_label": ""},
         {"ref_val": 0},
         {"ref_val": None},
         {"ref_val": {"mu": [{"ref_val": 1}]}},
diff --git a/arviz/tests/base_tests/test_plots_matplotlib.py b/arviz/tests/base_tests/test_plots_matplotlib.py
--- a/arviz/tests/base_tests/test_plots_matplotlib.py
+++ b/arviz/tests/base_tests/test_plots_matplotlib.py
@@ -927,7 +927,7 @@ def test_plot_rank(models, kwargs):
         {"rope": {"mu": [{"rope": (-2, 2)}], "theta": [{"school": "Choate", "rope": (2, 4)}]}},
         {"point_estimate": "mode"},
         {"point_estimate": "median"},
-        {"hdi_prob": "hide"},
+        {"hdi_prob": "hide", "label": ""},
         {"point_estimate": None},
         {"ref_val": 0},
         {"ref_val": None},