---
title: "Summary diagrams and diagnostic plots"
author: "Alexandre M.J.-C. Wadoux"
output: rmarkdown::html_vignette
bibliography: references.bib
link-citations: true
vignette: >
  %\VignetteIndexEntry{Summary diagrams and diagnostic plots}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 6
)
```

## 1. Why use summary diagrams?

The performance of a quantitative prediction cannot usually be described
adequately by a single statistic. Bias, overall prediction error, correlation,
and the ability to reproduce the variability of the observations describe
different aspects of predictive performance.

Summary diagrams combine several related statistics into a single graphical
representation. This can make differences among models easier to understand
than comparing a long table of individual metrics.

`modelskill` provides three complementary summary diagrams:

| Diagram | Main information shown | Main function |
|:--|:--|:--|
| **Solar diagram** | Mean error, centred error, total RMSE, model efficiency, and lower bounds on correlation | [`gg_solar()`](../reference/gg_solar.html) |
| **Target diagram** | Mean error, centred error, total RMSE, and whether prediction variability is smaller or larger than observed variability | [`gg_target()`](../reference/gg_target.html) |
| **Taylor diagram** | Correlation, relative standard deviation, and centred error | [`gg_taylor()`](../reference/gg_taylor.html) |

The three diagrams are related but answer different questions. In particular,
the Taylor diagram focuses on pattern and variability and does **not** represent
mean bias. The solar and target diagrams include bias explicitly.

The numerical quantities underlying all three diagrams can be obtained with
[`diagram_stats()`](../reference/diagram_stats.html).

## 2. Example data

We create five deliberately different prediction models so that the graphical
interpretation of the diagrams is clear.

```{r data}
library(modelskill)

set.seed(123)

n <- 150

obs <- seq(0, 10, length.out = n) +
  rnorm(n, sd = 1)

