Function to draw Taylor Diagrams for model evaluation. The function allows conditioning by any categorical or numeric variables, which makes the function very flexible.
Usage
TaylorDiagram(
mydata,
obs = "obs",
mod = "mod",
group = NULL,
type = "default",
normalise = FALSE,
cols = "brewer1",
rms.col = "darkgoldenrod",
cor.col = "black",
arrow.lwd = 3,
annotate = "centred\nRMS error",
text.obs = "observed",
key = TRUE,
key.title = group,
key.columns = 1,
key.pos = "right",
strip = TRUE,
auto.text = TRUE,
...
)
Arguments
- mydata
A data frame minimally containing a column of observations and a column of predictions.
- obs
A column of observations with which the predictions (
mod
) will be compared.- mod
A column of model predictions. Note,
mod
can be of length 2 i.e. two lots of model predictions. If two sets of predictions are are present e.g.mod = c("base", "revised")
, then arrows are shown on the Taylor Diagram which show the change in model performance in going from the first to the second. This is useful where, for example, there is interest in comparing how one model run compares with another using different assumptions e.g. input data or model set up. See examples below.- group
The
group
column is used to differentiate between different models and can be a factor or character. The total number of models compared will be equal to the number of unique values ofgroup
.group
can also be of length two e.g.group = c("model", "site")
. In this case all model-site combinations will be shown but they will only be differentiated by colour/symbol by the first grouping variable ("model" in this case). In essence the plot removes the differentiation by the second grouping variable. Because there will be different values ofobs
for each group,normalise = TRUE
should be used.- type
type
determines how the data are split i.e. conditioned, and then plotted. The default is will produce a single plot using the entire data. Type can be one of the built-in types as detailed incutData
e.g. “season”, “year”, “weekday” and so on. For example,type = "season"
will produce four plots — one for each season.It is also possible to choose
type
as another variable in the data frame. If that variable is numeric, then the data will be split into four quantiles (if possible) and labelled accordingly. If type is an existing character or factor variable, then those categories/levels will be used directly. This offers great flexibility for understanding the variation of different variables and how they depend on one another.Type can be up length two e.g.
type = c("season", "weekday")
will produce a 2x2 plot split by season and day of the week. Note, when two types are provided the first forms the columns and the second the rows.Note that often it will make sense to use
type = "site"
when multiple sites are available. This will ensure that each panel contains data specific to an individual site.- normalise
Should the data be normalised by dividing the standard deviation of the observations? The statistics can be normalised (and non-dimensionalised) by dividing both the RMS difference and the standard deviation of the
mod
values by the standard deviation of the observations (obs
). In this case the “observed” point is plotted on the x-axis at unit distance from the origin. This makes it possible to plot statistics for different species (maybe with different units) on the same plot. The normalisation is done by eachgroup
/type
combination.- cols
Colours to be used for plotting. Useful options for categorical data are available from
RColorBrewer
colours — see theopenair
openColours
function for more details. Useful schemes include “Accent”, “Dark2”, “Paired”, “Pastel1”, “Pastel2”, “Set1”, “Set2”, “Set3” — but see ?brewer.pal
for the maximum useful colours in each. For user defined the user can supply a list of colour names recognised by R (typecolours()
to see the full list). An example would becols = c("yellow", "green", "blue")
.- rms.col
Colour for centred-RMS lines and text.
- cor.col
Colour for correlation coefficient lines and text.
- arrow.lwd
Width of arrow used when used for comparing two model outputs.
- annotate
Annotation shown for RMS error.
- text.obs
The plot annotation for observed values; default is "observed".
- key
Should the key be shown?
- key.title
Title for the key.
- key.columns
Number of columns to be used in the key. With many pollutants a single column can make to key too wide. The user can thus choose to use several columns by setting
columns
to be less than the number of pollutants.- key.pos
Position of the key e.g. “top”, “bottom”, “left” and “right”. See details in
lattice:xyplot
for more details about finer control.- strip
Should a strip be shown?
- auto.text
Either
TRUE
(default) orFALSE
. IfTRUE
titles and axis labels will automatically try and format pollutant names and units properly e.g. by subscripting the `2' in NO2.- ...
Other graphical parameters are passed onto
cutData
andlattice:xyplot
. For example,TaylorDiagram
passes the optionhemisphere = "southern"
on tocutData
to provide southern (rather than default northern) hemisphere handling oftype = "season"
. Similarly, common graphical parameters, such aslayout
for panel arrangement andpch
andcex
for plot symbol type and size, are passed on toxyplot
. Most are passed unmodified, although there are some special cases whereopenair
may locally manage this process. For example, common axis and title labelling options (such asxlab
,ylab
,main
) are passed viaquickText
to handle routine formatting.
Value
an openair object. If retained, e.g., using
output <- TaylorDiagram(thedata, obs = "nox", mod = "mod")
, this
output can be used to recover the data, reproduce or rework the original
plot or undertake further analysis. For example, output$data
will be
a data frame consisting of the group, type, correlation coefficient (R),
the standard deviation of the observations and measurements.
Details
The Taylor Diagram is a very useful model evaluation tool. The diagram provides a way of showing how three complementary model performance statistics vary simultaneously. These statistics are the correlation coefficient R, the standard deviation (sigma) and the (centred) root-mean-square error. These three statistics can be plotted on one (2D) graph because of the way they are related to one another which can be represented through the Law of Cosines.
The openair
version of the Taylor Diagram has several enhancements
that increase its flexibility. In particular, the straightforward way of
producing conditioning plots should prove valuable under many circumstances
(using the type
option). Many examples of Taylor Diagrams focus on
model-observation comparisons for several models using all the available
data. However, more insight can be gained into model performance by
partitioning the data in various ways e.g. by season, daylight/nighttime, day
of the week, by levels of a numeric variable e.g. wind speed or by land-use
type etc.
To consider several pollutants on one plot, a column identifying the
pollutant name can be used e.g. pollutant
. Then the Taylor Diagram can
be plotted as (assuming a data frame thedata
):
TaylorDiagram(thedata, obs = "obs", mod = "mod", group = "model", type
= "pollutant")
which will give the model performance by pollutant in each panel.
Note that it is important that each panel represents data with the same mean
observed data across different groups. Therefore TaylorDiagram(mydata,
group = "model", type = "season")
is OK, whereas TaylorDiagram(mydata,
group = "season", type = "model")
is not because each panel (representing a
model) will have four different mean values — one for each season.
Generally, the option group
is either missing (one model being
evaluated) or represents a column giving the model name. However, the data
can be normalised using the normalise
option. Normalisation is carried
out on a per group
/type
basis making it possible to compare
data on different scales e.g. TaylorDiagram(mydata, group = "season",
type = "model", normalise = TRUE)
. In this way it is possible to compare
different pollutants, sites etc. in the same panel.
Also note that if multiple sites are present it makes sense to use type
= "site"
to ensure that each panel represents an individual site with its
own specific standard deviation etc. If this is not the case then select a
single site from the data first e.g. subset(mydata, site ==
"Harwell")
.
References
Taylor, K.E.: Summarizing multiple aspects of model performance in a single diagram. J. Geophys. Res., 106, 7183-7192, 2001 (also see PCMDI Report 55).
See also
taylor.diagram
from the plotrix
package from which
some of the annotation code was used.
Other model evaluation functions:
conditionalEval()
,
conditionalQuantile()
,
modStats()
Examples
## in the examples below, most effort goes into making some artificial data
## the function itself can be run very simply
if (FALSE) { # \dontrun{
## dummy model data for 2003
dat <- selectByDate(mydata, year = 2003)
dat <- data.frame(date = mydata$date, obs = mydata$nox, mod = mydata$nox)
## now make mod worse by adding bias and noise according to the month
## do this for 3 different models
dat <- transform(dat, month = as.numeric(format(date, "%m")))
mod1 <- transform(dat, mod = mod + 10 * month + 10 * month * rnorm(nrow(dat)),
model = "model 1")
## lag the results for mod1 to make the correlation coefficient worse
## without affecting the sd
mod1 <- transform(mod1, mod = c(mod[5:length(mod)], mod[(length(mod) - 3) :
length(mod)]))
## model 2
mod2 <- transform(dat, mod = mod + 7 * month + 7 * month * rnorm(nrow(dat)),
model = "model 2")
## model 3
mod3 <- transform(dat, mod = mod + 3 * month + 3 * month * rnorm(nrow(dat)),
model = "model 3")
mod.dat <- rbind(mod1, mod2, mod3)
## basic Taylor plot
TaylorDiagram(mod.dat, obs = "obs", mod = "mod", group = "model")
## Taylor plot by season
TaylorDiagram(mod.dat, obs = "obs", mod = "mod", group = "model", type = "season")
## now show how to evaluate model improvement (or otherwise)
mod1a <- transform(dat, mod = mod + 2 * month + 2 * month * rnorm(nrow(dat)),
model = "model 1")
mod2a <- transform(mod2, mod = mod * 1.3)
mod3a <- transform(dat, mod = mod + 10 * month + 10 * month * rnorm(nrow(dat)),
model = "model 3")
mod.dat2 <- rbind(mod1a, mod2a, mod3a)
mod.dat$mod2 <- mod.dat2$mod
## now we have a data frame with 3 models, 1 set of observations
## and TWO sets of model predictions (mod and mod2)
## do for all models
TaylorDiagram(mod.dat, obs = "obs", mod = c("mod", "mod2"), group = "model")
} # }
if (FALSE) { # \dontrun{
## all models, by season
TaylorDiagram(mod.dat, obs = "obs", mod = c("mod", "mod2"), group = "model",
type = "season")
## consider two groups (model/month). In this case all months are shown by model
## but are only differentiated by model.
TaylorDiagram(mod.dat, obs = "obs", mod = "mod", group = c("model", "month"))
} # }