Project Objective

This analysis evaluates the performance of various precipitation and climate models (CHIRPS, PERSIANN, TAMSATV3, ARCV2, ERA5) against ground-based observations using Taylor diagrams in R. Taylor diagrams provide a concise visualization of model performance by comparing correlation, standard deviation, and centered root-mean-square error (RMSE). The analysis uses synthetic data representing annual and seasonal (JF, MAM, JJAS, OND) precipitation measurements. By leveraging the plotrix and openair packages, we assess the models’ ability to replicate observed precipitation patterns, offering insights into their accuracy and reliability for climate studies.

Packages

The following packages are required for the analysis. Install them using: install.packages('package_name').

library(plotrix)
library(openair)
library(tidyr)
library(dplyr)

Data Preparation

Synthetic data is generated to represent observed precipitation (AIRPORT) and model outputs (CHIRPS, PERSIANN, TAMSATV3, ARCV2, ERA5) for annual and seasonal periods (JF, MAM, JJAS, OND). The data simulates realistic variations with different means and standard deviations.

set.seed(123)
n <- 50

# Annual data
OB <- rnorm(n, mean=15, sd=3)  # AIRPORT
CH <- OB * 0.9 + rnorm(n, sd=2)  # CHIRPS
PE <- OB * 0.8 + rnorm(n, sd=2.5)  # PERSIANN
TA <- OB * 0.7 + rnorm(n, sd=3)  # TAMSATV3
AR <- OB * 0.85 + rnorm(n, sd=2.2)  # ARCV2
ER <- OB * 0.95 + rnorm(n, sd=1.8)  # ERA5

# Seasonal data
JF.OB <- rnorm(n, mean=12, sd=2.5)
JF.CH <- JF.OB * 0.88 + rnorm(n, sd=2.1)
JF.PE <- JF.OB * 0.78 + rnorm(n, sd=2.6)
JF.TA <- JF.OB * 0.68 + rnorm(n, sd=3.1)
JF.AR <- JF.OB * 0.83 + rnorm(n, sd=2.3)
JF.ER <- JF.OB * 0.93 + rnorm(n, sd=1.9)

MAM.OB <- rnorm(n, mean=18, sd=3.2)
MAM.CH <- MAM.OB * 0.91 + rnorm(n, sd=2.2)
MAM.PE <- MAM.OB * 0.81 + rnorm(n, sd=2.7)
MAM.TA <- MAM.OB * 0.71 + rnorm(n, sd=3.2)
MAM.AR <- MAM.OB * 0.86 + rnorm(n, sd=2.4)
MAM.ER <- MAM.OB * 0.94 + rnorm(n, sd=2.0)

JJAS.OB <- rnorm(n, mean=22, sd=3.8)
JJAS.CH <- JJAS.OB * 0.92 + rnorm(n, sd=2.4)
JJAS.PE <- JJAS.OB * 0.82 + rnorm(n, sd=2.9)
JJAS.TA <- JJAS.OB * 0.72 + rnorm(n, sd=3.4)
JJAS.AR <- JJAS.OB * 0.87 + rnorm(n, sd=2.6)
JJAS.ER <- JJAS.OB * 0.96 + rnorm(n, sd=2.1)

OND.OB <- rnorm(n, mean=14, sd=2.8)
OND.CH <- OND.OB * 0.89 + rnorm(n, sd=2.0)
OND.PE <- OND.OB * 0.79 + rnorm(n, sd=2.5)
OND.TA <- OND.OB * 0.69 + rnorm(n, sd=3.0)
OND.AR <- OND.OB * 0.84 + rnorm(n, sd=2.2)
OND.ER <- OND.OB * 0.92 + rnorm(n, sd=1.7)

Annual Taylor Diagram

A Taylor diagram is created to compare the annual performance of the models against observations using the plotrix package. Each model is represented with a distinct color.

oldpar <- taylor.diagram(OB, CH, add=FALSE, pch=19, pos.cor=TRUE,
                         xlab="Standard deviation", ylab="Standard Deviation",
                         main="Annual Precipitation Model Comparison",
                         show.gamma=TRUE, ngamma=10, gamma.col="green",
                         sd.arcs=1, ref.sd=TRUE, sd.method="sample",
                         grad.corr.lines=c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 0.99),
                         col="blue", pcex=1.5, cex.axis=1.1, normalize=TRUE)

taylor.diagram(OB, PE, add=TRUE, col="black", pcex=1.5, cex.axis=1.1, normalize=TRUE)
taylor.diagram(OB, TA, add=TRUE, col="pink", pcex=1.5, cex.axis=1.1, normalize=TRUE)
taylor.diagram(OB, AR, add=TRUE, col="brown", pcex=1.5, cex.axis=1.1, normalize=TRUE)
taylor.diagram(OB, ER, add=TRUE, col="green", pcex=1.5, cex.axis=1.1, normalize=TRUE)

legend("left", legend=c("AIRPORT", "CHIRPS", "PERSIANN", "TAMSATV3", "ARCV2", "ERA5"),
       pch=c(15, 19, 19, 19, 19, 19), col=c("darkgreen", "blue", "black", "pink", "brown", "green"), cex=0.7)