models <- list(
  Good = obs + rnorm(n, sd = 0.5),

  # Constant positive offset: strong bias, but correlation and
  # variability are almost unchanged.
  Biased = obs + 1.5,

  # Reduced variability around the observed mean.
  Smooth = mean(obs) +
    0.55 * (obs - mean(obs)) +
    rnorm(n, sd = 0.15),

  # Similar mean but much larger random error.
  Noisy = obs + rnorm(n, sd = 2),

  # Similar variability but approximately reversed pattern.
  Reversed = rev(obs)
)
```

Before drawing the diagrams, it is useful to inspect the statistics from which
their coordinates are calculated:

```{r diagram-stats}
diagram_stats(models, obs)
```

The output contains:

* `r`: Pearson correlation;
* `sd_ratio`: prediction standard deviation divided by observation standard
  deviation;
* `mean_error`: mean prediction error using the package convention
  `obs - pred`;
* `nME`: standardized mean error;
* `sde`: standardized centred error;
* `signed_sde`: centred error with a sign indicating whether prediction
  variability is smaller or larger than observation variability.

Throughout `modelskill`, prediction error is defined as

\[
e_i = obs_i-pred_i.
\]

Consequently, a **negative mean error indicates overprediction**, whereas a
**positive mean error indicates underprediction**.

# 3. Solar diagram

The **solar diagram** is a summary diagram proposed for the integrated
evaluation of quantitative maps and predictions by @wadoux2022. It provides a compact representation of overall prediction error and
its decomposition into systematic and centred components.

Let

\[
\mathrm{ME}
=
\frac{1}{n}
\sum_{i=1}^{n}
(obs_i-pred_i),
\]

where ME is the mean prediction error, and let SDE denote the centred component
of the prediction errors. The root mean square error can then be decomposed as

\[
\mathrm{RMSE}^{2}
=
\mathrm{ME}^{2}
+
\mathrm{SDE}^{2}.
\]

For the solar diagram, these quantities are standardized relative to the
variability of the observations:

\[
\mathrm{ME}^{*}
=
\frac{\mathrm{ME}}{\mathrm{sd}(obs)}
\]

and

\[
\mathrm{SDE}^{*}
=
\frac{\mathrm{SDE}}{\mathrm{sd}(obs)}.
\]

The corresponding standardized RMSE is

\[
\mathrm{RMSE}^{*}
=
\frac{\mathrm{RMSE}}{\mathrm{sd}(obs)},
\]

which gives the geometric relationship

\[
\mathrm{RMSE}^{*2}
=
\mathrm{ME}^{*2}
+
\mathrm{SDE}^{*2}.
\]

Consequently, each model can be represented by a single point whose Cartesian
coordinates are \((\mathrm{ME}^{*}, \mathrm{SDE}^{*})\), while its Euclidean
distance from the origin is exactly \(\mathrm{RMSE}^{*}\).

`modelskill` uses a common normalization for these quantities so that this
geometric identity is retained in finite samples. See
[`diagram_stats()`](../reference/diagram_stats.html) for the exact computational
definitions.

## 3.1 Reading a solar diagram

In the solar diagram:

* the **horizontal position** represents standardized mean error,
  \(\mathrm{ME}^{*}\);
* the **vertical position** represents standardized centred error,
  \(\mathrm{SDE}^{*}\);
* the **distance from the origin** represents standardized RMSE,
  \(\mathrm{RMSE}^{*}\).

The origin therefore represents perfect prediction: both systematic bias and
centred prediction error are zero.

Because error is defined as `obs - pred`:

* points to the **left** have negative ME and systematically overpredict;
* points to the **right** have positive ME and systematically underpredict;
* points near the vertical axis have little systematic bias;
* points high on the diagram have substantial centred error even when their
  mean error is small.

The direction of a point therefore indicates the relative contribution of bias
and centred error, whereas its distance from the origin indicates the magnitude
of the total squared-error loss.

The outer reference semicircle corresponds to

\[
\mathrm{RMSE}^{*}=1.
\]

A point inside this circle performs better, in squared-error terms, than using
the mean of the observations as the prediction. This boundary is directly
related to the model-efficiency coefficient:

\[
\mathrm{MEC}
=
1-\mathrm{RMSE}^{*2}.
\]

Thus, points inside the circle have positive MEC/NSE/uppercase `R2()`, points
on the circle have a value of zero, and points outside the circle have negative
model efficiency.

The pale regions provide information about the association between predictions
and observations. They represent **lower bounds on Pearson correlation**, not
exact correlation values. A point inside the \(r>0.9\) region, for example,
must have correlation greater than approximately 0.9, but its precise
correlation cannot be read from the region alone. These regions are therefore
best interpreted as additional guidance on pattern agreement rather than as a
replacement for reporting the correlation coefficient itself.

## 3.2 Basic solar diagram

```{r solar-basic}
gg_solar(
  models,
  obs,
  label = TRUE,
  y.axis_end = 2
)
```

The expected patterns are informative:

* `Good` should lie close to the origin;
* `Biased` should be displaced mainly along the horizontal axis;
* `Smooth` should have relatively little bias but a larger centred-error
  component because it does not reproduce the full variability of the
  observations;
* `Noisy` should lie high on the diagram;
* `Reversed` should perform poorly because its pattern is inconsistent with
  the observations.

Models can therefore have similar overall RMSE while occupying different
positions in the diagram if the relative contributions of bias and centred
error differ.

One important advantage of the solar diagram over the Taylor diagram is that
mean bias contributes directly to position and distance from the optimum. The
diagram therefore combines information on systematic error, centred error, and
overall prediction performance in a single geometric representation.

## 3.3 Colour models instead of writing labels

For several models, direct labels may become crowded. Use
`colour_by = "model"` to identify models through a legend:

```{r solar-model-colours}
gg_solar(
  models,
  obs,
  colour_by = "model",
  y.axis_end = 2
)
```

By default, however, point colour represents model efficiency:

```{r solar-efficiency}
gg_solar(
  models,
  obs,
  y.axis_end = 2
)
```

The default efficiency colour is uppercase \(R^2\), which in `modelskill` is
equivalent to NSE and MEC. Higher values indicate better squared-error
performance, with \(R^2 = 1\) corresponding to perfect prediction and
\(R^2 = 0\) corresponding to the performance of predicting the observed mean.

This should not be confused with lowercase
[`r2()`](../reference/r2.html), which is squared Pearson correlation and
therefore measures association rather than model efficiency.

Other available colour mappings are:

```{r solar-colour-options}
gg_solar(
  models,
  obs,
  colour_by = "correlation",
  y.axis_end = 2
)

