Repository: arviz-devs/arviz

Issue:
plot_ppc only plots one legend if there are multiple `observed`
**To Reproduce**
```python
import seaborn as sns
import pymc3 as pm
import pandas as pd
import arviz as az

iris = sns.load_dataset("iris")
y_s = pd.Categorical(iris["species"]).codes
x_n = "sepal_length"
x_0 = iris[x_n].values

with pm.Model() as lda:
    μ = pm.Normal("μ", mu=0, sd=10, shape=2)
    σ = pm.HalfNormal("σ", 10)
    setosa = pm.Normal("setosa", mu=μ[0], sd=σ, observed=x_0[:50])
    versicolor = pm.Normal("versicolor", mu=μ[1], sd=σ, observed=x_0[50:])
    bd = pm.Deterministic("bd", (μ[0] + μ[1]) / 2)
    trace_lda = pm.sample(1000, return_inferencedata=True)

with lda:
    ppc = pm.sample_posterior_predictive(trace=trace_lda)

az.plot_ppc(az.from_pymc3(posterior_predictive=ppc, model=lda))
```

![image](https://user-images.githubusercontent.com/33491632/107128606-f04f5680-68b6-11eb-80cd-0dc5ba7e86a7.png)


**Expected behavior**
I think I'd have expected both subplots to have a legend

**Additional context**
```python
> az.__version__, pm.__version__
('0.11.1', '3.11.0')
```


Discussion:
We can change it to optionally have more than one legend, but I think this default makes sense at it reduces redundancy (and the data/ink ratio).
Sure, but the second subplot is about versicolor (whilst the first one setosa), so is it really redundant to have an extra legend when the first one reads "observed setosa"?
Yes, if you have that information on the x_label. Of  course the current behavior is problematic, because we have one legend that is supposed to work for both plots but is referring only to the first.  So I suggest to have as default one legend and remove from the legend the name of the variable.
Agreed, that would be good - I'll work on a PR next week
Thanks @MarcoGorelli!

Resolving patch:
diff --git a/arviz/plots/backends/matplotlib/ppcplot.py b/arviz/plots/backends/matplotlib/ppcplot.py
--- a/arviz/plots/backends/matplotlib/ppcplot.py
+++ b/arviz/plots/backends/matplotlib/ppcplot.py
@@ -124,14 +124,12 @@ def plot_ppc(
             plot_kwargs = {"color": color, "alpha": alpha, "linewidth": 0.5 * linewidth}
             if dtype == "i":
                 plot_kwargs["drawstyle"] = "steps-pre"
-            ax_i.plot(
-                [], color=color, label="{} predictive {}".format(group.capitalize(), pp_var_name)
-            )
+            ax_i.plot([], color=color, label="{} predictive".format(group.capitalize()))
             if observed:
                 if dtype == "f":
                     plot_kde(
                         obs_vals,
-                        label="Observed {}".format(var_name),
+                        label="Observed",
                         plot_kwargs={"color": "k", "linewidth": linewidth, "zorder": 3},
                         fill_kwargs={"alpha": 0},
                         ax=ax_i,
@@ -144,7 +142,7 @@ def plot_ppc(
                     ax_i.plot(
                         bin_edges,
                         hist,
-                        label="Observed {}".format(var_name),
+                        label="Observed",
                         color="k",
                         linewidth=linewidth,
                         zorder=3,
@@ -179,7 +177,7 @@ def plot_ppc(
                         ax_i.plot(x_s, y_s, **plot_kwargs)
 
             if mean:
-                label = "{} predictive mean {}".format(group.capitalize(), pp_var_name)
+                label = "{} predictive mean".format(group.capitalize())
                 if dtype == "f":
                     rep = len(pp_densities)
                     len_density = len(pp_densities[0])
@@ -224,7 +222,7 @@ def plot_ppc(
                     *_empirical_cdf(obs_vals),
                     color="k",
                     linewidth=linewidth,
-                    label="Observed {}".format(var_name),
+                    label="Observed",
                     drawstyle=drawstyle,
                     zorder=3
                 )
@@ -253,7 +251,7 @@ def plot_ppc(
                     drawstyle=drawstyle,
                     linewidth=linewidth
                 )
-            ax_i.plot([], color=color, label="Posterior predictive {}".format(pp_var_name))
+            ax_i.plot([], color=color, label="Posterior predictive")
             if mean:
                 ax_i.plot(
                     *_empirical_cdf(pp_vals.flatten()),
@@ -261,7 +259,7 @@ def plot_ppc(
                     linestyle="--",
                     linewidth=linewidth * 1.5,
                     drawstyle=drawstyle,
-                    label="Posterior predictive mean {}".format(pp_var_name)
+                    label="Posterior predictive mean"
                 )
             ax_i.set_yticks([0, 0.5, 1])
 
@@ -276,7 +274,7 @@ def plot_ppc(
                             "linewidth": linewidth * 1.5,
                             "zorder": 3,
                         },
-                        label="Posterior predictive mean {}".format(pp_var_name),
+                        label="Posterior predictive mean",
                         ax=ax_i,
                         legend=legend,
                     )
@@ -290,7 +288,7 @@ def plot_ppc(
                         hist,
                         color=color,
                         linewidth=linewidth * 1.5,
-                        label="Posterior predictive mean {}".format(pp_var_name),
+                        label="Posterior predictive mean",
                         zorder=3,
                         linestyle="--",
                         drawstyle="steps-pre",
@@ -316,7 +314,7 @@ def plot_ppc(
                     color="k",
                     markersize=markersize,
                     alpha=alpha,
-                    label="Observed {}".format(var_name),
+                    label="Observed",
                     zorder=4,
                 )
 
@@ -340,9 +338,7 @@ def plot_ppc(
                         vals, yvals, "o", zorder=2, color=color, markersize=markersize, alpha=alpha
                     )
 
-            ax_i.plot(
-                [], color=color, marker="o", label="Posterior predictive {}".format(pp_var_name)
-            )
+            ax_i.plot([], color=color, marker="o", label="Posterior predictive")
 
             ax_i.set_yticks([])
 


Test patch:
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
@@ -794,6 +794,14 @@ def test_plot_ppc_bad_ax(models, fig_ax):
         plot_ppc(models.model_1, ax=ax2)
 
 
+def test_plot_legend(models):
+    axes = plot_ppc(models.model_1)
+    legend_texts = axes.get_legend().get_texts()
+    result = [i.get_text() for i in legend_texts]
+    expected = ["Posterior predictive", "Observed", "Posterior predictive mean"]
+    assert result == expected
+
+
 @pytest.mark.parametrize("var_names", (None, "mu", ["mu", "tau"]))
 def test_plot_violin(models, var_names):
     axes = plot_violin(models.model_1, var_names=var_names)