JAVIER RUIZ PÉREZ PEC2


Base teórica


Esta práctica se basa en una de las aplicaciones de algoritmos de clasificación, desarrolladas con K-NN y árboles de decisión.

K-NN (o k-vecinos) es un sistema de clasificación basado en la comparación de instancias nuevas con instancias presentes en el juego de datos de entrenamiento. La construcción de grupos se realiza a partir del propio juego de datos de entrenamiento, tomando como referencia el parámetro k indicado por el investigador. El algoritmo de los K vecinos más cercanos es uno de los algoritmos más simples que existen que muestran la esencia del aprendizaje basado en instancias. Este algoritmo asume que todas las instancias corresponden a puntos que se encuentran en un espacio de dimensión n. El vecino más cercano de una instancia es definido en términos de la distancia Euclidiana estándar.

Los árboles de decisión son algoritmos que construyen modelos de decisión que forman estructuras similares a los diagramas de flujo donde los nodos internos suelen ser puntos de decisión sobre un atributo del juego de datos. Son muy dependientes del concepto de ganancia de la información ya que es el criterio que utilizan para construir las ramificaciones del árbol. A grandes rasgos existen dos tipos de árboles de decisión: * Árboles de decisión simple: el resultado se construye mediante un proceso de clasificación * Árboles de decisión múltiples (random forest): el resultado se construye mediante el desarrollo iterativo de n procesos de clasificación.

Recursos en la web:


Caso de estudio: — Clasificación red de ventas Bodegas Mureda —


Formamos parte de la Dirección Comercial de la Bodega de vinos Mureda y queremos analizar la actividad de nuestra red de ventas, formada por tres categor�??as de comerciales (A, B y C). Para ello, estamos interesados en conocer si existen diferencias en la actividad generada por cada uno de los comerciales y, en caso afirmativo, identificar cuáles son las variables que más contribuyen a dichas diferencias y si podemos predecir a qué categor�??a de comercial pertenece un nuevo empleado en función de su actividad.

Para ello, nuestro equipo de análisis dispone de un fichero con información de 150 clientes que recoge estad�??sticas de actividad de los tres grupos de Comerciales, a razón de 50 registros por grupo de comercial. El fichero contiene información de las siguientes variables:

Una vez definidos los objetivos de nuestra investigación, nuestro departamento de análisis nos propone desarrollar un proceso de clasificación que aplique tres tipos de algoritmos complementarios: K-NN, Árboles de decisión simples y Árboles de clasificación múltiples (random forest) sobre nuestro fichero de datos.


Apartados de la práctica


El código R que utilizaremos en la práctica se divide en apartados según las tareas que iremos realizando:

Apartados práctica:


Carga de paquetes y del fichero de datos


Empezaremos por cargar los packages R que necesitaremos tener en memoria.

Cargamos también los datos ubicados en el fichero PEC2.csv

#revisamos si es necesario instalar los paquetes necesarios para desarrollar la PEC 2
#install.packages("ggplot2")
#install.packages("party")
#install.packages("rpart.plot")
#install.packages("useful")
#install.packages("randomForest")

#cargamos los paquetes necesarios para desarrollar la PEC 2

# Para representar gráficamente la relación entre variables
library("ggplot2")
# Para clasificar con K-NN
library("class")
# Para clasificar con rpart
library("rpart")
library("rpart.plot")
# Para clasificar con party
library("party")
# Para clasificar con randomForest
library("useful")
library("randomForest")


#cargamos el fichero de datos que utilizamos para desarrollar la PEC 2

nombreruta_PEC2 <- paste(getwd(),"/PEC2.csv", sep = "")

Data_PEC2 <- read.csv(nombreruta_PEC2, encoding="UTF-8",
                     header=TRUE, sep=",", na.strings="NA", dec=".", strip.white=TRUE)


Análisis univariable y bivariable del fichero


La primera fase del análisis consiste siempre en un análisis descriptivo de las variables incluidas en el fichero y de la relación existente entre ellas. Para ello, aplicamos la siguiente secuencia de cálculos y representaciones gráficas.

  1. EstadÃ???sticos descriptivos de las variables
  2. Representación gráfica de cada una de las variables
  3. Estudio de la relación entre las variables cuantitativas
  4. Estudio de la existencia de diferencias por comercial
# 1.Calculamos los descriptivos univariables de las variables del fichero
summary(Data_PEC2) #Estad�??sticos descriptivos básicos de las variables
##     Ingresos        Margen            Km           Visitas      Comercial
##  Min.   :4300   Min.   :200.0   Min.   :10.00   Min.   : 1.00   A:50     
##  1st Qu.:5100   1st Qu.:280.0   1st Qu.:16.00   1st Qu.: 3.00   B:50     
##  Median :5800   Median :300.0   Median :43.50   Median :13.00   C:50     
##  Mean   :5843   Mean   :305.4   Mean   :37.59   Mean   :11.99            
##  3rd Qu.:6400   3rd Qu.:330.0   3rd Qu.:51.00   3rd Qu.:18.00            
##  Max.   :7900   Max.   :440.0   Max.   :69.00   Max.   :25.00

Las 5 variables presentan una distribución bastante homogénea:

# 2.Representamos gráficamente las variables del fichero mediante histogramas

#Histograma Ingresos
f1 <- hist(Data_PEC2$Ingresos, main="Histograma Ingresos", col = "gray", labels = TRUE) 

f1
## $breaks
## [1] 4000 4500 5000 5500 6000 6500 7000 7500 8000
## 
## $counts
## [1]  5 27 27 30 31 18  6  6
## 
## $density
## [1] 6.666667e-05 3.600000e-04 3.600000e-04 4.000000e-04 4.133333e-04
## [6] 2.400000e-04 8.000000e-05 8.000000e-05
## 
## $mids
## [1] 4250 4750 5250 5750 6250 6750 7250 7750
## 
## $xname
## [1] "Data_PEC2$Ingresos"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"
#Histograma Margen
f2 <- hist(Data_PEC2$Margen, main="Histograma Margen", col = "gray", labels = TRUE) 

f2
## $breaks
##  [1] 200 220 240 260 280 300 320 340 360 380 400 420 440
## 
## $counts
##  [1]  4  7 13 23 36 25 18  9  9  3  2  1
## 
## $density
##  [1] 0.0013333333 0.0023333333 0.0043333333 0.0076666667 0.0120000000
##  [6] 0.0083333333 0.0060000000 0.0030000000 0.0030000000 0.0010000000
## [11] 0.0006666667 0.0003333333
## 
## $mids
##  [1] 210 230 250 270 290 310 330 350 370 390 410 430
## 
## $xname
## [1] "Data_PEC2$Margen"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"
#Histograma Km
f3 <- hist(Data_PEC2$Km, main="Histograma Km", col = "gray", labels = TRUE)

