Facultad de Ingeniería y Ciencias
UNIVERSIDAD ADOLFO IBÁÑEZ
Diplomado en Hidrología e
Impactos del Cambio Climático
Guía Ejercicios UQM y QDM:
Esta guía de estudio tiene como objetivo aplicar el Unbiased Quantile Mapping y el Quantile
Delta Mapping a proyecciones de precipitaciones GCM del CMIP6, bajo los escenarios SSP
2-4.5 y 5-8.5, para la cuenca del Río Cauquenes. Resuelva lo siguiente:
1) Corrija el sesgo de las precipitaciones para cada uno de los 37 GCM del SSP5-8.5 en
Cauquenes, usando Unbiased Quantile Mapping (UQM). (Nota: programe el UQM,
no use el paquete climQMBC) (Nota 2: considere el período histórico 1979-2014 y
2015-2100 como futuro para la corrección de sesgo).
2) Corrija el sesgo de las precipitaciones para cada uno de los 37 GCM del SSP5-8.5 en
Cauquenes, usando Quantile Delta Mapping (QDM). (Nota: programe el QDM, no
use el paquete climQMBC) (Nota 2: considere el período histórico 1979-2014 y 2015-
2100 como futuro para la corrección de sesgo).
3) Grafique las medias mensuales (variación estacional) del período futuro 2071-2100
de un cada GCM corregidas con el QDM y el UQM, junto a la media histórica
observada del período 1981-2010.
4) Grafique las desviaciones estándar mensuales (variación estacional) del período
futuro 2071-2100 de un cada GCM corregidas con el QDM y el UQM, junto a la
media histórica observada del período 1981-2010.
Ejercicios Adicionales (Opcionales):
5) Repita los ejercicios del 1 al 4, pero esta vez usando el paquete climQMBC.
6) Ejercicio Adicional, repetir los problemas 1) al 5), pero con el SSP2-4.5.
7) Proponga otro tipo de comparativos entre los resultados del UQM y QDM.
8) Repita los ejercicios con temperaturas.
Nota: Cuando tenga que ajustar una distribución asuma que las precipitaciones distribuyen
Gamma de 2 parámetros, mientras que las temperaturas distribuyen normal.
Resultados:
Figura 1. Resultado del problema 3, promedios de precipitaciones mensuales de los GCM
del SSP5-8.5 corregidas con Unbiased Quantile Mapping y Quantile Delta Mapping para el
período 2071-2100, contra los promedios observados en la cuenca de Río Cauquenes para el
período 1981-2010.
Figura 2. Resultado del problema 4, desviación estándar de precipitaciones mensuales de los
GCM del SSP5-8.5 corregidas con Unbiased Quantile Mapping y Quantile Delta Mapping
para el período 2071-2100, contra las desviaciones estándar observadas en la cuenca de Río
Cauquenes para el período 1981-2010.
Código:
El primer paso es iniciar el código, por lo general se recomienda borrar todo y cerrar gráficos
previos. Luego hay que importar valores de los GCM y observados.
# borrar todas las variables
rm(list=ls())
# cerrar todas las figuras
graphics.off()
# Fija el directorio en que estamos trabajando, hay que modificar esto
# a la carpeta en que usted esté trabajando
setwd("C:/Users/HP/Desktop/B")
# para instalar el paquete en nuestro ordenador ejecute la siguiente
# línea, la cual está comentada.
# install.packages("openxlsx")
# este paquete es más amigable para abrir archivos xlsx
library(openxlsx)
# Importar datos de precipitaciones, fijarse bien en la hoja que están
# importando, si tiene encabezado o no
name<-read.xlsx("Pr_CMIP6_SSP585.xlsx",sheet = 1,startRow = 1, colNames = FALSE, rowNames =
FALSE,detectDates = TRUE)
pp_obs<-read.xlsx("Pr_CR2MET.xlsx",sheet = 1,startRow = 1, colNames = TRUE, rowNames =
FALSE,detectDates = TRUE)
pp_SSP585<-read.xlsx("Pr_CMIP6_SSP585.xlsx",sheet = 1,startRow = 1, colNames = TRUE,
rowNames = FALSE,detectDates = TRUE)
Una vez que se ha importado los valores observados y se tiene guardados en variables, hay
que cortar para usar solo los datos deseados, lo cual es el período 1979-2014 para el histórico
tanto para el GCM como para el observado y por otro lado se tiene el período completo del
GCM 1979-2100. El motivo para tener el período histórico del GCM, es que con eso se
obtienen los parámetros a utilizar en las distribuciones de los correctores de sesgo. Por otro
lado, se necesita el archivo con el período completo, dado que se corregirá la serie completa.
# Se genera una nueva variable solo con los años a utilizar, para este
# problema serían los 36 años del período histórico del GCM
# (1979-2014) y otro que contiene el período completo tanto histórico
# como futuro (1979-2100).
# Se extraen datos observados, histórico y Futuros de los GCM
# el usar coordenadas -2:-1 traspasa todas las filas o columnas,
# excepto la 1 y 2.
N_Year<-2014-1979+1
N_pp_obs<-pp_obs[1:(N_Year*12),-1]
N_pp_hist<-pp_SSP585[129*12+(1:(N_Year*12)),-2:-1]
N_pp_SSP585<-pp_SSP585[(129*12+1):dim(pp_SSP585)[1],-2:-1]
# Acá extraemos en FUT_YEAR las columnas de años y meses para ser
# utilizada al final para guardar los datos. También se deja en name
# el encabezado original para guardar los resultados con encabezado
# que tenga los nombres de los GCM.
FUT_YEAR<-name[(129*12+2):dim(name)[1],2]
name<-name[1,]
Como primer paso en la corrección de sesgo del UQM, estimemos los ∆𝜇 y ∆𝜎 para cada
GCM, para cada año, esto se hace de la siguiente manera:
Notar que hay un ∆𝜇 y ∆𝜎 por cada mes, por cada año futuro y por cada GCM, por lo que
“Delt_mu” y “Delt_sig” tienen 3 dimensiones: meses X años X número de GCMs. Para esto
se generan arreglos en 3D que estén vacíos y luego se estiman los valores de lo deseado
dentro de ciclos “for”. Los resultados de las tasas de cambio son guardados en “Delt_mu” y
“Delt_sig”.
# Luego se estima el número de valores de Delta_mu y Delta_sig
# los cuales tienen 3 Dimensiones (3D). Las tres dimensiones
# son 12 x 86 x 37, correspondiente a número de meses x número
# de años (uno por cada año futuro) x número de GCMs.
N_yr_fut<-(dim(N_pp_SSP585)[1]-dim(N_pp_hist)[1])/12
Delt_mu<-array(0,c(12,N_yr_fut,dim(N_pp_hist)[2]))
Delt_sig<-array(0,c(12,N_yr_fut,dim(N_pp_hist)[2]))
# Dentro del ciclo for, se extrae el GCM i, en el año j y se estima
# el cambio en la media (Delta_mu) y desviación estándar (Delta_sig)
for (i in 1:dim(N_pp_hist)[2]){
AUX<-array(N_pp_hist[,i],c(12,N_Year))
muxCont<-apply(AUX,1,mean)
sigmaxCont<-apply(AUX,1,sd)
for (j in 1:N_yr_fut){
AUX2<-array(N_pp_SSP585[,i],c(12,(dim(N_pp_SSP585)[1])/12))
AUX3<-AUX2[,(1+j):(N_Year+j)]
Delt_mu[,j,i]<-apply(AUX3,1,mean)/muxCont
Delt_sig[,j,i]<-apply(AUX3,1,sd)/sigmaxCont
}
}
Una vez que tenemos los valores de Delt_mu y Delt_sig, hay que encontrar los valores del
promedio y desviación estándar histórico observado.
# Se calcula media y desviación estándar para ajustar distribución tanto
# del período de histórico observado.
AUX<-array(N_pp_obs,c(12,N_Year))
muxObs<-apply(AUX,1,mean)
sigmaxObs<-apply(AUX,1,sd)
Teniendo las tasas de cambio, se puede proceder a corregir con el UQM, por medio de estimar
los parámetros dentro del ciclo for (cada año hay parámetros de la distribución que cambian
en el tiempo). Además, los parámetros cambian por mes y GCM, recordar que es necesario
utilizar 3 ciclos “for” y una matriz de 3 dimensiones para ir almacenando los resultados.
Dentro de cada ciclo for, se estima una variable AUX de probabilidad con la función pgamma
y los parámetros del GCM. Luego la probabilidad AUX es evaluada en otra distribución
qgamma con los parámetros de la distribución gamma que se ajusta a los datos observados:
# Calculamos la dimensión 1 contiene meses
Mi<-12
# Calculamos la dimensión 2 contiene años
Mj<-dim(N_pp_SSP585)[1]/12
# Calculamos la dimensión 3, el número de GCMs
Mk<-dim(N_pp_hist)[2]
# Inicializamos la matriz UQM_pp, esto es importante, en cualquier código
# de programación. Hay algunos códigos que no exigen inicializar variables,
# pero es computacionalmente muy ineficiente.
# Notar que esta matriz es 3D, luego dentro del ciclo for, se puede aplicar el
# quantile mapping bias correction para cada mes, para cada GCM, para cada
# año.
UQM_pp<-array(0,dim=c(Mi,Mj,Mk))
for (k in 1:Mk){
# Se extraen los valores del GCM con el que se va a trabajar, con el
# subíndice k.
Dat_AUX<-array(N_pp_SSP585[,k],c(12,Mj))
for (i in 1:Mi){
for (j in 1:Mj){
# Para todos los años del período histórico del GCM, el UQM opera
# igual que el QM, motivo por el que se verifica el año j
# de estar en el histórico la media y desviación estándar con
# las que usa el QM. En caso de estar en el período futuro, se
# procede a estimar la media y desviación estándar del UQM.
if (j<=N_Year){
muCamb<- muxObs[i]
sigmaCamb<- sigmaxObs[i]
muAUX<-mean(Dat_AUX[i,1:N_Year])
sigAUX<-sd(Dat_AUX[i,1:N_Year])
}else{
muCamb<- muxObs[i]*Delt_mu[i,(j-N_Year),k]
sigmaCamb<-sigmaxObs[i]*Delt_sig[i,(j-N_Year),k]
muAUX<-mean(Dat_AUX[i,(j-N_Year+1):j])
sigAUX<-sd(Dat_AUX[i,(j-N_Year+1):j])
}
# Se estiman los parámetros de las distribuciones
AObs<-sigmaCamb^2/muCamb
BObs<-(muCamb/sigmaCamb)^2
ACont<-sigAUX^2/muAUX
BCont<-(muAUX/sigAUX)^2
# Se estima la probabilidad asociada la cual usa los parámetros del GCM,
# notar que para el período futuro del GCM, estos parámetros son variables
# en el tiempo, dado que se estiman a partir de una ventana móvil.
AUX=pgamma(Dat_AUX[i,j],BCont,scale= ACont)
# Con la probabilidad AUX estimada, pasamos a encontrar el valor
# de precipitación. En el período futuro los parámetros "observados"
# cambian, conforme cambia la distribución.
UQM_pp[i,j,k]=qgamma(AUX,BObs,scale= AObs)
}
}
}
Luego se procede a estimar el QDM:
# Calculamos la dimensión 1 contiene meses
Mi<-12
# Calculamos la dimensión 2 contiene años
Mj<-dim(N_pp_SSP585)[1]/12
# Calculamos la dimensión 3, el número de GCMs
Mk<-dim(N_pp_hist)[2]
# Inicializamos la matriz QDM_pp, esto es importante, en cualquier código
# de programación. Hay algunos códigos que no exigen inicializar variables,
# pero es computacionalmente muy ineficiente.
# Notar que esta matriz es 3D, luego dentro del ciclo for, se puede aplicar el
# quantile mapping bias correction para cada mes, para cada GCM, para cada
# año.
QDM_pp<-array(0,dim=c(Mi,Mj,Mk))
# Dado que en el QDM los parámetros de la distribución observada no cambian en
# el tiempo, se estiman los parámetros de la distribución Gamma histórica
# observada, para cada mes (ojo que AObs y BObs son vectores con los valores
# para los 12 meses)
AObs<-sigmaxObs^2/muxObs
BObs<-(muxObs/sigmaxObs)^2
for (k in 1:Mk){
# Se extraen los valores del GCM con el que se va a trabajar, con el
# subíndice k.
Dat_AUX<-array(N_pp_SSP585[,k],c(12,Mj))
for (i in 1:Mi){
for (j in 1:Mj){
# Para todos los años del período histórico del GCM, el UQM opera
# igual que el QM, motivo por el que se verifica el año j
# de estar en el histórico la media y desviación estándar con
# las que usa el QM. En caso de estar en el período futuro, se
# procede a estimar la media y desviación estándar del UQM.
if (j<=N_Year){
muAUX<-mean(Dat_AUX[i,1:N_Year])
sigAUX<-sd(Dat_AUX[i,1:N_Year])
# Se estiman los parámetros de las distribuciones
ACont<-sigAUX^2/muAUX
BCont<-(muAUX/sigAUX)^2
Dm<-1
}else{
muAUX<-mean(Dat_AUX[i,(j-N_Year+1):j])
sigAUX<-sd(Dat_AUX[i,(j-N_Year+1):j])
# Se estiman los parámetros de las distribuciones
ACont<-sigAUX^2/muAUX
BCont<-(muAUX/sigAUX)^2
Prob<-pgamma(Dat_AUX[i,j],BCont,scale= ACont)
muAUX_hist<-mean(Dat_AUX[i,1:N_Year])
sigAUX_hist<-sd(Dat_AUX[i,1:N_Year])
AAux<-sigAUX_hist^2/muAUX_hist
BAux<-(muAUX_hist/sigAUX_hist)^2
Dm<-Dat_AUX[i,j]/qgamma(Prob,BAux,scale= AAux)
}
# Se estima la probabilidad asociada la cual usa los parámetros del GCM,
# notar que para el período futuro del GCM, estos parámetros son variables
# en el tiempo, dado que se estiman a partir de una ventana móvil.
AUX=pgamma(Dat_AUX[i,j],BCont,scale= ACont)
# Con la probabilidad AUX estimada, pasamos a encontrar el valor
# de precipitación. En el período futuro los parámetros "observados"
# cambian, conforme cambia la distribución.
QDM_pp[i,j,k]=qgamma(AUX,BObs[i],scale= AObs[i])*Dm
}
}
}
Una vez que se tiene la se tiene la serie corregida tanto por UQM, como QDM, se pasa a
graficar. Notar que hay que ser cuidadoso de usar solo el período futuro para el GCM (2071-
2100), e histórico para el observado (1981-2010).
Se parte por graficar los promedios
# Se hace un ciclo para graficar los valores de la media de precipitaciones
# del período histórico observado (1981-2010), además del período futuro
# del GCM (2071-2100).
month<-1:12
for(k in 1:Mk) {
AUX<-UQM_pp[,(Mj-30+1):Mj,k]
AUX<-apply(AUX,1,mean)
if(k==1){
plot(month,AUX,type = "l", ylab = "Prom. Precipitación [mm]",xlab = "Meses",
col=rgb(.22,.35,.85) , ylim = range(0,500))
}else{
matplot(month,AUX,type = "l", add = TRUE, col=rgb(.22,.35,.85))
}
}
# Se decide graficar en el mismo gráfico el QDM, pero este usa línea
# discontinua (lty=2), además de un color verde con transparencia (dentro
# de rgb, el primer término determina la cantidad de luz roja, el segundo
# la cantidad de luz verde, mientras que el tercero la cantidad de luz azul,
# por último el cuarto determina el nivel de transparencia). Notar, que los
# colores primarios cuándo se habla del espectro visible de luz para el ser
# humano es el rojo (r), verde (g) y azul (b).
for(k in 1:Mk) {
AUX<-QDM_pp[,(Mj-30+1):Mj,k]
AUX<-apply(AUX,1,mean)
matplot(month,AUX,type = "l",lty=2, lwd = 2, add = TRUE, col=rgb(.32,.85,.45,0.6))
}
# Se estima la media observada y se grafica en rojo junto
# a la de los GCM.
AUX<-array(N_pp_obs,c(12,N_Year))
AUX<-apply(AUX,1,mean)
matplot(month,AUX,type = "c",lwd=4, add = TRUE, col=rgb(.8,.15,.25))
# Comando para leyenda
legend(1, 450, legend=c("UQM", "QDM", "Obs"),
col=c(rgb(.22,.35,.85), rgb(.32,.85,.45,0.6), rgb(.8,.15,.25)), lty=c(1,2,3),lwd=c(1,2,4))
Al igual que la media, se pasa a graficar la desviación estándar:
# Se repite el mismo gráfico, pero para la desviación estándar
# Se hace un ciclo para graficar los valores de la media de precipitaciones
# del período histórico observado (1981-2010), además del período futuro
# del GCM (2071-2100).
month<-1:12
for(k in 1:Mk) {
AUX<-UQM_pp[,(Mj-30+1):Mj,k]
AUX<-apply(AUX,1,sd)
if(k==1){
plot(month,AUX,type = "l", ylab = "Desv. Est. Precipitación [mm]",xlab = "Meses",
col=rgb(.22,.35,.85) , ylim = range(0,500))
}else{
matplot(month,AUX,type = "l", add = TRUE, col=rgb(.22,.35,.85))
}
}
# Se decide graficar en el mismo gráfico el QDM, pero este usa línea
# discontinua (lty=2), además de un color verde con transparencia (dentro
# de rgb, el primer término determina la cantidad de luz roja, el segundo
# la cantidad de luz verde, mientras que el tercero la cantidad de luz azul,
# por último el cuarto determina el nivel de transparencia). Notar, que los
# colores primarios cuándo se habla del espectro visible de luz para el ser
# humano es el rojo (r), verde (g) y azul (b).
for(k in 1:Mk) {
AUX<-QDM_pp[,(Mj-30+1):Mj,k]
AUX<-apply(AUX,1,sd)
matplot(month,AUX,type = "l",lty=2, lwd = 2, add = TRUE, col=rgb(.32,.85,.45,0.6))
}
# Se estima la media observada y se grafica en rojo junto
# a la de los GCM.
AUX<-array(N_pp_obs,c(12,N_Year))
AUX<-apply(AUX,1,sd)
matplot(month,AUX,type = "c",lwd=4, add = TRUE, col=rgb(.8,.15,.25))
# Comando para leyenda
legend(1, 450, legend=c("UQM", "QDM", "Obs"),
col=c(rgb(.22,.35,.85), rgb(.32,.85,.45,0.6), rgb(.8,.15,.25)), lty=c(1,2,3),lwd=c(1,2,4))
En caso que uno decida guardar los resultados, esto se hace de la siguiente manera:
# Se combina las columnas con los años y meses, con la de los datos de
# precipitaciones que ya se le aplicó un bias correction. Luego se le asigna
# como encabezado el nombre de los GCM
Fut_ppUQM<-array(UQM_pp,c(Mi*Mj,Mk))
a<-cbind(FUT_YEAR,Fut_ppUQM)
colnames(a) <- name[-1]
# Se guarda en un archivo Excel la precipitación la cual se le aplicó el
# UQM a todos los GCM del SSP5-8.5
# Notar que en este caso se convierte el formato de “a” donde tenemos
# las precipitaciones corregidas a un “dataframe”, por medio de usar el
# comando “as.data.frame()”. En algunos computadores esto no es necesario
# en otros el no hacer este paso genera errores.
write.xlsx(as.data.frame(a),"PP_SSP585_FUT_UQM.xlsx",sheetName = "SSP585_PP", colNames =
TRUE, rowNames = FALSE)
# Se repite el mismo procedimiento para los datos del QDM
Fut_ppQDM<-array(QDM_pp,c(Mi*Mj,Mk))
a<-cbind(FUT_YEAR,Fut_ppQDM)
colnames(a) <- name[-1]
# Se guarda en un archivo Excel la precipitación la cual se le aplicó el
# QDM a todos los GCM del SSP5-8.5
# Notar que en este caso se convierte el formato de “a” donde tenemos
# las precipitaciones corregidas a un “dataframe”, por medio de usar el
# comando “as.data.frame()”. En algunos computadores esto no es necesario
# en otros el no hacer este paso genera errores.
write.xlsx(as.data.frame(a),"PP_SSP585_FUT_QDM.xlsx",sheetName = "SSP585_PP", colNames =
TRUE, rowNames = FALSE)