gg_solar(
  models,
  obs,
  colour_by = "r2",
  y.axis_end = 2
)
```

Here, `colour_by = "correlation"` uses Pearson correlation, whereas
`colour_by = "r2"` uses squared Pearson correlation.

## 3.4 Control the reference geometry

The manually drawn reference axes can be adjusted with `x.axis_begin`,
`x.axis_end`, `y.axis_end`, and `by`. This is useful when one or more models
fall outside the default plotting range or when a common plotting extent is
required across several figures.

```{r solar-axes}
gg_solar(
  models,
  obs,
  colour_by = "model",
  x.axis_begin = -2,
  x.axis_end = 2,
  y.axis_end = 2,
  by = 0.5
)
```

The reference regions can also be removed:

```{r solar-no-reference}
gg_solar(
  models,
  obs,
  colour_by = "model",
  y.axis_end = 2,
  reference = FALSE
)
```

This can be useful when the main objective is to compare model positions
without displaying the correlation regions.

# 4. Target diagram

The **target diagram** was introduced by @jolliff2009 as a compact summary of
bias, centred error, and prediction variability.

## 4.1 Reading a target diagram

The distance from the origin remains standardized RMSE:

\[
\mathrm{RMSE}^{*}
=
\sqrt{
\mathrm{ME}^{*2}
+
\mathrm{SDE}^{*2}
}.
\]

Points close to the origin therefore have smaller overall error.

The two components answer different questions:

* **ME\*** identifies systematic overprediction or underprediction;
* **signed SDE\*** combines centred error with information about whether
  predictive variability is smaller or larger than observed variability.

A prediction with the correct mean but too little variation will therefore be
separated from a prediction with the correct mean but excessive variation.

This additional sign information is useful diagnostically, but it also means
that models with similar absolute SDE and RMSE can appear on opposite sides of
the diagram. The target diagram should therefore be interpreted in terms of
its components rather than simply by comparing the apparent separation between
points.

### 4.1.1 Note on the `modelskill` coordinate convention

Internally, [`gg_target()`](../reference/gg_target.html) plots **signed SDE\***
on the horizontal coordinate and **ME\*** on the vertical coordinate. The
current graphical implementation retains the historical axis-title orientation
of the package. When interpreting model positions, the coordinate definitions
given here and in the function documentation are authoritative.

## 4.2 Basic target diagram

```{r target-basic}
gg_target(
  models,
  obs,
  label = TRUE
)
```

For the example models:

* `Good` should lie nearest the origin;
* `Biased` should be displaced mainly by its mean-error component;
* `Smooth` should fall on the side associated with prediction variability
  smaller than the observed variability;
* `Noisy` should fall on the side associated with excessive prediction
  variability.

## 4.3 Colour models with a legend

```{r target-model-colours}
gg_target(
  models,
  obs,
  colour_by = "model"
)
```

As in the solar diagram, the default colour variable is model efficiency:

```{r target-efficiency}
gg_target(
  models,
  obs
)
```

Correlation and squared correlation can also be used:

```{r target-correlation}
gg_target(
  models,
  obs,
  colour_by = "correlation"
)
```

## 4.4 Change the displayed range

`axis_begin`, `axis_end`, and `by` control the manually drawn target-diagram
axes:

```{r target-axes}
gg_target(
  models,
  obs,
  colour_by = "model",
  axis_begin = -2,
  axis_end = 2,
  by = 0.5
)
```

The reference circles can be removed with:

```{r target-no-reference}
gg_target(
  models,
  obs,
  colour_by = "model",
  reference = FALSE
)
```

# 5. Taylor diagram

The **Taylor diagram** was introduced by @taylor2001 to summarize several
aspects of pattern agreement between predictions and observations.

It simultaneously represents:

* Pearson correlation \(r\);
* the ratio of prediction to observation standard deviation;
* centred root mean square difference.

Let

\[
\sigma^{*}
=
\frac{\mathrm{sd}(pred)}
{\mathrm{sd}(obs)}.
\]

The radial coordinate of a Taylor diagram is \(\sigma^{*}\), while the angular
coordinate is

\[
\theta = \arccos(r).
\]

The centred standardized error is related to these quantities by the law of
cosines:

\[
\mathrm{SDE}^{*}
=
\sqrt{
1+\sigma^{*2}-2\sigma^{*}r
}.
\]

Again, `modelskill` retains the finite-sample convention of the original
implementation; [`diagram_stats()`](../reference/diagram_stats.html) documents
the exact scaling used by the package.

## 5.1 The reference point

Perfect predictions have

\[
r=1
\qquad\text{and}\qquad
\sigma^{*}=1.
\]

They therefore occupy the reference point on the positive horizontal axis.

Distance from a model point to this reference is proportional to centred error:
points nearer the reference have smaller \(\mathrm{SDE}^{*}\).

The diagram can therefore be read in three complementary ways:

* **angle**: correlation or pattern agreement;
* **radius**: prediction variability relative to observed variability;
* **distance from the reference point**: centred prediction error.

A point inside the unit-radius arc has less variation than the observations and
therefore represents a smoother prediction. A point outside that arc has
greater variation.

## 5.2 Full Taylor diagram

By default, `gg_taylor()` displays correlations from -1 to 1:

```{r taylor-full}
gg_taylor(
  models,
  obs,
  label = TRUE
)
```

This is particularly useful when negative correlations are scientifically
possible.

The `Reversed` model in the example should appear on the negative-correlation
side of the diagram because its pattern is approximately reversed relative to
the observations.

## 5.3 Half Taylor diagram

In many prediction problems only positive correlations are of practical
interest. Set `half = TRUE` to show only correlations from 0 to 1:

```{r taylor-half}
gg_taylor(
  models,
  obs,
  legend = TRUE,
  half = TRUE
)
```

Models with negative correlation are omitted from the half diagram. Thus the
`Reversed` model shown in the full Taylor diagram is not displayed here.

The half diagram is often easier to read when all relevant models are
positively correlated.

## 5.4 Labels or legend

Use `label = TRUE` when the number of models is small:

```{r taylor-labels}
gg_taylor(
  models,
  obs,
  label = TRUE,
  half = TRUE
)
```

Alternatively, use `legend = TRUE`:

```{r taylor-legend}
gg_taylor(
  models,
  obs,
  legend = TRUE,
  half = TRUE
)
```

For `gg_taylor()`, `label = TRUE` and `legend = TRUE` are alternative ways of
identifying models and should not be requested simultaneously.

## 5.5 Centred RMSD contours

The curved contours around the reference point represent standardized centred
RMSD or SDE.

They are displayed by default.

Remove them with:

```{r taylor-no-rmsd}
gg_taylor(
  models,
  obs,
  legend = TRUE,
  half = TRUE,
  rmsd = FALSE
)
```

Change their colour with:

```{r taylor-rmsd-colour}
gg_taylor(
  models,
  obs,
  legend = TRUE,
  half = TRUE,
  rmsd_colour = "grey40"
)
```

Or specify the contour values directly:

```{r taylor-rmsd-breaks}
gg_taylor(
  models,
  obs,
  legend = TRUE,
  half = TRUE,
  rmsd_breaks = c(0.25, 0.5, 1, 1.5, 2)
)
```

## 5.6 A limitation of the Taylor diagram

The Taylor diagram deliberately works with centred quantities and therefore
does **not** show mean error.

This can produce an apparently surprising result for the `Biased` model:

```{r compare-biased}
diagram_stats(
  models[c("Good", "Biased")],
  obs
)