f3
## $breaks
##  [1] 10 15 20 25 30 35 40 45 50 55 60 65 70
## 
## $counts
##  [1] 37 13  0  1  4 11 21 21 17 16  5  4
## 
## $density
##  [1] 0.049333333 0.017333333 0.000000000 0.001333333 0.005333333
##  [6] 0.014666667 0.028000000 0.028000000 0.022666667 0.021333333
## [11] 0.006666667 0.005333333
## 
## $mids
##  [1] 12.5 17.5 22.5 27.5 32.5 37.5 42.5 47.5 52.5 57.5 62.5 67.5
## 
## $xname
## [1] "Data_PEC2$Km"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"
#Histograma Visitas
f4 <- hist(Data_PEC2$Visitas, main="Histograma Visitas", col = "gray", labels = TRUE)

f4
## $breaks
##  [1]  0  2  4  6  8 10 12 14 16 18 20 22 24 26
## 
## $counts
##  [1] 34 14  2  0  7  8 21 16 14 11  9 11  3
## 
## $density
##  [1] 0.113333333 0.046666667 0.006666667 0.000000000 0.023333333
##  [6] 0.026666667 0.070000000 0.053333333 0.046666667 0.036666667
## [11] 0.030000000 0.036666667 0.010000000
## 
## $mids
##  [1]  1  3  5  7  9 11 13 15 17 19 21 23 25
## 
## $xname
## [1] "Data_PEC2$Visitas"
## 
## $equidist
## [1] TRUE
## 
## attr(,"class")
## [1] "histogram"
#Histograma Comercial
f5 <- plot(Data_PEC2$Comercial)

f5
##      [,1]
## [1,]  0.7
## [2,]  1.9
## [3,]  3.1

Las variables cuantitativas presentan dos distribuciones diferenciadas:

# 3.Estudiamos la relación existente entre las variables del fichero

# Estudiamos la relación entre variables mediante gráficos de dispersión
f6<- plot(Data_PEC2)                                              

f6
## NULL
# Estudiamos la relación entre variables cuantitativas mediante correlaciones
cor(Data_PEC2[,c("Ingresos","Margen","Km","Visitas")], use="complete")
##            Ingresos     Margen         Km    Visitas
## Ingresos  1.0000000 -0.1093692  0.8717542  0.8179536
## Margen   -0.1093692  1.0000000 -0.4205161 -0.3565441
## Km        0.8717542 -0.4205161  1.0000000  0.9627571
## Visitas   0.8179536 -0.3565441  0.9627571  1.0000000

Analizando los gráficos de dispersión, apuntamos una fuerte relación entre Visitas-Km, Ingresos-Km y Ingresos-Visitas que podemos validar con el coeficiente de correlación, estad�??stico que toma valores entre -1 y 1 y que mide la fuerza con la que dos variables quedan interrelacionadas (próximo a 1 cuando la relación es muy fuerte y próximo a -1 cuando la relación es fuerte pero inversa)

# Estudiamos la relación entre variables Km y Visitas
f7<-ggplot(Data_PEC2, aes(x=Km, y=Visitas)) + geom_point()
f7

# Estudiamos la relación entre variables Km y Visitas con tamaño ingresos
f8<-ggplot(Data_PEC2, aes(x=Km, y=Visitas)) + geom_point(aes(size=Ingresos))
f8

# Relación entre variables Km y Visitas con tamaño margen
f9<-ggplot(Data_PEC2, aes(x=Km, y=Visitas)) + geom_point(aes(size=Margen))
f9

# 3.Estudiamos la existencia de diferencias por Comercial

# promedio variables por comercial 
tapply(Data_PEC2$Ingresos,Data_PEC2$Comercial,mean)
##    A    B    C 
## 5006 5936 6588
tapply(Data_PEC2$Margen,Data_PEC2$Comercial,mean)
##     A     B     C 
## 341.8 277.0 297.4
tapply(Data_PEC2$Km,Data_PEC2$Comercial,mean)
##     A     B     C 
## 14.64 42.60 55.52
tapply(Data_PEC2$Visitas,Data_PEC2$Comercial,mean)
##     A     B     C 
##  2.44 13.26 20.26

Vemos que existen diferencias remarcables en el promedio de cada una de las variables para cada Comercial:

Graficamos a continuación las variables cuantitativas diferenciando por Comercial.

# Relación entre variables Km y Visitas con tamaño ingresos y Color según Comercial
f10<-ggplot(Data_PEC2, aes(x=Km, y=Visitas, color=Comercial)) + geom_point(aes(size=Ingresos))
f10

# Relación entre variables Km y Visitas con tamaño ingresos y Color según Comercial, l�??nea tendencia y elipse
f11<-ggplot(Data_PEC2, aes(x=Km, y=Visitas, color=Comercial)) + geom_point(aes(size=Ingresos)) + 
  geom_smooth(method=lm, aes(fill=Comercial))+ stat_ellipse(type = "norm")
f11

Identificamos un comportamiento diferenciado donde Km y Visitas ya que son las variables que presentan una mayor capacidad de diferenciación.



Estudio de la capacidad de Clasificación de los Comerciales mediante K-NN, árboles de decisión simples y múltiples


Una vez analizado descriptivamente el fichero, consideramos necesario evaluar la capacidad predictiva de tres modelos predictivos:

Con dicho objetivo, aplicaremos los algoritmos siguiendo la siguiente secuencia:

5 Clasificación de los clientes con K-NN

 5.1 Construcción del Modelo de clasificación con _K-NN_  
 
 5.2 Validación del Modelo de clasificación con _K-NN_  
 

6 Clasificación de los clientes con árboles de decisión simples

 6.1 Construcción del Modelo de clasificación con el paquete _party_  
 
 6.2 Validación del Modelo de clasificación con el paquete _party_  
 
 6.3 Construcción del Modelo de clasificación con el paquete _rpart_  
 
 6.4 Validación del Modelo de clasificación con el paquete _rpart_  
 

7 Clasificación de los clientes con árboles de decisión múltiples (random forest)

 7.1 Construcción del Modelo de clasificación con el paquete _randomForest_  
 
 7.2 Validación del Modelo de clasificación con el paquete _randomForest_  
 

Construcción del juego de datos de entrenamiento


Construimos un juego de datos de entrenamiento con el 70% de registros para construir los modelos y un juego de datos de pruebas con el 30% de registros restantes para validar los modelos.

# Dividimos el fichero en 70% entreno y 30% validación  #
set.seed(1234)
ind <- sample(2, nrow(Data_PEC2), replace=TRUE, prob=c(0.7, 0.3))
trainData <- Data_PEC2[ind==1,]
testData <- Data_PEC2[ind==2,]

Clasificación de los Comerciales con K-NN


Aplicamos el modelo K-NN, pasándole como parámetros la matriz de entrenamiento compuesta por las 4 variables cuantitativas : Importe, Margen, Km y Visitas. No le pasamos el campo Comercial porque precisamente es el campo que el algoritmo debe predecir.

Dado que el modelo K-NN permite replicar el modelo para n valores diferentes de k, repetimos el análisis para k=1,2,3 y 4.

