You are on page 1of 47

Trabajo Final - Curso Modelos

basados en Arboles
iDRHiCA - Universidad de Cuenca

Datos Generales
• Freddy Armijos Arcos
• Consultor Ambiental - IDYC Cía. Ltda.

Problema
Uno de los factores determinantes dentro de la contaminación de aire, es la altura de capa de mezcla -
zi-. Esto debido a que dado una fuente de emisión (chimeneas, por ejemplo) influye en los niveles de
inmisión (niveles en el aire ambiente) de los diferentes parámetros de contaminación (Material
particulado, Dióxido de Azufre, Dióxido de Nitrógeno, etc.) Para el cálculo de los valores de -zi- se
requiere el procesamiento de parámetros meteorológicos de superficie (generalmente a nivel de hora)
y de sondas de altura (generalmente una al amanecer y otra al aterdecer). Sin embargo, la
disponibilidad de este tipo de datos es sumamente escaso en el país, y en el caso de estar disponibles
los formatos en los que se maneja la información no son los adecuados para el procesamiento en
el/los software correspondientes, por lo que se debe incluir el tiempo de pre-procesamiento de los
datos. Como alternativa se utiliza downscaling, de datos ya disponibles a partir de satelite, siendo entre
los más usados WRF y MM5, pero en estos caso la capacidad computacional requerida para procesar
los datos suele ser muy grande, así como también el tiempo requerido. Dado que las mediciones de
superficie, son más comunes en nuestro medio, se analizará si es posible determinar, con únicamente
estos parámetros, la altura de capa de mezcla.

Objetivo y solución propuesta


Determinar la altura de capa de mezcla -zi-, la altura de capa límite convectiva -zic- y la altura de capa
límite mecánica -zim-, a partir de datos meteorológicos de superficie usando árboles de decisión.

El esquema de la solución propuesta para alcanzar el objetivo se muestra en la figura siguiente:


Esquema de la solución propuesta

Descripción de los datos


Se utiliza la meteorología generada a partir de MM5 y ajustada con datos de campo, de la ciudad de
Santa Elena, para el año 2013 Los datos se encuentran en un data.frame de 8168 observaciones con
un total de 27 variables, de estas las primeras 5 columnas corresponden a datos temporales, las 10
siguientes a datos generados por el procesamiento, las siguientes 10 a parámetros meteorológicos de
superficie, y los 2 finales a especificaciones o notas generadas en el procesamiento.
setwd("D:/Cursos/Random_Forest/R")
observSNE2013.Completo <­ read.csv("data/SantaElena2013.csv")
str (observSNE2013.Completo)

## 'data.frame': 8760 obs. of 27 variables:


## $ year : int 13 13 13 13 13 13 13 13 13 13 ...
## $ month : int 1 1 1 1 1 1 1 1 1 1 ...
## $ day : int 1 1 1 1 1 1 1 1 1 1 ...
## $ julianDay : int 1 1 1 1 1 1 1 1 1 1 ...
## $ hour : int 1 2 3 4 5 6 7 8 9 10 ...
## $ sensitiveHeatFlux : num ­0.6 ­0.5 ­1.1 ­6.7 ­8.2 ­9.9 ­8.7
33.4 96 34.2 ...
## $ surfaceFrictionVelocity : num 0.032 0.029 0.046 0.15 0.146 0.124
0.125 0.143 0.154 0.153 ...
## $ convectiveVelocityScale : num ­9 ­9 ­9 ­9 ­9 ...
## $ verticalPotencialGradient500m : num ­9 ­9 ­9 ­9 ­9 ­9 ­9 0.008 0.009
0.009 ...
## $ convectivelyGeneratedBoundaryLayer : int ­999 ­999 ­999 ­999 ­999 ­999 ­999
297 488 524 ...
## $ heightMechanicklyGeneratedBoundaryLayer: int 14 12 23 139 134 105 107 129 144 1
44 ...
## $ MoningObuikiovLenght : num 5.1 4.4 7.6 44.9 34 17.4 20.4 ­7.8
­3.4 ­9.5 ...
## $ SurfaceRoughtnessLength : num 0.02 0.02 0.02 0.02 0.02 0.02 0.02
0.02 0.02 0.02 ...
## $ bowenRatio : num 0.52 0.52 0.52 0.52 0.52 0.52 0.52
0.52 0.52 0.52 ...
## $ albedo : num 1 1 1 1 1 1 0.6 0.26 0.18 0.16 ...
## $ windSpeed : num 1.11 1.07 1.37 2.74 2.81 2.82 2.64
1.77 1.73 1.95 ...
## $ windDirection : num 42.6 47 38 40.4 60.5 56.9 53.5 45
3.5 14.2 ...
## $ heightWind : int 10 10 10 10 10 10 10 10 10 10 ...
## $ temperature : num 296 296 295 295 295 ...
## $ heightTemperature : int 2 2 2 2 2 2 2 2 2 2 ...
## $ precipCode : int 9999 9999 9999 9999 9999 9999 9999
9999 9999 9999 ...
## $ precipValue : num 0 0 0 0 0 0 0 0 0 0 ...
## $ relativeHumidity : int 94 95 95 94 94 95 95 86 79 82 ...
## $ pressure : int 1008 1008 1008 1008 1008 1008 1007
1007 1007 1007 ...
## $ cloudCover : int 10 10 10 10 10 7 0 0 0 10 ...
## $ tag1 : Factor w/ 2 levels "NAD","NAD­OS": 2 2
2 2 2 2 2 2 2 2 ...
## $ tag2 : Factor w/ 2 levels "NoSubs","Sub_CC": 1
1 1 1 1 1 1 1 1 1 ...
Debido a que no se utilizarán todos los datos, se procede a hacer un filtro y corte con las columnas a
utilizar, reduciendo de 27 a 12 variables, con un total de 8168 observaciones válidas. Debido a que los
datos originales no incluyen -zi- este se calcula, mediante la forma simplificado de máximo entre capa
límite convectiva y mecánica

require (dplyr)

## Loading required package: dplyr

##  
## Attaching package: 'dplyr'

## The following objects are masked from 'package:stats': 
##  
##     filter, lag

## The following objects are masked from 'package:base': 
##  
##     intersect, setdiff, setequal, union