gg_taylor(
  models[c("Good", "Biased")],
  obs,
  label = TRUE,
  half = TRUE
)
```

Adding a constant to every prediction changes its mean error but leaves its
correlation and standard deviation essentially unchanged. The biased model can
therefore appear close to the Taylor reference point despite having a large
systematic error.

This is one reason the Taylor diagram should be interpreted together with bias
statistics or with a diagram that explicitly includes mean error, such as the
solar or target diagram.

# 6. Which diagram should I use?

The three diagrams are complementary rather than competing alternatives.

| Question | Solar | Target | Taylor |
|:--|:--:|:--:|:--:|
| Is the model biased? | **Yes** | **Yes** | No |
| What is the total standardized RMSE? | **Yes** | **Yes** | No |
| What is the centred error? | **Yes** | **Yes** | **Yes** |
| Is prediction variability too small or too large? | Indirectly | **Yes** | **Yes** |
| What is the exact Pearson correlation? | No | No | **Yes** |
| Can negative correlation be displayed explicitly? | No | No | **Yes**, with full diagram |
| Is performance relative to the mean benchmark visible? | **Yes** | **Yes** | No |

A useful practical approach is:

1. **Start with the solar diagram** when the objective is a broad assessment of
   prediction performance, because it includes both systematic and centred
   error.

2. **Use the target diagram** when distinguishing under-dispersed from
   over-dispersed predictions is particularly important.

3. **Use the Taylor diagram** when the primary interest is pattern agreement,
   correlation, and reproduction of variability.

No diagram should replace the underlying numerical metrics. Summary diagrams
are most useful when they help interpret several complementary statistics
together.

# 7. Customising the diagrams with ggplot2

All three plotting functions return ordinary `ggplot2` objects. This means that
standard ggplot additions can be applied after the diagram has been created.

## 7.1 Add titles and change the theme

```{r customise-title}
p <- gg_solar(
  models,
  obs,
  colour_by = "model",
  y.axis_end = 2
)

p +
  ggplot2::labs(
    title = "Comparison of prediction models",
    subtitle = "Solar diagram"
  ) +
  ggplot2::theme_minimal()
```

## 7.2 Move the legend

```{r customise-legend}
gg_solar(
  models,
  obs,
  colour_by = "model",
  y.axis_end = 2
) +
  ggplot2::theme(
    legend.position = "bottom"
  )
```

The same approach works for the target and Taylor diagrams.

## 7.3 Change the model colour palette

For the Taylor diagram, models are mapped to the `colour` aesthetic when
`legend = TRUE`:

```{r customise-taylor-colours}
gg_taylor(
  models,
  obs,
  legend = TRUE,
  half = TRUE
) +
  ggplot2::scale_colour_brewer(
    palette = "Dark2"
  ) +
  ggplot2::theme(
    legend.position = "bottom"
  )
```

For the target diagram, model colours use the `fill` aesthetic:

```{r customise-target-colours}
gg_target(
  models,
  obs,
  colour_by = "model"
) +
  ggplot2::scale_fill_brewer(
    palette = "Dark2"
  ) +
  ggplot2::theme(
    legend.position = "bottom"
  )
```

Adding a new scale replaces the default scale defined by the diagram function.

## 7.4 Change the target axis titles

Because a `gg_target()` result is a normal ggplot object, the displayed labels
can be replaced without changing the underlying coordinates.

For example, to label the coordinates explicitly according to the values
stored by `modelskill`:

```{r customise-target-labels}
gg_target(
  models,
  obs,
  colour_by = "model"
) +
  ggplot2::labs(
    x = "Signed SDE*",
    y = "ME*",
    title = "Target diagram"
  )
```

## 7.5 Zoom without changing the statistics

The axis arguments of `gg_solar()` and `gg_target()` define their manually drawn
reference geometry rather than clipping the data.

Because the returned plots are ggplot objects, a custom coordinate window can
also be added when a closer view is useful:

```{r customise-zoom}
gg_solar(
  models,
  obs,
  colour_by = "model",
  y.axis_end = 2
) +
  ggplot2::coord_fixed(
    xlim = c(-1.5, 1.5),
    ylim = c(0, 1.5)
  )
```

Equal x and y scaling should be retained for solar and target diagrams because
their interpretation depends on geometric distances and circular reference
lines.

## 7.6 Change point and label sizes

Core diagram elements that have direct function arguments should generally be
changed through those arguments rather than by adding ggplot layers:

```{r customise-sizes}
gg_solar(
  models,
  obs,
  label = TRUE,
  point_size = 5,
  label_size = 3.5,
  y.axis_end = 2
)
```

Similarly:

```{r customise-taylor-sizes}
gg_taylor(
  models,
  obs,
  label = TRUE,
  half = TRUE,
  point_size = 5,
  label_size = 3.5
)
```

# 8. Practical recommendations

When using summary diagrams:

1. Use the **same validation observations** for all models being compared.

2. Check the numerical statistics with
   [`diagram_stats()`](../reference/diagram_stats.html) when a model position
   requires closer interpretation.

3. Remember the error convention `obs - pred`: negative mean error means
   overprediction and positive mean error means underprediction.

4. Do not interpret a Taylor diagram as a measure of overall prediction
   accuracy because it does not include mean bias.

5. Do not interpret the solar correlation regions as exact correlation values;
   they represent lower bounds.

6. In a target diagram, consider both the absolute distance from the origin and
   the sign of the centred-error component.

7. Use the diagrams alongside numerical performance metrics rather than as
   substitutes for them.

The central benefit of these diagrams is that they make statistical
relationships visible. A model can have excellent correlation but substantial
bias, low total error but excessive smoothing, or similar RMSE to another model
for very different reasons. Summary diagrams help distinguish these situations
without relying on a single performance statistic.