# Aplicamos el algoritmo K-NN seleccionando 1 como k inicial
KnnTestPrediccion_k1 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 1, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k1 )
##    KnnTestPrediccion_k1
##      A  B  C
##   A 10  0  0
##   B  0  9  3
##   C  0  6 10
# Calculamos el % de aciertos para k=1
sum(KnnTestPrediccion_k1 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 76.31579
# Aplicamos el algoritmo K-NN seleccionando 2 como k inicial
KnnTestPrediccion_k2 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 2, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k2 )
##    KnnTestPrediccion_k2
##      A  B  C
##   A 10  0  0
##   B  2  8  2
##   C  0  7  9
# Calculamos el % de aciertos para k=2
sum(KnnTestPrediccion_k2 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 71.05263
# Aplicamos el algoritmo K-NN seleccionando 3 como k inicial
KnnTestPrediccion_k3 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 3, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k3 )
##    KnnTestPrediccion_k3
##      A  B  C
##   A 10  0  0
##   B  2  7  3
##   C  0  8  8
# Calculamos el % de aciertos para k=3



# Aplicamos el algoritmo K-NN seleccionando 4 como k inicial
KnnTestPrediccion_k4 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 4, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k4 )
##    KnnTestPrediccion_k4
##     A B C
##   A 9 1 0
##   B 2 7 3
##   C 0 7 9
# Calculamos el % de aciertos para k=4
sum(KnnTestPrediccion_k4 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 65.78947

Una vez aplicados el algoritmo para k=1,2,3 y 4. Mediante la matriz de confusión valoramos el nivel de acierto del modelo. Con dicho objetivo, estudiamos el % de acierto de cada uno de ellos con el objetivo de escoger el valor de k que permite obtener un % de clasificación correcta más alto:

En consecuencia tomamos el valor k=1 con un 76% de clasificación correcta.



Proceso de clasificación con árboles de decisión simples


Para construir un árbol de decisión es necesario definir una función que relaciona una variable categórica dependiente (factor) con n variables independientes que pueden ser categóricas o numéricas. En nuestro caso trabajaremos con:

El algoritmo de clasificación busca cuál es la variable que permite obtener una submuestra más diferenciada para la variable dependiente (Comercial en nuestro caso) e identifica también qué intervalos (si la variable es cuantitativa) ó agrupación de categor�??as de la/s variable/s independiente/s permitir�??a/n maximizar dicha división.

Una vez identificada la variable independiente que permite obtener la clasificación con una mayor capacidad de diferenciación, el proceso se repite reiterativamente en cada uno de los nodos obtenidos hasta que el algoritmo no encuentra diferencias significativas que le permitan seguir profundizando en los nodos.

Una vez obtenido una primera versión del árbol, existen algoritmos que permiten hacer un podado del árbol (prunning), eliminando aquellas ramas que no acaban de justificar su presencia de acuerdo con algunos parámetros preestablecidos.

En todos los casos seguiremos la siguiente secuencia de pasos para obtener los árboles de clasificación:

  1. Definir la muestra de entrenamiento y la muestra de prueba

  2. Definir la función que relaciona la variable dependiente con las variables independientes

  3. Estimar el árbol de decisión

  4. Representar gráficamente una primera versión del árbol

  1. Estudiar la capacidad predictiva del árbol

Clasificación de los Comerciales con árboles de decisión simples (paquete party)


Una vez estudiados los datos de manera individual y evaluada la capacidad predictiva del algoritmo K-NN, estudiamos a continuación la capacidad predictiva del árbol de decisión simple, obtenido mediante el paquete party

# Dividimos el fichero en 70% entreno y 30% validación  (parte recurrente en todo experimento)
set.seed(1234)
ind <- sample(2, nrow(Data_PEC2), replace=TRUE, prob=c(0.7, 0.3))
trainData <- Data_PEC2[ind==1,]
testData <- Data_PEC2[ind==2,]
#Declaramos función del árbol
ArbolParty <- Comercial ~ Ingresos + Margen + Km + Visitas
#Aplicamos algoritmo
ArbolParty_ctree <- ctree(ArbolParty, data=trainData)
#Obtenemos la relación de reglas de asociación del árbol en formato listado
print(ArbolParty_ctree)
## 
##   Conditional inference tree with 4 terminal nodes
## 
## Response:  Comercial 
## Inputs:  Ingresos, Margen, Km, Visitas 
## Number of observations:  112 
## 
## 1) Km <= 19; criterion = 1, statistic = 104.637
##   2)*  weights = 40 
## 1) Km > 19
##   3) Visitas <= 17; criterion = 1, statistic = 48.939
##     4) Km <= 44; criterion = 0.974, statistic = 7.397
##       5)*  weights = 21 
##     4) Km > 44
##       6)*  weights = 19 
##   3) Visitas > 17
##     7)*  weights = 32
#Obtenemos el árbol con un diseño gráfico cuidado
f12<-plot(ArbolParty_ctree)

f12
## NULL
# Validamos la capacidad de predicción del árbol con el fichero de validación
testPredParty <- predict(ArbolParty_ctree, newdata = testData)
table(testPredParty, testData$Comercial)
##              
## testPredParty  A  B  C
##             A 10  0  0
##             B  0 12  2
##             C  0  0 14
# Calculamos el % de aciertos
sum(testPredParty == testData$Comercial)/ length(testData$Comercial)*100
## [1] 94.73684

El árbol de decisión obtenido mediante el paquete party clasifica correctamente un 26% de los registros. Un resultado demasiado pobre.


Clasificación de los Comerciales con árboles de decisión simples (paquete rpart)


Una vez evaluada la capacidad predictiva del árbol de decisión obtenido con party, estudiamos a continuación la capacidad predictiva del árbol de decisión simple obtenido mediante el paquete rpart

# Dividimos el fichero en 70% entreno y 30% validación  (parte recurrente en todo experimento)
set.seed(1234)
ind <- sample(2, nrow(Data_PEC2), replace=TRUE, prob=c(0.7, 0.3))
trainData <- Data_PEC2[ind==1,]
testData <- Data_PEC2[ind==2,]
#Declaramos función del árbol
ArbolRpart <- Comercial ~ Ingresos + Margen + Km + Visitas
#Aplicamos algoritmo
ArbolRpart_ctree <- rpart(ArbolRpart, method="class", data=trainData)
#Obtenemos la relación de reglas de asociación del árbol en formato listado
print(ArbolRpart_ctree) # estadÃ???sticas detalladas de cada nodo
## n= 112 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 112 72 A (0.3571429 0.3392857 0.3035714)  
##   2) Km< 24.5 40  0 A (1.0000000 0.0000000 0.0000000) *
##   3) Km>=24.5 72 34 B (0.0000000 0.5277778 0.4722222)  
##     6) Visitas< 17.5 40  3 B (0.0000000 0.9250000 0.0750000) *
##     7) Visitas>=17.5 32  1 C (0.0000000 0.0312500 0.9687500) *
#Obtenemos el árbol con un diseño gráfico cuidado
f13<-rpart.plot(ArbolRpart_ctree,extra=4) #visualizamos el árbol

f13
## $obj
## n= 112 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 112 72 A (0.3571429 0.3392857 0.3035714)  
##   2) Km< 24.5 40  0 A (1.0000000 0.0000000 0.0000000) *
##   3) Km>=24.5 72 34 B (0.0000000 0.5277778 0.4722222)  
##     6) Visitas< 17.5 40  3 B (0.0000000 0.9250000 0.0750000) *
##     7) Visitas>=17.5 32  1 C (0.0000000 0.0312500 0.9687500) *
## 
## $snipped.nodes
## NULL
## 
## $xlim
## [1] -0.2  1.2
## 
## $ylim
## [1] -0.45  1.45
## 
## $x
## [1] 0.37107240 0.08029439 0.66185040 0.39750676 0.92619405
## 
## $y
## [1] 0.95286077 0.49393924 0.49393924 0.03501771 0.03501771
## 
## $branch.x
##        [,1]       [,2]      [,3]      [,4]      [,5]
## x 0.3710724 0.08029439 0.6618504 0.3975068 0.9261940
##          NA 0.31291679 0.4292280 0.6089817 0.7147191
##          NA 0.37107240 0.3710724 0.6618504 0.6618504
## 
## $branch.y
##        [,1]      [,2]      [,3]      [,4]      [,5]
## y 0.9621171 0.6221893 0.5031955 0.1632677 0.1632677
##          NA 0.9528608 0.9528608 0.4939392 0.4939392
##          NA 0.9528608 0.9528608 0.4939392 0.4939392
## 
## $labs
## [1] NA                  "A\n1.00  .00  .00" NA                 
## [4] "B\n.00  .92  .07"  "C\n.00  .03  .97" 
## 
## $cex
## [1] 1
## 
## $boxes
## $boxes$x1
## [1]          NA -0.04856926          NA  0.27938175  0.80806904
## 
## $boxes$y1
## [1]          NA  0.42145010          NA -0.03747143 -0.03747143
## 
## $boxes$x2
## [1]        NA 0.2091580        NA 0.5156318 1.0443191
## 
## $boxes$y2
## [1]        NA 0.6221893        NA 0.1632677 0.1632677
## 
## 
## $split.labs
## [1] ""
## 
## $split.cex
## [1] 1
## 
## $split.box
## $split.box$x1
## [1] 0.2809872        NA 0.5389527        NA        NA
## 
## $split.box$y1
## [1] 0.9249803        NA 0.4660588        NA        NA
## 
## $split.box$x2
## [1] 0.4611576        NA 0.7847481        NA        NA
## 
## $split.box$y2
## [1] 1.0365021        NA 0.5775806        NA        NA
# Estudiamos la evolución del error a medida que el árbol va creciendo
summary(ArbolRpart_ctree) # estadÃ???sticas detalladas de cada nodo
## Call:
## rpart(formula = ArbolRpart, data = trainData, method = "class")
##   n= 112 
## 
##          CP nsplit  rel error     xerror       xstd
## 1 0.5277778      0 1.00000000 1.15277778 0.06438675
## 2 0.4166667      1 0.47222222 0.55555556 0.07042952
## 3 0.0100000      2 0.05555556 0.08333333 0.03309688
## 
## Variable importance
##  Visitas       Km Ingresos   Margen 
##       34       31       21       14 
## 
## Node number 1: 112 observations,    complexity param=0.5277778
##   predicted class=A  expected loss=0.6428571  P(node) =1
##     class counts:    40    38    34
##    probabilities: 0.357 0.339 0.304 
##   left son=2 (40 obs) right son=3 (72 obs)
##   Primary splits:
##       Km       < 24.5 to the left,  improve=38.61111, (0 missing)
##       Visitas  < 8    to the left,  improve=38.61111, (0 missing)
##       Ingresos < 5450 to the left,  improve=27.51111, (0 missing)
##       Margen   < 305  to the right, improve=16.75806, (0 missing)
##   Surrogate splits:
##       Visitas  < 8    to the left,  agree=1.000, adj=1.00, (0 split)
##       Ingresos < 5450 to the left,  agree=0.929, adj=0.80, (0 split)
##       Margen   < 335  to the right, agree=0.839, adj=0.55, (0 split)
## 
## Node number 2: 40 observations
##   predicted class=A  expected loss=0  P(node) =0.3571429
##     class counts:    40     0     0
##    probabilities: 1.000 0.000 0.000 
## 
## Node number 3: 72 observations,    complexity param=0.4166667
##   predicted class=B  expected loss=0.4722222  P(node) =0.6428571
##     class counts:     0    38    34
##    probabilities: 0.000 0.528 0.472 
##   left son=6 (40 obs) right son=7 (32 obs)
##   Primary splits:
##       Visitas  < 17.5 to the left,  improve=28.401390, (0 missing)
##       Km       < 47.5 to the left,  improve=25.263500, (0 missing)
##       Ingresos < 7050 to the left,  improve= 6.469534, (0 missing)
##       Margen   < 295  to the left,  improve= 2.688889, (0 missing)
##   Surrogate splits:
##       Km       < 47.5 to the left,  agree=0.917, adj=0.812, (0 split)
##       Ingresos < 6350 to the left,  agree=0.708, adj=0.344, (0 split)
##       Margen   < 295  to the left,  agree=0.667, adj=0.250, (0 split)
## 
## Node number 6: 40 observations
##   predicted class=B  expected loss=0.075  P(node) =0.3571429
##     class counts:     0    37     3
##    probabilities: 0.000 0.925 0.075 
## 
## Node number 7: 32 observations
##   predicted class=C  expected loss=0.03125  P(node) =0.2857143
##     class counts:     0     1    31
##    probabilities: 0.000 0.031 0.969
printcp(ArbolRpart_ctree) # estadÃ???sticas de resultados
## 
## Classification tree:
## rpart(formula = ArbolRpart, data = trainData, method = "class")
## 
## Variables actually used in tree construction:
## [1] Km      Visitas
## 
## Root node error: 72/112 = 0.64286
## 
## n= 112 
## 
##        CP nsplit rel error   xerror     xstd
## 1 0.52778      0  1.000000 1.152778 0.064387
## 2 0.41667      1  0.472222 0.555556 0.070430
## 3 0.01000      2  0.055556 0.083333 0.033097
plotcp(ArbolRpart_ctree) # evolución del error a medida que se incrementan los nodos

# Validamos la capacidad de predicción del árbol con el fichero de validación
testPredRpart <- predict(ArbolRpart_ctree, newdata = testData, type = "class")
table(testPredRpart, testData$Comercial)
##              
## testPredRpart  A  B  C
##             A 10  0  0
##             B  0 12  2
##             C  0  0 14
# Calculamos el % de aciertos 
sum(testPredRpart == testData$Comercial)/ length(testData$Comercial)*100
## [1] 94.73684

El árbol de decisión obtenido mediante el paquete rpart clasifica correctamente un 94,73% de los registros. Un resultado bastante alto y aceptable.

Una vez construida una primera versión del árbol, estudiamos la viabilidad de un podado de árbol.

# Podado del árbol
pArbolRpart_ctree<- prune(ArbolRpart_ctree, cp= ArbolRpart_ctree$cptable[which.min(ArbolRpart_ctree$cptable[,"xerror"]),"CP"])
  pArbolRpart_ctree<- prune(ArbolRpart_ctree, cp= 0.02)
# Representación del árbol podado
f14<-rpart.plot(pArbolRpart_ctree,extra=4) #visualizamos el árbol

f14
## $obj
## n= 112 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 112 72 A (0.3571429 0.3392857 0.3035714)  
##   2) Km< 24.5 40  0 A (1.0000000 0.0000000 0.0000000) *
##   3) Km>=24.5 72 34 B (0.0000000 0.5277778 0.4722222)  
##     6) Visitas< 17.5 40  3 B (0.0000000 0.9250000 0.0750000) *
##     7) Visitas>=17.5 32  1 C (0.0000000 0.0312500 0.9687500) *
## 
## $snipped.nodes
## NULL
## 
## $xlim
## [1] -0.2  1.2
## 
## $ylim
## [1] -0.45  1.45
## 
## $x
## [1] 0.37107240 0.08029439 0.66185040 0.39750676 0.92619405
## 
## $y
## [1] 0.95286077 0.49393924 0.49393924 0.03501771 0.03501771
## 
## $branch.x
##        [,1]       [,2]      [,3]      [,4]      [,5]
## x 0.3710724 0.08029439 0.6618504 0.3975068 0.9261940
##          NA 0.31291679 0.4292280 0.6089817 0.7147191
##          NA 0.37107240 0.3710724 0.6618504 0.6618504
## 
## $branch.y
##        [,1]      [,2]      [,3]      [,4]      [,5]
## y 0.9621171 0.6221893 0.5031955 0.1632677 0.1632677
##          NA 0.9528608 0.9528608 0.4939392 0.4939392
##          NA 0.9528608 0.9528608 0.4939392 0.4939392
## 
## $labs
## [1] NA                  "A\n1.00  .00  .00" NA                 
## [4] "B\n.00  .92  .07"  "C\n.00  .03  .97" 
## 
## $cex
## [1] 1
## 
## $boxes
## $boxes$x1
## [1]          NA -0.04856926          NA  0.27938175  0.80806904
## 
## $boxes$y1
## [1]          NA  0.42145010          NA -0.03747143 -0.03747143
## 
## $boxes$x2
## [1]        NA 0.2091580        NA 0.5156318 1.0443191
## 
## $boxes$y2
## [1]        NA 0.6221893        NA 0.1632677 0.1632677
## 
## 
## $split.labs
## [1] ""
## 
## $split.cex
## [1] 1
## 
## $split.box
## $split.box$x1
## [1] 0.2809872        NA 0.5389527        NA        NA
## 
## $split.box$y1
## [1] 0.9249803        NA 0.4660588        NA        NA
## 
## $split.box$x2
## [1] 0.4611576        NA 0.7847481        NA        NA
## 
## $split.box$y2
## [1] 1.0365021        NA 0.5775806        NA        NA

Dado que el árbol original es muy simple. El podado no devuelve ninguna versión nueva reducida.


Clasificación de los Comerciales con árboles de decisión múltimples (paquete randomForest)


Una vez evaluada la capacidad predictiva del algoritmo K-NN, y los árboles de decisión simples obtenidos mediante los paquetes party y rpart, estimamos el modelo que obtendr�??amos si ejecutásemos n árboles de decisión simultáneamente (para n=100 en nuestro caso) mediante el algoritmo randomForest.

El algoritmo randomForest es un método de estimación combinado, donde el resultado de la estimación se construye a partir de los resultados obtenidos mediante el cálculo de n árboles donde los predictores son incluidos al azar.

Es un método complejo con ventajas e inconvenientes respecto a los árboles de clasificación simples:

Ventajas

Inconvenientes

# Dividimos el fichero en 70% entreno y 30% validación  (parte recurrente en todo experimento)
set.seed(1234)
ind <- sample(2, nrow(Data_PEC2), replace=TRUE, prob=c(0.7, 0.3))
trainData <- Data_PEC2[ind==1,]
testData <- Data_PEC2[ind==2,]
#Declaramos función del árbol
ArbolRF <- Comercial ~ Ingresos + Margen + Km + Visitas
#Aplicamos algoritmo
ArbolRF_ctree <- randomForest(ArbolRF, data=trainData, ntree=100,proximity=T) #indicamos el número de árboles mediante ntree=100
#Obtenemos la importancia de cada variable en el proceso de clasificación
importance(ArbolRF_ctree)      #Importancia de las variables en formato text
##          MeanDecreaseGini
## Ingresos         7.731585
## Margen           1.775483
## Km              28.376887
## Visitas         35.959795
f15<-varImpPlot(ArbolRF_ctree) #Importancia de las variables en formato gráfico

f15
##          MeanDecreaseGini
## Ingresos         7.731585
## Margen           1.775483
## Km              28.376887
## Visitas         35.959795
#evolución del error según el número de árboles
f16<-plot(ArbolRF_ctree, main = "")  

f16
##               OOB A          B          C
##   [1,] 0.04347826 0 0.05882353 0.07142857
##   [2,] 0.05714286 0 0.11111111 0.06250000
##   [3,] 0.08333333 0 0.10344828 0.16000000
##   [4,] 0.08510638 0 0.09375000 0.16666667
##   [5,] 0.07920792 0 0.08571429 0.15625000
##   [6,] 0.07619048 0 0.08333333 0.14705882
##   [7,] 0.07476636 0 0.08333333 0.14705882
##   [8,] 0.07407407 0 0.08108108 0.14705882
##   [9,] 0.07339450 0 0.07894737 0.14705882
##  [10,] 0.06363636 0 0.07894737 0.11764706
##  [11,] 0.06363636 0 0.07894737 0.11764706
##  [12,] 0.05454545 0 0.07894737 0.08823529
##  [13,] 0.05405405 0 0.07894737 0.08823529
##  [14,] 0.05357143 0 0.07894737 0.08823529
##  [15,] 0.05357143 0 0.07894737 0.08823529
##  [16,] 0.05357143 0 0.07894737 0.08823529
##  [17,] 0.05357143 0 0.07894737 0.08823529
##  [18,] 0.05357143 0 0.07894737 0.08823529
##  [19,] 0.05357143 0 0.07894737 0.08823529
##  [20,] 0.05357143 0 0.07894737 0.08823529
##  [21,] 0.05357143 0 0.07894737 0.08823529
##  [22,] 0.05357143 0 0.07894737 0.08823529
##  [23,] 0.05357143 0 0.07894737 0.08823529
##  [24,] 0.05357143 0 0.07894737 0.08823529
##  [25,] 0.05357143 0 0.07894737 0.08823529
##  [26,] 0.05357143 0 0.07894737 0.08823529
##  [27,] 0.05357143 0 0.07894737 0.08823529
##  [28,] 0.05357143 0 0.07894737 0.08823529
##  [29,] 0.05357143 0 0.07894737 0.08823529
##  [30,] 0.05357143 0 0.07894737 0.08823529
##  [31,] 0.05357143 0 0.07894737 0.08823529
##  [32,] 0.05357143 0 0.07894737 0.08823529
##  [33,] 0.05357143 0 0.07894737 0.08823529
##  [34,] 0.05357143 0 0.07894737 0.08823529
##  [35,] 0.05357143 0 0.07894737 0.08823529
##  [36,] 0.05357143 0 0.07894737 0.08823529
##  [37,] 0.05357143 0 0.07894737 0.08823529
##  [38,] 0.05357143 0 0.07894737 0.08823529
##  [39,] 0.05357143 0 0.07894737 0.08823529
##  [40,] 0.04464286 0 0.07894737 0.05882353
##  [41,] 0.05357143 0 0.07894737 0.08823529
##  [42,] 0.04464286 0 0.07894737 0.05882353
##  [43,] 0.04464286 0 0.07894737 0.05882353
##  [44,] 0.04464286 0 0.07894737 0.05882353
##  [45,] 0.04464286 0 0.07894737 0.05882353
##  [46,] 0.04464286 0 0.07894737 0.05882353
##  [47,] 0.04464286 0 0.07894737 0.05882353
##  [48,] 0.04464286 0 0.07894737 0.05882353
##  [49,] 0.05357143 0 0.07894737 0.08823529
##  [50,] 0.04464286 0 0.07894737 0.05882353
##  [51,] 0.04464286 0 0.07894737 0.05882353
##  [52,] 0.04464286 0 0.07894737 0.05882353
##  [53,] 0.04464286 0 0.07894737 0.05882353
##  [54,] 0.04464286 0 0.07894737 0.05882353
##  [55,] 0.04464286 0 0.07894737 0.05882353
##  [56,] 0.04464286 0 0.07894737 0.05882353
##  [57,] 0.04464286 0 0.07894737 0.05882353
##  [58,] 0.04464286 0 0.07894737 0.05882353
##  [59,] 0.04464286 0 0.07894737 0.05882353
##  [60,] 0.04464286 0 0.07894737 0.05882353
##  [61,] 0.04464286 0 0.07894737 0.05882353
##  [62,] 0.04464286 0 0.07894737 0.05882353
##  [63,] 0.04464286 0 0.07894737 0.05882353
##  [64,] 0.04464286 0 0.07894737 0.05882353
##  [65,] 0.04464286 0 0.07894737 0.05882353
##  [66,] 0.04464286 0 0.07894737 0.05882353
##  [67,] 0.04464286 0 0.07894737 0.05882353
##  [68,] 0.04464286 0 0.07894737 0.05882353
##  [69,] 0.04464286 0 0.07894737 0.05882353
##  [70,] 0.04464286 0 0.07894737 0.05882353
##  [71,] 0.04464286 0 0.07894737 0.05882353
##  [72,] 0.04464286 0 0.07894737 0.05882353
##  [73,] 0.04464286 0 0.07894737 0.05882353
##  [74,] 0.04464286 0 0.07894737 0.05882353
##  [75,] 0.04464286 0 0.07894737 0.05882353
##  [76,] 0.04464286 0 0.07894737 0.05882353
##  [77,] 0.04464286 0 0.07894737 0.05882353
##  [78,] 0.04464286 0 0.07894737 0.05882353
##  [79,] 0.04464286 0 0.07894737 0.05882353
##  [80,] 0.04464286 0 0.07894737 0.05882353
##  [81,] 0.04464286 0 0.07894737 0.05882353
##  [82,] 0.04464286 0 0.07894737 0.05882353
##  [83,] 0.04464286 0 0.07894737 0.05882353
##  [84,] 0.04464286 0 0.07894737 0.05882353
##  [85,] 0.04464286 0 0.07894737 0.05882353
##  [86,] 0.04464286 0 0.07894737 0.05882353
##  [87,] 0.04464286 0 0.07894737 0.05882353
##  [88,] 0.04464286 0 0.07894737 0.05882353
##  [89,] 0.04464286 0 0.07894737 0.05882353
##  [90,] 0.04464286 0 0.07894737 0.05882353
##  [91,] 0.04464286 0 0.07894737 0.05882353
##  [92,] 0.04464286 0 0.07894737 0.05882353
##  [93,] 0.04464286 0 0.07894737 0.05882353
##  [94,] 0.04464286 0 0.07894737 0.05882353
##  [95,] 0.04464286 0 0.07894737 0.05882353
##  [96,] 0.04464286 0 0.07894737 0.05882353
##  [97,] 0.04464286 0 0.07894737 0.05882353
##  [98,] 0.04464286 0 0.07894737 0.05882353
##  [99,] 0.04464286 0 0.07894737 0.05882353
## [100,] 0.04464286 0 0.07894737 0.05882353
# Validamos la capacidad de predicción del árbol con el fichero de validación
  testPredRF <- predict(ArbolRF_ctree, newdata = testData)
  table(testPredRF, testData$Comercial)
##           
## testPredRF  A  B  C
##          A 10  0  0
##          B  0 12  2
##          C  0  0 14
# Calculamos el % de aciertos 
sum(testPredRF == testData$Comercial)/ length(testData$Comercial)*100
## [1] 94.73684

El árbol de decisión obtenido mediante el paquete randomForest clasifica correctamente un 94,73% de los registros. Un resultado bastante alto y aceptable.



Ejercicios


Pregunta 1. ¿La capacidad predictiva del modelo K-NN se incrementa si aumentamos la k hasta 10 (k=5, 6, 7, 8, 9 y 10)?

# Aplicamos el algoritmo K-NN seleccionando 5 como k inicial
KnnTestPrediccion_k5 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 5, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k5)
##    KnnTestPrediccion_k5
##     A B C
##   A 9 1 0
##   B 3 8 1
##   C 0 7 9
# Calculamos el % de aciertos para k=5
sum(KnnTestPrediccion_k5 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 68.42105
# Aplicamos el algoritmo K-NN seleccionando 6 como k inicial
KnnTestPrediccion_k6 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 6, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k6)
##    KnnTestPrediccion_k6
##      A  B  C
##   A  9  1  0
##   B  3  8  1
##   C  0  6 10
# Calculamos el % de aciertos para k=6
sum(KnnTestPrediccion_k6 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 71.05263
# Aplicamos el algoritmo K-NN seleccionando 7 como k inicial
KnnTestPrediccion_k7 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 7, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k7)
##    KnnTestPrediccion_k7
##      A  B  C
##   A  9  1  0
##   B  3  8  1
##   C  0  6 10
# Calculamos el % de aciertos para k=7
sum(KnnTestPrediccion_k7 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 71.05263
# Aplicamos el algoritmo K-NN seleccionando 8 como k inicial
KnnTestPrediccion_k8 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 8, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k8)
##    KnnTestPrediccion_k8
##      A  B  C
##   A  9  1  0
##   B  3  7  2
##   C  0  6 10
# Calculamos el % de aciertos para k=8
sum(KnnTestPrediccion_k8 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 68.42105
# Aplicamos el algoritmo K-NN seleccionando 9 como k inicial
KnnTestPrediccion_k9 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 9, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k9)
##    KnnTestPrediccion_k9
##      A  B  C
##   A  9  1  0
##   B  3  7  2
##   C  0  5 11
# Calculamos el % de aciertos para k=9
sum(KnnTestPrediccion_k9 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 71.05263
# Aplicamos el algoritmo K-NN seleccionando 10 como k inicial
KnnTestPrediccion_k10 <- knn(trainData[,1:4],testData[,1:4], trainData$Comercial , k = 10, prob = TRUE )
table ( testData$Comercial , KnnTestPrediccion_k10)
##    KnnTestPrediccion_k10
##      A  B  C
##   A  9  1  0
##   B  3  7  2
##   C  0  5 11
# Calculamos el % de aciertos para k=10
sum(KnnTestPrediccion_k10 == testData$Comercial)/ length(testData$Comercial)*100
## [1] 71.05263
# Al aumentar la k hasta 10, no hemos conseguido superar la capacidad predictiva de k=1. Valores grandes de k reducen el efecto de ruido en la clasificación, pero crean límites entre clases parecidas.

Pregunta 2. ¿Qué variables influyen significativamente en el proceso de estimación de cada método? Indica cómo podemos identificar las variables influyentes de cada modelo y cuál es el peso de cada una de ellas

# En el modelo K-NN, utiliza el valor de los k valores más cercanos y ello determina la variable DISTANCIA. La idea que fundamenta este algoritmo es que el nuevo objeto se clasificará en la clase más frecuente de sus K vecinos más próximos. Respecto del peso de las variables cuantitativas, hemos de decir que todas tiene el mismo peso salvo que decidamos otorgar mayor peso a alguna de las variables, en ese caso nos encontraremos frente un caso de Algoritmo K-NN con pesado de variables. Por otra parte, en el caso de valores de k pares, y en que se de la situación en que exista igualdad de casos para cada una de las etiquetas posibles, el resultado se determinará en función de los pesos de cada etiqueta que se atribuyen en función de la distancia al punto que queremos predecir (p.e. método de Shepard).

# En el modelo de clasificación con árboles de decisión simples, el algoritmo busca cuál es la variable más influyente, que permite obtener una submuestra más diferenciada para la variable dependiente, e identifica también qué intervalos ó agrupación de categorías de la/s variable/s independiente/s permitiría/n maximizar dicha división. A partir de esa varible más influyentes, continua estableciendo clasificaciones en funcioón del resto de variables por orden de importancia.

# En el modelo de clasificación con árboles de decisión múltiples, el aldoritmo puede determina la importancia de cada una de las variables. Para ello se utiliza la función importance(ArbolRF_ctree).

Pregunta 3. A partir de los resultados obtenidos ¿Qué algoritmo/s deber�??amos tomar como referencia para hacer predicciones sobre el fichero de trabajo? Elabora vuestra respuesta considerando la facilidad de cálculo, la facilidad de interpretación de resultados, la capacidad predictiva de cada modelo y el principio de parsimonia (ante dos soluciones tomaremos siempre la más simple)

# Basándonos en la capacidad predictiva de los tres modelos, los más efectivoso son los modelos rpart y randomForest. De los dos modelos más efectivos, el rpart es bastante más fácil de calcular y de más sencilla interpretación. Por tanto el modelo más decuado para hace predicciones en el actual modelo de trabajo es el ARBOLES DE DECISION SIMPLES, utlizando el paquete RPART.

Pregunta 4. Si rpart y randomForest tiene el mismo porcentaje de clasificación correcta ¿están asignando los mismos individuos a cada grupo de Comerciales? Y, en paralelo, ¿Qué individuos no están clasificados del mismo modo que el resultado de K-NN para k=2.

# SI, ambos modelos están asignado los mismos individuos a cada grupo de Comerciales.

# En los modelos rpart y randomForest se clasifica un total de 38 individuos (A-10 ; B-12; C-16), en cambio en el modelo KNN con K=2, se clasifica el mismo número de individuos, 38, pero con resultados diferentes (A-12; B-15; C-11)

Pregunta 5. A partir de los resultados obtenidos, ¿Cómo podr�??amos clasificar los 10 individuos registrados en el fichero PE2NuevosRegistros.csv? Desarolla la solución aplicando las reglas obtenidas en rpart en una hoja de cálculo y aplicando los algoritmos sobre el un nuevo fichero de datos que incluya los 160 registros (150 originales + 10 nuevos registros)

# Clasificación de los 10 nuevos registros:
#Ingresos   Margen  Km  Visitas Comercial
#  6900     310   49       15         B
#  5800     270   41       10         B
#  6800     300   55       21         C
#  5800     270   39       12         B
#  5000     340   15        2         A
#  4600     360   10        2         A
#  5800     270   51       19         C
#  4900     310   15        1         A
#  6100     300   49       18         C
#  6300     290   43     13       B
# Desarolla la solución aplicando las reglas obtenidas en *rpart* en una hoja de cálculo y aplicando los algoritmos sobre el un nuevo fichero de datos que incluya los 160 registros (150 originales + 10 nuevos registros)
#cargamos el fichero de datos que utilizamos para desarrollar la PEC2NR

nombreruta_PEC2 <- paste(getwd(),"/PEC2new.csv", sep = "")

Data_PEC2 <- read.csv(nombreruta_PEC2, encoding="UTF-8",                   header=TRUE, sep=";", na.strings="NA", dec=".", strip.white=TRUE)

library(rpart)
library(rpart.plot)
# Dividimos el fichero en 70% entreno y 30% validación  #
set.seed(1234)
ind <- sample(2, nrow(Data_PEC2), replace=TRUE, prob=c(0.7, 0.3))
trainData <- Data_PEC2[ind==1,]
testData <- Data_PEC2[ind==2,]
#Declaramos función del árbol
ArbolRpart <- Comercial ~ Ingresos + Margen + Km + Visitas
#Aplicamos algoritmo
ArbolRpart_ctree <- rpart(ArbolRpart, method="class", data=trainData)
#Obtenemos la relación de reglas de asociación del árbol en formato listado
print(ArbolRpart_ctree) # estadÃ???sticas detalladas de cada nodo
## n= 119 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 119 76 B (0.35294118 0.36134454 0.28571429)  
##   2) Km< 24.5 42  0 A (1.00000000 0.00000000 0.00000000) *
##   3) Km>=24.5 77 34 B (0.00000000 0.55844156 0.44155844)  
##     6) Visitas< 16.5 45  2 B (0.00000000 0.95555556 0.04444444) *
##     7) Visitas>=16.5 32  0 C (0.00000000 0.00000000 1.00000000) *
#Obtenemos el árbol con un diseño gráfico cuidado
f13<-rpart.plot(ArbolRpart_ctree,extra=4) #visualizamos el árbol

f13
## $obj
## n= 119 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 119 76 B (0.35294118 0.36134454 0.28571429)  
##   2) Km< 24.5 42  0 A (1.00000000 0.00000000 0.00000000) *
##   3) Km>=24.5 77 34 B (0.00000000 0.55844156 0.44155844)  
##     6) Visitas< 16.5 45  2 B (0.00000000 0.95555556 0.04444444) *
##     7) Visitas>=16.5 32  0 C (0.00000000 0.00000000 1.00000000) *
## 
## $snipped.nodes
## NULL
## 
## $xlim
## [1] -0.2  1.2
## 
## $ylim
## [1] -0.45  1.45
## 
## $x
## [1] 0.36868024 0.07977676 0.65758371 0.39494419 0.92022324
## 
## $y
## [1] 0.95286077 0.49393924 0.49393924 0.03501771 0.03501771
## 
## $branch.x
##        [,1]       [,2]      [,3]      [,4]      [,5]
## x 0.3686802 0.07977676 0.6575837 0.3949442 0.9202232
##          NA 0.31089954 0.4264609 0.6050558 0.7101116
##          NA 0.36868024 0.3686802 0.6575837 0.6575837
## 
## $branch.y
##        [,1]      [,2]      [,3]      [,4]      [,5]
## y 0.9621171 0.6221893 0.5031955 0.1632677 0.1632677
##          NA 0.9528608 0.9528608 0.4939392 0.4939392
##          NA 0.9528608 0.9528608 0.4939392 0.4939392
## 
## $labs
## [1] NA                  "A\n1.00  .00  .00" NA                 
## [4] "B\n.00  .96  .04"  "C\n.00  .00  1.00"
## 
## $cex
## [1] 1
## 
## $boxes
## $boxes$x1
## [1]          NA -0.04908688          NA  0.27681918  0.79135959
## 
## $boxes$y1
## [1]          NA  0.42145010          NA -0.03747143 -0.03747143
## 
## $boxes$x2
## [1]        NA 0.2086404        NA 0.5130692 1.0490869
## 
## $boxes$y2
## [1]        NA 0.6221893        NA 0.1632677 0.1632677
## 
## 
## $split.labs
## [1] ""
## 
## $split.cex
## [1] 1
## 
## $split.box
## $split.box$x1
## [1] 0.278595       NA 0.534686       NA       NA
## 
## $split.box$y1
## [1] 0.9249803        NA 0.4660588        NA        NA
## 
## $split.box$x2
## [1] 0.4587655        NA 0.7804815        NA        NA
## 
## $split.box$y2
## [1] 1.0365021        NA 0.5775806        NA        NA
# Estudiamos la evolución del error a medida que el árbol va creciendo
summary(ArbolRpart_ctree) # estadÃ???sticas detalladas de cada nodo
## Call:
## rpart(formula = ArbolRpart, data = trainData, method = "class")
##   n= 119 
## 
##          CP nsplit  rel error     xerror       xstd
## 1 0.5526316      0 1.00000000 1.21052632 0.06011581
## 2 0.4210526      1 0.44736842 0.44736842 0.06484281
## 3 0.0100000      2 0.02631579 0.02631579 0.01845104
## 
## Variable importance
##  Visitas       Km Ingresos   Margen 
##       34       31       20       14 
## 
## Node number 1: 119 observations,    complexity param=0.5526316
##   predicted class=B  expected loss=0.6386555  P(node) =1
##     class counts:    42    43    34
##    probabilities: 0.353 0.361 0.286 
##   left son=2 (42 obs) right son=3 (77 obs)
##   Primary splits:
##       Km       < 24.5 to the left,  improve=40.95034, (0 missing)
##       Visitas  < 8    to the left,  improve=40.95034, (0 missing)
##       Ingresos < 5450 to the left,  improve=27.32013, (0 missing)
##       Margen   < 305  to the right, improve=17.43176, (0 missing)
##   Surrogate splits:
##       Visitas  < 8    to the left,  agree=1.000, adj=1.000, (0 split)
##       Ingresos < 5450 to the left,  agree=0.916, adj=0.762, (0 split)
##       Margen   < 335  to the right, agree=0.840, adj=0.548, (0 split)
## 
## Node number 2: 42 observations
##   predicted class=A  expected loss=0  P(node) =0.3529412
##     class counts:    42     0     0
##    probabilities: 1.000 0.000 0.000 
## 
## Node number 3: 77 observations,    complexity param=0.4210526
##   predicted class=B  expected loss=0.4415584  P(node) =0.6470588
##     class counts:     0    43    34
##    probabilities: 0.000 0.558 0.442 
##   left son=6 (45 obs) right son=7 (32 obs)
##   Primary splits:
##       Visitas  < 16.5 to the left,  improve=34.151800, (0 missing)
##       Km       < 47.5 to the left,  improve=27.341100, (0 missing)
##       Ingresos < 6150 to the left,  improve= 7.022609, (0 missing)
##       Margen   < 295  to the left,  improve= 3.685137, (0 missing)
##   Surrogate splits:
##       Km       < 50.5 to the left,  agree=0.909, adj=0.781, (0 split)
##       Ingresos < 6350 to the left,  agree=0.740, adj=0.375, (0 split)
##       Margen   < 295  to the left,  agree=0.688, adj=0.250, (0 split)
## 
## Node number 6: 45 observations
##   predicted class=B  expected loss=0.04444444  P(node) =0.3781513
##     class counts:     0    43     2
##    probabilities: 0.000 0.956 0.044 
## 
## Node number 7: 32 observations
##   predicted class=C  expected loss=0  P(node) =0.2689076
##     class counts:     0     0    32
##    probabilities: 0.000 0.000 1.000
printcp(ArbolRpart_ctree) # estadÃ???sticas de resultados
## 
## Classification tree:
## rpart(formula = ArbolRpart, data = trainData, method = "class")
## 
## Variables actually used in tree construction:
## [1] Km      Visitas
## 
## Root node error: 76/119 = 0.63866
## 
## n= 119 
## 
##        CP nsplit rel error   xerror     xstd
## 1 0.55263      0  1.000000 1.210526 0.060116
## 2 0.42105      1  0.447368 0.447368 0.064843
## 3 0.01000      2  0.026316 0.026316 0.018451
plotcp(ArbolRpart_ctree) # evolución del error a medida que se incrementan los nodos

# Validamos la capacidad de predicción del árbol con el fichero de validación
testPredRpart <- predict(ArbolRpart_ctree, newdata = testData, type = "class")
table(testPredRpart, testData$Comercial)
##              
## testPredRpart  A  B  C
##             A 11  0  0
##             B  0  9  2
##             C  0  2 17
# Calculamos el % de aciertos 
sum(testPredRpart == testData$Comercial)/ length(testData$Comercial)*100
## [1] 90.2439