observSNE2013 <­ observSNE2013.Completo %>% 
  select (c (month,hour,convectivelyGeneratedBoundaryLayer,heightMechanicklyGeneratedB
oundaryLayer,windSpeed,windDirection,temperature, precipCode, relativeHumidity, pressu
re, cloudCover) ) %>% 
  rename (zicBoundaryLayer = 'convectivelyGeneratedBoundaryLayer', zimBoundaryLayer = 
'heightMechanicklyGeneratedBoundaryLayer', mes = 'month', hora = 'hour') %>% 
  filter (windSpeed != 999, windDirection != 999, temperature != 9999, relativeHumidit
y != 999, pressure != 9999, cloudCover != 99) %>% 
  na.omit() %>% 
  mutate (mes = factor(mes, levels = c(1:12), labels = c('01Ene', '02Feb', '03Mar','04
Abr','05May','06Jun','07Jul','08Ago','09Sep','10Oct','11Nov', '12Dic')), 
          precipCode = factor(precipCode, levels = c(11,9999), labels = c('1Lluvia', 
'0No'))) 

observSNE2013$ziMixingHeight <­ pmax(observSNE2013$zicBoundaryLayer,observSNE2013$zimB
oundaryLayer, na.rm = T) 

str(observSNE2013)
## 'data.frame':    8168 obs. of  12 variables: 
##  $ mes             : Factor w/ 12 levels "01Ene","02Feb",..: 1 1 1 1 1 1 1 1 1 1 
... 
##  $ hora            : int  1 2 3 4 5 6 7 8 9 10 ... 
##  $ zicBoundaryLayer: int  ­999 ­999 ­999 ­999 ­999 ­999 ­999 297 488 524 ... 
##  $ zimBoundaryLayer: int  14 12 23 139 134 105 107 129 144 144 ... 
##  $ windSpeed       : num  1.11 1.07 1.37 2.74 2.81 2.82 2.64 1.77 1.73 1.95 ... 
##  $ windDirection   : num  42.6 47 38 40.4 60.5 56.9 53.5 45 3.5 14.2 ... 
##  $ temperature     : num  296 296 295 295 295 ... 
##  $ precipCode      : Factor w/ 2 levels "1Lluvia","0No": 2 2 2 2 2 2 2 2 2 2 ... 
##  $ relativeHumidity: int  94 95 95 94 94 95 95 86 79 82 ... 
##  $ pressure        : int  1008 1008 1008 1008 1008 1008 1007 1007 1007 1007 ... 
##  $ cloudCover      : int  10 10 10 10 10 7 0 0 0 10 ... 
##  $ ziMixingHeight  : int  14 12 23 139 134 105 107 297 488 524 ...

Métodos utilizados
Acorde a la figura 1, se utiliza árboles de decisión para predecir los valores de -zic-, -zim- y -zi-, y
adicionalmente se predecira -zi- mediante el cálculo de max(-zic- y -zim-) y se comprobará si existe
diferencia entre generar el árbol de predicción de -zi- directamente y generar -zi- mediante el cálculo
del máximo de cada observación entre los árboles generados para -zic- y -zim-

Para ello se proceden a realizar los siguientes pasos: 1. Pre-procesamiento de la información de


entrada (incluye eliminación de datos faltantes), y cálculo de -zi- (mediante el máximo entre -zic- y -
zim) 2-4. Predicción mediante árboles de decisión de 2) -zi- 3)-zic- y 4) -zim- 2-4.0 Elección de
métricas para la evaluación de árboles (estas se presentan dentro de los pasos 2.1 y 2.2) 2-4.1
Determinación de cp óptimo 2-4.2 Determinación del minbucket óptimo (utilizando el cp óptimo ya
obtenido) 2-4.3 Obtención de cp y minbucket a utilizar en el árbol de decisión

5. Calculo de -zi- acorde a máx de observaciones de los árboles de -zic- y -zim-


6. Comparación de métricas entre -zi- de árbol individual y -zi- calculo de árboles -zic- y -zim-

La carga de librerías se irá realizando acorde se las necesite.

Resultados
Paso 1. Preprocesamiento de la información de entrada
Véase la descripción de los datos. Con los datos de entrada, se procede a la sepración de los datos
para Train y Test. Estos mismos datos serán los utilizados en la generación de cada uno de los árboles
de los pasos posteriores, de manera que se obtendrán los mismos índices para el procesamiento final

set.seed(987) 

require (rsample)

## Loading required package: rsample
## Loading required package: tidyr

##  
## Attaching package: 'rsample'

## The following object is masked from 'package:tidyr': 
##  
##     fill

observSNE2013.Split <­ initial_split(observSNE2013, prop = 0.7)  # strata = 'month' (n


o suficientes datos para estratificar)
observSNE2013.Train <­ training(observSNE2013.Split) 
observSNE2013.Test  <­ testing(observSNE2013.Split)

Pasos 2 al 4 y 6 Metricas a utilizar


Para evaluar el modelo se utilizaran las siguientes: “RMSE”, Error cuadrático medio “MAE”,Error medio
absoluto “ME”, Error medio (que se espera tienda a 0) Sumario del ratio
“q97.5Ratio”,“medianRatio”,“q2.5Ratio”, “meanRatio”, El ratio es evaluado como la relación entre valor
predicho, sobre observado. En un escenario óptimo se espera que los valores tiendan a 1, se toma los
quintiles 97.5 y 2.5 para evaluar los datos, debido a la posibilidad de datos extremos. Es de esperar
que no exista una sobre-estimación ni sub-estimación significativa, ya que eso puede influir en que un
día/hora sea considerado “estables” y por tanto perjudicial para la dispersión de los contaminantes en
la atmósfera, o se considera inestable, y la dispersión sea rápida.

Paso 2. Predicción mediante árboles de decisión de -zic-


Generación de los data.frame de Train y Test a partir de los datos de origen.

zi.observSNE2013.Train <­ select (observSNE2013.Train, ­c(zicBoundaryLayer,zimBoundary
Layer)) 
zi.observSNE2013.Train <­ zi.observSNE2013.Train[(zi.observSNE2013.Train$ziMixingHeigh
t != ­999),] 
casos.zi.observSNE2013.Train <­ nrow(zi.observSNE2013.Train) 

zi.observSNE2013.Test <­ select (observSNE2013.Test, ­c(zicBoundaryLayer,zimBoundaryLa
yer)) 
zi.observSNE2013.Test<­ zi.observSNE2013.Test[(zi.observSNE2013.Test$ziMixingHeight != 
­999),] 

Determinación del valor óptimo de cp, para la selección del mismo se parte de los valores de defecto,
posteriormente se lo realiza con cp = 0, a partir de allí se generan otros valores que pueden ser los
óptimos para cp. Para una evaluación más completa se porcede a realizar el plotcp y el plot del valor
predicho vs real.
Los diferentes valores se colocan en varControl (Dentro del procedimeinto de generación del trabajo se
añadían o quitaban valor en un esquema prueba-error, se han mantenido algunos valores
significativos)

require (rpart)

## Loading required package: rpart

require (rpart.plot)

## Loading required package: rpart.plot
varControl = list(rpart.control(minsplit = 20, cp = 0.01,  
                                maxcompete = 4, maxsurrogate = 5, usesurrogate = 2, xv
al = 10, 
                                surrogatestyle = 0, maxdepth = 30), 
                  list(cp = 0), 
                  list(cp = 0.00001), 
                  list(cp = 0.000025),  #Elegido
                  list(cp = 0.00005), 
                  list(cp = 0.0001), 
                  list(cp = 0.0005), 
                  list(cp = 0.001) 

zi.matrizDatosTest.cp <­ matrix(data = NA, nrow = nrow(zi.observSNE2013.Test), ncol = 
length(varControl)) 
zi.metricas.cp <­ matrix(data = NA, nrow = 7, ncol = length(varControl), 
                              dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","median
Ratio","q2.5Ratio", "meanRatio"))) 

for(i in seq_along(varControl)) { 
  zi.modeloSNE2013 <­ rpart( formula = ziMixingHeight ~ ., data = zi.observSNE2013.Tra
in, method  = "anova", control = as.vector(varControl[[i]])) 
  plotcp(zi.modeloSNE2013) 
  zi.matrizDatosTest.cp[,i] <­ predict(zi.modeloSNE2013, zi.observSNE2013.Test) 
  plot(zi.observSNE2013.Test$ziMixingHeight, zi.matrizDatosTest.cp[,i]) 
  auxiliar.RMSE <­ (zi.observSNE2013.Test$ziMixingHeight ­ zi.matrizDatosTest.cp[,i])^
2
  zi.metricas.cp[1,i] <­ sqrt(mean(auxiliar.RMSE)) 
  auxiliar.resta <­ zi.matrizDatosTest.cp[,i] ­ zi.observSNE2013.Test$ziMixingHeight 
  zi.metricas.cp[2,i] <­ (sum(abs(auxiliar.resta))/nrow(zi.observSNE2013.Test)) 
  zi.metricas.cp[3,i] <­ mean(auxiliar.resta) 
  auxiliar.ratioError <­ zi.matrizDatosTest.cp[,i]/zi.observSNE2013.Test$ziMixingHeigh

  zi.metricas.cp[4,i] <­ quantile (auxiliar.ratioError, 0.975) 
  zi.metricas.cp[5,i] <­ median(auxiliar.ratioError) 
  zi.metricas.cp[6,i] <­ quantile (auxiliar.ratioError, 0.025) 
  zi.metricas.cp[7,i] <­ mean(auxiliar.ratioError) 
}
zi.metricas.cp

## [,1] [,2] [,3] [,4] [,5]


## RMSE 150.4991373 99.8336667 99.8044470 100.0979305 100.7478232
## MAE 102.0409109 58.2141152 58.5941641 59.2589799 60.1523679
## ME ­2.7986326 ­2.6951411 ­2.7391297 ­2.3801783 ­1.9054406
## q97.5Ratio 15.7363803 2.8618358 3.3037037 3.7939488 5.0413870
## medianRatio 1.1749276 1.0185185 1.0341137 1.0340909 1.0402737
## q2.5Ratio 0.2810068 0.3942308 0.3848192 0.3890496 0.3858308
## meanRatio 3.0022696 1.1818617 1.2554935 1.3325710 1.4190760
## [,6] [,7] [,8]
## RMSE 102.6443496 109.1245229 111.7004902
## MAE 62.6757015 68.3312737 70.4064109
## ME ­2.2251054 ­2.2701470 ­2.4752797
## q97.5Ratio 5.6027306 5.9066543 5.9066543
## medianRatio 1.0484467 1.0672670 1.0672670
## q2.5Ratio 0.2949364 0.2935956 0.2950901
## meanRatio 1.5112544 1.6161808 1.6472359
# Determinacion de bucket

varControl = list(list(minbucket = 0.025*casos.zi.observSNE2013.Train, cp = 0.000025),


list(minbucket = 0.01*casos.zi.observSNE2013.Train, cp = 0.000025),
list(minbucket = 0.0075*casos.zi.observSNE2013.Train, cp = 0.00002
5),
list(minbucket = 0.005*casos.zi.observSNE2013.Train, cp = 0.000025),
list(minbucket = 0.0025*casos.zi.observSNE2013.Train, cp = 0.00002
5), #ELEGIDO
list(minbucket = 0.001*casos.zi.observSNE2013.Train, cp = 0.000025),
list(minbucket = 0.00075*casos.zi.observSNE2013.Train, cp = 0.00002
5)
)

zi.matrizDatosTest.bucket <­ matrix(data = NA, nrow = nrow(zi.observSNE2013.Test), nco


l = length(varControl))
zi.metricas.bucket <­ matrix(data = NA, nrow = 7, ncol = length(varControl),
dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","medianRati
o","q2.5Ratio", "meanRatio")))

for(i in seq_along(varControl)) {
zi.modeloSNE2013 <­ rpart( formula = ziMixingHeight ~ ., data = zi.observSNE2013.Tra
in, method = "anova", control = as.vector(varControl[[i]]))
zi.matrizDatosTest.bucket[,i] <­ predict(zi.modeloSNE2013, zi.observSNE2013.Test)
plot(zi.observSNE2013.Test$ziMixingHeight, zi.matrizDatosTest.bucket[,i])
auxiliar.RMSE <­ (zi.observSNE2013.Test$ziMixingHeight ­ zi.matrizDatosTest.bucket[,
i])^2
zi.metricas.bucket[1,i] <­ sqrt(mean(auxiliar.RMSE))
auxiliar.resta <­ zi.matrizDatosTest.bucket[,i] ­ zi.observSNE2013.Test$ziMixingHeig
ht
zi.metricas.bucket[2,i] <­ (sum(abs(auxiliar.resta))/nrow(zi.observSNE2013.Test))
zi.metricas.bucket[3,i] <­ mean(auxiliar.resta)
auxiliar.ratioError <­ zi.matrizDatosTest.bucket[,i]/zi.observSNE2013.Test$ziMixingH
eight
zi.metricas.bucket[4,i] <­ quantile (auxiliar.ratioError, 0.975)
zi.metricas.bucket[5,i] <­ median(auxiliar.ratioError)
zi.metricas.bucket[6,i] <­ quantile (auxiliar.ratioError, 0.025)
zi.metricas.bucket[7,i] <­ mean(auxiliar.ratioError)
}
zi.metricas.bucket

## [,1] [,2] [,3] [,4] [,5]


## RMSE 152.2640563 113.1393269 107.6840796 104.1785668 99.64700782
## MAE 90.6233981 70.1109676 65.4390571 62.7907885 59.54847015
## ME 4.3722634 ­0.4146359 0.2087259 ­1.2420212 ­0.05345155
## q97.5Ratio 6.4804587 4.9051724 3.9525515 3.9402345 3.89216172
## medianRatio 1.0960145 1.0687546 1.0653210 1.0487432 1.04296234
## q2.5Ratio 0.3671839 0.3809907 0.3851961 0.3852088 0.39691361
## meanRatio 1.7014714 1.5413430 1.3706692 1.3538105 1.32800992
## [,6] [,7]
## RMSE 99.7762166 99.7854052
## MAE 58.9349404 58.9659060
## ME ­1.4804930 ­1.0191668
## q97.5Ratio 3.7939488 3.7939488
## medianRatio 1.0375289 1.0373979
## q2.5Ratio 0.3876263 0.3876263
## meanRatio 1.3319314 1.3334611

### Los valores elegidos son: cp = 0.000025 y minbucket = 00.25% de los casos de zi.ob
servSNE2013.Train
Los valores elegidos son: cp = 0.000025 y cp = 0.000025

Paso 3. Predicción mediante árboles de decisión de -zic-


El esquema de cálculo es similar al paso 2, en el presente se omiten los plots (que ahora se
encuentran como comentarios) únicamente por motivos de simplificar los valores mostrados en el html
generado. Sin embargo, en la realización y determinación de los parámetros óptimos si se utilizaron,
para ofrecer una mejor idea de los valores de control que se buscaban.
#### Calculo ZIC

zic.observSNE2013.Train <­ select (observSNE2013.Train, ­c(zimBoundaryLayer,ziMixingHe
ight)) 
zic.observSNE2013.Train <­ zic.observSNE2013.Train[(zic.observSNE2013.Train$zicBoundar
yLayer != ­999),]  #Error con funcion filter de dplyr (no conserva el row id)
casos.zic.observSNE2013.Train <­ nrow(zic.observSNE2013.Train) 

zic.observSNE2013.Test <­ select (observSNE2013.Test, ­c(zimBoundaryLayer,ziMixingHeig
ht)) 
zic.observSNE2013.Test<­ zic.observSNE2013.Test[(zic.observSNE2013.Test$zicBoundaryLay
er != ­999),]  

require (rpart) 
require (rpart.plot) 

#### Determinación de cp
varControl = list(rpart.control(minsplit = 20, cp = 0.01,  
                    maxcompete = 4, maxsurrogate = 5, usesurrogate = 2, xval = 10, 
                    surrogatestyle = 0, maxdepth = 30), 
                  list(cp = 0), 
                  list(cp = 0.0001), ##Elegido
                  list(cp = 0.0005), 
                  list(cp = 0.001), 
                  list(cp = 0.005) 
                  ) 

zic.matrizDatosTest.cp <­ matrix(data = NA, nrow = nrow(zic.observSNE2013.Test), ncol 
= length(varControl)) 
zic.metricas.cp <­ matrix(data = NA, nrow = 7, ncol = length(varControl), 
                          dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","medianRati
o","q2.5Ratio", "meanRatio"))) 

for(i in seq_along(varControl)) { 
  zic.modeloSNE2013 <­ rpart( formula = zicBoundaryLayer ~ ., data = zic.observSNE201
3.Train, method  = "anova", control = as.vector(varControl[[i]])) 
# plotcp(zic.modeloSNE2013)
  zic.matrizDatosTest.cp[,i] <­ predict(zic.modeloSNE2013, zic.observSNE2013.Test) 
#plot(zic.observSNE2013.Test$zicBoundaryLayer, zic.matrizDatosTest.cp[,i])
  auxiliar.RMSE <­ (zic.observSNE2013.Test$zicBoundaryLayer ­ zic.matrizDatosTest.cp[,
i])^2
  zic.metricas.cp[1,i] <­ sqrt(mean(auxiliar.RMSE)) 
  auxiliar.resta <­ zic.matrizDatosTest.cp[,i] ­ zic.observSNE2013.Test$zicBoundaryLay
er 
  zic.metricas.cp[2,i] <­ (sum(abs(auxiliar.resta))/nrow(zic.observSNE2013.Test)) 
  zic.metricas.cp[3,i] <­ mean(auxiliar.resta) 
  auxiliar.ratioError <­ zic.matrizDatosTest.cp[,i]/zic.observSNE2013.Test$zicBoundary
Layer 
  zic.metricas.cp[4,i] <­ quantile (auxiliar.ratioError, 0.975) 
  zic.metricas.cp[5,i] <­ median(auxiliar.ratioError) 
  zic.metricas.cp[6,i] <­ quantile (auxiliar.ratioError, 0.025) 
  zic.metricas.cp[7,i] <­ mean(auxiliar.ratioError) 

zic.metricas.cp

##                    [,1]        [,2]        [,3]        [,4]        [,5] 
## RMSE        149.2276504 119.1682312 119.3146818 124.9240299 128.8594988 
## MAE         117.1200212  86.7882626  87.1821568  93.2027576  98.1930669 
## ME           ­7.2041090  ­1.2728823  ­1.5958281   0.1598701  ­2.6147466 
## q97.5Ratio    3.5539866   1.9238988   2.0814198   2.1748075   2.6127537 
## medianRatio   1.0016184   1.0048873   1.0055955   1.0074840   1.0012657 
## q2.5Ratio     0.5141958   0.6717029   0.6512368   0.6609660   0.6347181 
## meanRatio     1.6227613   1.1198419   1.1672100   1.2754618   1.3785674 
##                    [,6] 
## RMSE        142.3578911 
## MAE         111.4045029 
## ME           ­3.3692144 
## q97.5Ratio    2.8650865 
## medianRatio   1.0066095 
## q2.5Ratio     0.6251986 
## meanRatio     1.4157597
# determinacion minBucket ­ minSplit
varControl = list(list(minbucket = 0.05*casos.zic.observSNE2013.Train, cp = 0.0001), 
                  list(minbucket = 0.025*casos.zic.observSNE2013.Train, cp = 0.0001), 
                  list(minbucket = 0.0175*casos.zic.observSNE2013.Train, cp = 0.0001), 
                  list(minbucket = 0.01*casos.zic.observSNE2013.Train, cp = 0.0001),  
                  list(minbucket = 0.005*casos.zic.observSNE2013.Train, cp = 0.0001), 
##Elegido
                  list(minbucket = 0.001*casos.zic.observSNE2013.Train, cp = 0.0001) 

zic.matrizDatosTest.bucket <­ matrix(data = NA, nrow = nrow(zic.observSNE2013.Test), n
col = length(varControl)) 
zic.metricas.bucket <­ matrix(data = NA, nrow = 7, ncol = length(varControl), 
                          dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","medianRati
o","q2.5Ratio", "meanRatio"))) 

for(i in seq_along(varControl)) { 
  zic.modeloSNE2013 <­ rpart( formula = zicBoundaryLayer ~ ., data = zic.observSNE201
3.Train, method  = "anova", control = as.vector(varControl[[i]])) 
  zic.matrizDatosTest.bucket[,i] <­ predict(zic.modeloSNE2013, zic.observSNE2013.Test) 
#plot(zic.observSNE2013.Test$zicBoundaryLayer, zic.matrizDatosTest.bucket[,i])
  auxiliar.RMSE <­ (zic.observSNE2013.Test$zicBoundaryLayer ­ zic.matrizDatosTest.buck
et[,i])^2
  zic.metricas.bucket[1,i] <­ sqrt(mean(auxiliar.RMSE)) 
  auxiliar.resta <­ zic.matrizDatosTest.bucket[,i] ­ zic.observSNE2013.Test$zicBoundar
yLayer 
  zic.metricas.bucket[2,i] <­ (sum(abs(auxiliar.resta))/nrow(zic.observSNE2013.Test)) 
  zic.metricas.bucket[3,i] <­ mean(auxiliar.resta) 
  auxiliar.ratioError <­ zic.matrizDatosTest.bucket[,i]/zic.observSNE2013.Test$zicBoun
daryLayer 
  zic.metricas.bucket[4,i] <­ quantile (auxiliar.ratioError, 0.975) 
  zic.metricas.bucket[5,i] <­ median(auxiliar.ratioError) 
  zic.metricas.bucket[6,i] <­ quantile (auxiliar.ratioError, 0.025) 
  zic.metricas.bucket[7,i] <­ mean(auxiliar.ratioError) 

zic.metricas.bucket
##                    [,1]        [,2]        [,3]        [,4]        [,5] 
## RMSE        142.1599539 130.0988267 126.5374330 123.1389348 119.2634097 
## MAE         110.5437134  98.5414042  95.3557526  92.7993632  88.2120682 
## ME           ­1.7777303  ­3.8393692  ­1.9946698  ­2.0452334  ­0.5090242 
## q97.5Ratio    2.8650865   2.1023127   2.1842861   2.1088725   1.9769650 
## medianRatio   0.9981044   0.9975823   0.9955529   1.0030722   1.0040643 
## q2.5Ratio     0.6312699   0.6700816   0.6777849   0.6882936   0.6603006 
## meanRatio     1.4144176   1.2360523   1.2269541   1.2291394   1.1711780 
##                    [,6] 
## RMSE        124.9592541 
## MAE          90.5333784 
## ME           ­3.0175189 
## q97.5Ratio    2.0421561 
## medianRatio   1.0042931 
## q2.5Ratio     0.6477963 
## meanRatio     1.1673379

### Elegidos
# minbucket = 0.5% de los casos.zim.observSNE2013.Train, y cp = 0.0001

Paso 4. Predicción mediante árboles de decisión de -zim-


El esquema de cálculo es similar al paso 2 y 3 (los plot están ocultos, para optimizar la visualización de
resultados). Como comentarios adicionales es de notar que en cada uno de los casos se mantiene el
indice de la base de datos original observaciones2013, para la mejor caracterización y discusión final.
### Calculo ZIM
zim.observSNE2013.Train <­ select (observSNE2013.Train, ­c(zicBoundaryLayer,ziMixingHe
ight)) 
zim.observSNE2013.Train <­ zim.observSNE2013.Train[(zim.observSNE2013.Train$zimBoundar
yLayer != ­999),]  #Error con funcion filter de dplyr (no conserva el row id)
casos.zim.observSNE2013.Train <­ nrow(zim.observSNE2013.Train) 

zim.observSNE2013.Test <­ select (observSNE2013.Test, ­c(zicBoundaryLayer,ziMixingHeig
ht)) 
zim.observSNE2013.Test<­ zim.observSNE2013.Test[(zim.observSNE2013.Test$zimBoundaryLay
er != ­999),]  

require (rpart) 
require (rpart.plot) 

#### Determinación de cp
varControl = list(rpart.control(minsplit = 20, cp = 0.01,  
                                maxcompete = 4, maxsurrogate = 5, usesurrogate = 2, xv
al = 10, 
                                surrogatestyle = 0, maxdepth = 30), 
                  list(cp = 0), 
                  list(cp = 0.00005), 
                  list(cp = 0.0001), #ELEGIDO
                  list(cp = 0.0002), 
                  list(cp = 0.0005), 
                  list(cp = 0.001) 

zim.matrizDatosTest.cp <­ matrix(data = NA, nrow = nrow(zim.observSNE2013.Test), ncol 
= length(varControl)) 
zim.metricas.cp <­ matrix(data = NA, nrow = 7, ncol = length(varControl), 
                          dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","medianRati
o","q2.5Ratio", "meanRatio"))) 

for(i in seq_along(varControl)) { 
  zim.modeloSNE2013 <­ rpart( formula = zimBoundaryLayer ~ ., data = zim.observSNE201
3.Train, method  = "anova", control = as.vector(varControl[[i]])) 
#plotcp(zim.modeloSNE2013)
  zim.matrizDatosTest.cp[,i] <­ predict(zim.modeloSNE2013, zim.observSNE2013.Test) 
#plot(zim.observSNE2013.Test$zimBoundaryLayer, zim.matrizDatosTest.cp[,i])
  auxiliar.RMSE <­ (zim.observSNE2013.Test$zimBoundaryLayer ­ zim.matrizDatosTest.cp[,
i])^2
  zim.metricas.cp[1,i] <­ sqrt(mean(auxiliar.RMSE)) 
  auxiliar.resta <­ zim.matrizDatosTest.cp[,i] ­ zim.observSNE2013.Test$zimBoundaryLay
er 
  zim.metricas.cp[2,i] <­ (sum(abs(auxiliar.resta))/nrow(zim.observSNE2013.Test)) 
  zim.metricas.cp[3,i] <­ mean(auxiliar.resta) 
  auxiliar.ratioError <­ zim.matrizDatosTest.cp[,i]/zim.observSNE2013.Test$zimBoundary
Layer 
  zim.metricas.cp[4,i] <­ quantile (auxiliar.ratioError, 0.975) 
  zim.metricas.cp[5,i] <­ median(auxiliar.ratioError) 
  zim.metricas.cp[6,i] <­ quantile (auxiliar.ratioError, 0.025) 
  zim.metricas.cp[7,i] <­ mean(auxiliar.ratioError) 

zim.metricas.cp

##                   [,1]       [,2]       [,3]       [,4]       [,5] 
## RMSE        61.7765047 25.4750691 26.7903364 28.5018841 30.8892535 
## MAE         46.7189827 16.6601811 18.2034173 20.1025800 22.1868928 
## ME          ­1.3219623 ­0.3081732 ­0.2492591 ­0.3726142 ­0.8053598 
## q97.5Ratio  10.6632904  2.7041462  3.2782486  3.6721659  5.0260244 
## medianRatio  1.0675602  1.0069930  1.0232975  1.0212567  1.0193035 
## q2.5Ratio    0.2824713  0.4242187  0.4255954  0.4242902  0.4075155 
## meanRatio    2.2305818  1.1348276  1.2300312  1.2825471  1.3543940 
##                   [,6]       [,7] 
## RMSE        34.6401823 39.8170767 
## MAE         25.2996080 29.3346853 
## ME          ­1.0297032 ­0.7312674 
## q97.5Ratio   5.5045535  5.5237173 
## medianRatio  1.0336066  1.0466007 
## q2.5Ratio    0.3270464  0.3249245 
## meanRatio    1.4255860  1.4609022
# determinacion minBucket ­ minSplit
varControl = list(list(minbucket = 0.025*casos.zim.observSNE2013.Train, cp = 0.0001), 
                  list(minbucket = 0.01*casos.zim.observSNE2013.Train, cp = 0.0001),   
                  list(minbucket = 0.0075*casos.zim.observSNE2013.Train, cp = 0.0001),  
                  list(minbucket = 0.005*casos.zim.observSNE2013.Train, cp = 0.0001),  
### Elegido
                  list(minbucket = 0.0025*casos.zim.observSNE2013.Train, cp = 0.0001), 
                  list(minbucket = 0.001*casos.zim.observSNE2013.Train, cp = 0.0001) 

zim.matrizDatosTest.bucket <­ matrix(data = NA, nrow = nrow(zim.observSNE2013.Test), n
col = length(varControl)) 
zim.metricas.bucket <­ matrix(data = NA, nrow = 7, ncol = length(varControl), 
                              dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","median
Ratio","q2.5Ratio", "meanRatio"))) 

for(i in seq_along(varControl)) { 
  zim.modeloSNE2013 <­ rpart( formula = zimBoundaryLayer ~ ., data = zim.observSNE201
3.Train, method  = "anova", control = as.vector(varControl[[i]])) 
  zim.matrizDatosTest.bucket[,i] <­ predict(zim.modeloSNE2013, zim.observSNE2013.Test) 
#plot(zim.observSNE2013.Test$zimBoundaryLayer, zim.matrizDatosTest.bucket[,i])
  auxiliar.RMSE <­ (zim.observSNE2013.Test$zimBoundaryLayer ­ zim.matrizDatosTest.buck
et[,i])^2
  zim.metricas.bucket[1,i] <­ sqrt(mean(auxiliar.RMSE)) 
  auxiliar.resta <­ zim.matrizDatosTest.bucket[,i] ­ zim.observSNE2013.Test$zimBoundar
yLayer 
  zim.metricas.bucket[2,i] <­ (sum(abs(auxiliar.resta))/nrow(zim.observSNE2013.Test)) 
  zim.metricas.bucket[3,i] <­ mean(auxiliar.resta) 
  auxiliar.ratioError <­ zim.matrizDatosTest.bucket[,i]/zim.observSNE2013.Test$zimBoun
daryLayer 
  zim.metricas.bucket[4,i] <­ quantile (auxiliar.ratioError, 0.975) 
  zim.metricas.bucket[5,i] <­ median(auxiliar.ratioError) 
  zim.metricas.bucket[6,i] <­ quantile (auxiliar.ratioError, 0.025) 
  zim.metricas.bucket[7,i] <­ mean(auxiliar.ratioError) 

zim.metricas.bucket
## [,1] [,2] [,3] [,4] [,5]
## RMSE 42.7957551 34.0285806 32.4932181 30.1018835 29.1939340
## MAE 29.6663614 23.4647538 22.3373121 21.0664829 20.7174879
## ME ­1.0395491 ­0.7881025 ­0.6946696 ­0.5747879 ­0.6656133
## q97.5Ratio 4.7111111 3.6826742 3.6826742 3.6826742 3.6721659
## medianRatio 1.0308365 1.0197870 1.0195446 1.0194280 1.0212567
## q2.5Ratio 0.4222538 0.4182974 0.4159184 0.4292684 0.4242902
## meanRatio 1.3713179 1.2968067 1.2883535 1.2848222 1.2820595
## [,6]
## RMSE 28.5191887
## MAE 20.1098270
## ME ­0.4334624
## q97.5Ratio 3.6721659
## medianRatio 1.0212567
## q2.5Ratio 0.4242902
## meanRatio 1.2828656

### Elegidos
# minbucket = 0.5% de los casos.zim.observSNE2013.Train, y cp = 0.0001

Paso 5 Calculo de -zi- acorde a máx de observaciones de los árboles de -zic- y


-zim-
Como procedimiento previo se organiza una matriz con los resultados obtenidos, teniendo presente los
indices de cada uno de los data.frame. Para ello se ejecuta el árbol de decisión (mediante rpart), se
predicen los resultados y finalmente se los coloca en una matriz
# Determinación de ZI, ZIC y ZIM con los valores seleccionados
zic.modeloSNE2013 <­ rpart( formula = zicBoundaryLayer ~ ., data = zic.observSNE2013.T
rain, method = "anova", minbucket = 0.005*casos.zic.observSNE2013.Train, cp = 0.0001)
zim.modeloSNE2013 <­ rpart( formula = zimBoundaryLayer ~ ., data = zim.observSNE2013.T
rain, method = "anova", minbucket = 0.005*casos.zim.observSNE2013.Train, cp = 0.0001)
zi.modeloSNE2013 <­ rpart( formula = ziMixingHeight ~ ., data = zi.observSNE2013.Trai
n, method = "anova", minbucket = 0.0025*casos.zi.observSNE2013.Train, cp = 0.000025)

# Predicción de valores para los 3 arboles


zic.observSNE2013.Test$zicPrediccion <­ predict(zic.modeloSNE2013, zic.observSNE2013.T
est)
zim.observSNE2013.Test$zimPrediccion <­ predict(zim.modeloSNE2013, zim.observSNE2013.T
est)
zi.observSNE2013.Test$ziPrediccion <­ predict(zi.modeloSNE2013, zi.observSNE2013.Test)

#Organización de matrices (data.frames)


zi.observSNE2013.Test.auxiliarzic <­ zic.observSNE2013.Test[,c('zicBoundaryLayer','zic
Prediccion')]
zi.observSNE2013.Test.auxiliarzim <­ zim.observSNE2013.Test[,c('zimBoundaryLayer','zim
Prediccion')]
zi.observSNE2013.Test.auxiliarzi <­ zi.observSNE2013.Test[,c('ziMixingHeight','ziPredi
ccion' )]

# Determinacion de zi mediante operacion de resultatos de zic y zim


zi.matrizDatos <­ merge (zi.observSNE2013.Test.auxiliarzic, zi.observSNE2013.Test.auxi
liarzim, by="row.names", all = TRUE)
rownames(zi.matrizDatos) <­ zi.matrizDatos$Row.names
zi.matrizDatos$Row.names <­ NULL
zi.matrizDatos <­ merge (zi.matrizDatos, zi.observSNE2013.Test.auxiliarzi, by="row.nam
es", all = TRUE)
rownames(zi.matrizDatos) <­ zi.matrizDatos$Row.names
zi.matrizDatos$Row.names <­ NULL

Se calcula zi mediante el máximo y se le añade a la matriz de resutados. La misma que consta de 7


columnas correspondientes a -zic- real y predicho, -zim- real y predicho, -zi- real, predicho mediante
árbol, predicho mediante pmax de -zic- y -zim- predichos

#Cálculo de Zi mediante pmax


zi.matrizDatos$ziPredicCalc <­ pmax(zi.matrizDatos$zicPrediccion,zi.matrizDatos$zimPre
diccion,na.rm = T)

head(zi.matrizDatos)
## zicBoundaryLayer zicPrediccion zimBoundaryLayer zimPrediccion
## 100 319 217.7000 58 56.17647
## 1003 511 496.5217 85 93.58000
## 1005 1032 844.5000 221 213.26733
## 1006 1151 864.5833 320 341.14894
## 1009 1414 1109.9167 247 259.98387
## 1010 1421 1109.9167 239 224.61290
## ziMixingHeight ziPrediccion ziPredicCalc
## 100 319 203.4103 217.7000
## 1003 511 440.9259 496.5217
## 1005 1032 870.6875 844.5000
## 1006 1151 1029.2571 864.5833
## 1009 1414 1178.3429 1109.9167
## 1010 1421 1178.3429 1109.9167

Paso 6 Comparación de métricas entre -zi- de árbol individual y -zi- calculo de


árboles -zic- y -zim-
Se compara primero los plot entre datos reales y calculados de zi, mediante los dos métodos.

plot(zi.matrizDatos$ziMixingHeight,zi.matrizDatos$ziPrediccion)
plot(zi.matrizDatos$ziMixingHeight,zi.matrizDatos$ziPredicCalc)

Se elaboran las métricas para cada uno de los valores predichos (las métricas son las mismas utilizas
en los acápites anteriores)
metricas.finales <­ matrix(data = NA, nrow = 7, ncol = 4,
dimnames = list(c("RMSE","MAE","ME","q97.5Ratio","medianR
atio","q2.5Ratio", "meanRatio"),c("zic","zim","zi_arbol","zi_calc")))

auxiliar.contador = 0
auxiliar.datosReales = c(1,3,5,5)
auxiliar.datosPredichos = c(2,4,6,7)# Columnas con los datos reales del modelo
for(contador in seq(1:4)) { #Columnas con los datos predichos del modelo
i = auxiliar.datosPredichos [contador]
j = auxiliar.datosReales[contador]
auxiliar.RMSE <­ (zi.matrizDatos[,i] ­ zi.matrizDatos[,j])^2
metricas.finales[1,contador] <­ sqrt(mean(auxiliar.RMSE, na.rm = TRUE))
auxiliar.resta <­ zi.matrizDatos[,i] ­ zi.matrizDatos[,j]
metricas.finales[2,contador] <­ (sum(abs(auxiliar.resta), na.rm = TRUE)/nrow(zi.matr
izDatos) )
metricas.finales[3,contador] <­ mean(auxiliar.resta, na.rm = TRUE)
auxiliar.ratioError <­ zi.matrizDatos[,i] / zi.matrizDatos[,j]
metricas.finales[4,contador] <­ quantile (auxiliar.ratioError, 0.975, na.rm = TRUE)
metricas.finales[5,contador] <­ median(auxiliar.ratioError, na.rm = TRUE)
metricas.finales[6,contador] <­ quantile (auxiliar.ratioError, 0.025, na.rm = TRUE)
metricas.finales[7,contador] <­ mean(auxiliar.ratioError, na.rm = TRUE)
}

metricas.finales

## zic zim zi_arbol zi_calc


## RMSE 119.6915185 31.2318944 100.0482487 83.8322761
## MAE 42.1150697 21.5774904 60.0889607 51.8549785
## ME 0.4143252 ­0.6332330 ­1.6724235 0.7430253
## q97.5Ratio 1.9769650 3.6721659 3.9297551 3.6826742
## medianRatio 1.0072136 1.0209677 1.0407972 1.0433589
## q2.5Ratio 0.6608028 0.4242902 0.3969136 0.4258151
## meanRatio 1.1731265 1.2858638 1.3338632 1.3103777

Discusión
Respecto a los parámetros de control
En relación a los parámetros de control de los árboles, se observa que los parámetros por default son
extremadamente ineficientes, en relación a los parámetros ingresados por el usuario, por otro lado
mantener el parámetro de control en cp = 0 ofrece mejores resultados, esto acorde a las métricas
utilizadas, sin embargo el árbol de decisión crece de forma significativa. Tómese por ejemplo las
métricas obtenidas para el árbol de -zi-

Metrica Valores por default cp =0 cp seleccionado 2.5e-5

RMSE 150.4991373 99.8336667 100.0979305


Metrica Valores por default cp =0 cp seleccionado 2.5e-5

MAE 102.0409109 58.2141152 59.2589799

ME -2.7986326 -2.6951411 -2.3801783

q97.5Ratio 15.7363803 2.8618358 3.7939488

medianRatio 1.1749276 1.0185185 1.0340909

q2.5Ratio 0.2810068 0.3942308 0.3890496

meanRatio 3.0022696 1.1818617 1.3325710

Obsérvese un MAE de más del 40% respecto a cp=0, y el q97.5 del ratio es de 15.7, esto quiere decir
que existe allí un valor predicho que es 15 veces superior al valor real, esto significaría que la
contaminación que en un principio no se dispersaría, acorde al modelo ahora se dispersaría con gran
facilidad, por otro lado q2.5 es de 0.28, esto quiere decir que el valor predicho es al menos 5 veces
inferior respecto al valor real, lo cual implica lo contrario que en un escenario en que los contaminantes
se dispersaban con gran facilidad, ahora lo harán con dificultad. En terminos absolutos se obtiene un
MAE de 102 m en el valor por default, esto implica el error posible en la altura de capa de mezcla, que
en valores del sector de la costa pueden resultar significativos, pero similares valores en la sierra
pueden producir un error altamente significativo e incluso inutilizable en ciertas horas. De todas formas
los valores de cp = 0, aunque son más prometedores poseen un q97.5 de 2.8, que en terminos
prácticos implica que los valores de predicción en la dispersión de contaminantes a nivel horario,
tendran un error significativo, pero que a nivel diario, es suficiente para predecir adecuadamente.

Con respecto a los cortes en minbucket, se observa, especialmente en los plots, que valores por
encima del 1% de los datos totales no ofrecen una buena distribución, y por debajo del 1% los valores
tienden a mejorar significativamente, lo cual también es visible en el plot. En relación a las diferentes
variaciones del parámetro minbucket, se observa que por lo general 0.5% es el valor crítico / óptimo
para la selección.

Respecto a las métricas finales


Como conclusión respecto a las métricas finales

metricas.finales

## zic zim zi_arbol zi_calc


## RMSE 119.6915185 31.2318944 100.0482487 83.8322761
## MAE 42.1150697 21.5774904 60.0889607 51.8549785
## ME 0.4143252 ­0.6332330 ­1.6724235 0.7430253
## q97.5Ratio 1.9769650 3.6721659 3.9297551 3.6826742
## medianRatio 1.0072136 1.0209677 1.0407972 1.0433589
## q2.5Ratio 0.6608028 0.4242902 0.3969136 0.4258151
## meanRatio 1.1731265 1.2858638 1.3338632 1.3103777
Se tiene que los valores de -zic- son los que mejor se ajustan al uso de árboles de decisión, esto sobre
todo en los valores del quantil 97.5, 50 y 2.5, donde valores de 1.98, 1.01 y 0.66 destacan que los
valores pueden ser utilizados para los modelos de dispersión, aunque con cuidado respecto a
predicción horaria, pero lo suficientemente adecuados para predicción en 8h y 24h. Además un valor
de MAE de 42 metros, respecto a valores de -zic- que por lo general están entre los 400 m, es un valor
aceptable (10%) en cuestión de modelar la dispersión.

Sin embargo, respecto a -zim- -zi_arbol- y -zi_calculado- los resultados son menos alentdores, con
q97.5 por sobre 3.5, y q2.5 por debajo de 0.5, en el caso de -zim- un MAE de 21.5 metros en una
variable que suele bordear los 100 m, es significativa (20%) aunque utilizable, para obtener una idea
general de los promedios en los niveles de inmisión, más no para niveles críticos o de alerta.

En relación a zi_arbol y zi_calculado, zi_calculado es más robusto, esto se debe a que posee como
precedente dos árboles, versus zi_arbol que solo considera 1.