Seasonal Taylor Diagrams

Separate Taylor diagrams are generated for each season (JF, MAM, JJAS, OND) to evaluate model performance across different climatic periods.

require(plotrix)
taylor.diagram(JF.OB,  JF.CH,           col="blue",       pos.cor=F,pcex=1.5,normalize=F)
taylor.diagram(JF.OB,  JF.PE,add=TRUE,  col="black",      pcex=1.5,normalize=F)
taylor.diagram(JF.OB,  JF.TA,add=TRUE,  col="pink",       pcex=1.5,normalize=F)
taylor.diagram(JF.OB,  JF.AR,add=TRUE,  col="brown",      pcex=1.5,normalize=F)
taylor.diagram(JF.OB,  JF.ER,add=TRUE,  col="green",      pcex=1.5,normalize=F)

require(plotrix)
taylor.diagram(MAM.OB,  MAM.CH,           col="blue",       pos.cor=F,pcex=1.5,normalize=F)
taylor.diagram(MAM.OB,  MAM.PE,add=TRUE,  col="black",      pcex=1.5,normalize=F)
taylor.diagram(MAM.OB,  MAM.TA,add=TRUE,  col="pink",       pcex=1.5,normalize=F)
taylor.diagram(MAM.OB,  MAM.AR,add=TRUE,  col="brown",      pcex=1.5,normalize=F)
taylor.diagram(MAM.OB,  MAM.ER,add=TRUE,  col="green",      pcex=1.5,normalize=F)

require(plotrix)
taylor.diagram(JJAS.OB,  JJAS.CH,           col="blue",       pos.cor=F,pcex=1.5,normalize=F)
taylor.diagram(JJAS.OB,  JJAS.PE,add=TRUE,  col="black",      pcex=1.5,normalize=F)
taylor.diagram(JJAS.OB,  JJAS.TA,add=TRUE,  col="pink",       pcex=1.5,normalize=F)
taylor.diagram(JJAS.OB,  JJAS.AR,add=TRUE,  col="brown",      pcex=1.5,normalize=F)
taylor.diagram(JJAS.OB,  JJAS.ER,add=TRUE,  col="green",      pcex=1.5,normalize=F)

require(plotrix)
taylor.diagram(OND.OB,  OND.CH,           col="blue",       pos.cor=F,pcex=1.5,normalize=F)
taylor.diagram(OND.OB,  OND.PE,add=TRUE,  col="black",      pcex=1.5,normalize=F)
taylor.diagram(OND.OB,  OND.TA,add=TRUE,  col="pink",       pcex=1.5,normalize=F)
taylor.diagram(OND.OB,  OND.AR,add=TRUE,  col="brown",      pcex=1.5,normalize=F)
taylor.diagram(OND.OB,  OND.ER,add=TRUE,  col="green",      pcex=1.5,normalize=F)


legend(30,53
,legend=c("OND.OBSERVATON","OND.CHIRPS","OND.PESERIANNCDR","OND.TAMSAT","OND.ARC","OND.ERA"),horiz=FALSE,
 pch=c(15,19,19,19,19,19),col=c("darkgreen","red","blue","brown","orange","darkgreen"), cex=0.7) 

par(mfrow=c(2,2))
colors <- c("blue", "black", "pink", "brown", "green")

plot_taylor_diagram <- function(season, main_title) {
  obs <- get(paste0(season, ".OB"))
  taylor.diagram(obs, get(paste0(season, ".CH")), col=colors[1], pch=19,
                 main=main_title, normalize=FALSE, pos.cor=TRUE)
  for(i in 2:5) {
    model <- c("PE", "TA", "AR", "ER")[i-1]
    taylor.diagram(obs, get(paste0(season, ".", model)), 
                   add=TRUE, col=colors[i], pch=19)
  }
  legend("topright", legend=c("CHIRPS", "PERSIANN", "TAMSATV3", "ARCV2", "ERA5"),
         col=colors, pch=19, cex=0.8)
}

plot_taylor_diagram("JF", "Janvier-Février (JF)")
plot_taylor_diagram("MAM", "Mars-Mai (MAM)")
plot_taylor_diagram("JJAS", "Juin-Septembre (JJAS)")
plot_taylor_diagram("OND", "Octobre-Décembre (OND)")

par(mfrow=c(1,1))

Openair Taylor Diagram

Using the openair package, a Taylor diagram is created to compare all models in a single plot, with data reformatted into a long format for compatibility.

mod.dat <- data.frame(
  date = seq.Date(from = as.Date("2000-01-01"), by = "day", length.out = n),
  obs = OB, mod.CH = CH, mod.PE = PE, mod.TA = TA, mod.AR = AR, mod.ER = ER
)

mod.dat.long <- mod.dat %>%
  pivot_longer(cols = starts_with("mod."), 
               names_to = "model", 
               values_to = "mod") %>%
  mutate(model = gsub("mod.", "", model))

TaylorDiagram(mod.dat.long, obs = "obs", mod = "mod", group = "model",
              main="Model Comparison (Openair)")

Contact

For further inquiries, please contact: