Objetivo

Construir interpretar un modelo de árbol de clasificación para predecir estados de felicidad de una persona conforme a características.

Descripción

Desarrollo

Cargar librerías

Cargar librerías y es necesario instalar aquellas que no se tienen de manera anticipada.

library(readr) # install.package
library(dplyr)
library(caret) # Para matriz de confusion
library(rpart) # Para arbol
library(rpart.plot) # Para arbol

library(knitr)  # Para tablas amigables con los datos

Cargar los datos

datos <- read.csv("https://raw.githubusercontent.com/rpizarrog/Industrias-4.0/main/datos/estado%20de%20felicidad%20variables.csv", encoding = "UTF-8", stringsAsFactors = TRUE)

kable(datos, caption = "Los datos")
Los datos
genero esto.civil edad satisfaccion.laboral satisfaccion.profesional vida.familiar vida.social salud dinero estado
MASCULINO SOLTERO 25 80.0 90.0 70.0 80.00 BUENO 90.0 FELIZ
FEMENINO CASADO 35 50.0 80.0 60.0 70.00 MALO 30.0 NO FELIZ
MASCULINO DIVORCIADO 45 70.0 78.0 80.0 40.00 REGULAR 70.0 FELIZ
FEMENINO VIUDO 54 50.0 80.0 60.0 80.00 BUENO 20.0 NO FELIZ
MASCULINO CASADO 52 40.0 50.0 60.0 70.00 BUENO 60.0 NO FELIZ
FEMENINO SOLTERO 28 50.0 60.0 54.0 60.00 MALO 50.0 NO FELIZ
MASCULINO VIUDO 56 71.5 60.8 86.9 70.60 MALO 70.0 FELIZ
FEMENINO DIVORCIADO 32 60.0 80.0 30.0 50.00 REGULAR 20.0 NO FELIZ
MASCULINO CASADO 35 70.0 60.0 72.0 60.00 BUENO 70.0 FELIZ
FEMENINO SOLTERO 29 80.0 80.0 90.0 60.00 MALO 80.0 FELIZ
MASCULINO DIVORCIADO 45 60.0 60.0 70.0 50.00 REGULAR 90.0 FELIZ
FEMENINO VIUDO 48 60.0 50.0 50.0 45.50 MALO 70.0 NO FELIZ
MASCULINO CASADO 26 50.0 45.0 80.0 60.00 MALO 20.0 NO FELIZ
FEMENINO SOLTERO 34 60.0 40.0 50.0 80.00 BUENO 65.9 FELIZ
MASCULINO DIVORCIADO 42 50.0 65.0 56.0 62.58 REGULAR 33.5 NO FELIZ
FEMENINO VIUDO 35 80.0 70.0 20.0 20.00 MALO 20.5 NO FELIZ
MASCULINO CASADO 48 50.0 50.0 50.0 50.00 BUENO 49.5 FELIZ
FEMENINO SOLTERO 34 54.0 80.0 56.0 60.00 REGULAR 55.0 FELIZ
MASCULINO DIVORCIADO 34 60.0 70.0 80.0 50.00 MALO 100.0 FELIZ
FEMENINO SOLTERO 32 40.0 50.0 80.0 90.00 BUENO 95.0 FELIZ
MASCULINO SOLTERO 29 50.0 60.0 60.0 80.00 MALO 70.0 FELIZ
FEMENINO SOLTERO 26 60.0 60.0 60.0 60.00 BUENO 60.0 FELIZ
MASCULINO CASADO 45 60.0 60.0 60.0 60.00 BUENO 50.0 FELIZ
FEMENINO VIUDO 45 50.0 60.0 60.0 30.00 REGULAR 35.0 NO FELIZ
MASCULINO CASADO 28 50.0 40.0 80.0 30.00 MALO 30.0 NO FELIZ
FEMENINO DIVORCIADO 32 80.0 70.0 40.0 40.00 MALO 40.0 NO FELIZ
MASCULINO SOLTERO 36 65.0 60.0 62.0 87.00 REGULAR 56.5 FELIZ
FEMENINO CASADO 40 45.0 50.0 40.0 90.00 MALO 60.0 NO FELIZ
MASCULINO SOLTERO 41 60.0 60.0 60.0 60.00 BUENO 49.0 FELIZ
FEMENINO VIUDO 38 80.0 70.0 30.0 40.00 BUENO 45.0 NO FELIZ
MASCULINO CASADO 36 85.0 80.0 90.0 50.00 BUENO 80.0 FELIZ
FEMENINO CASADO 38 60.0 80.0 90.0 80.00 BUENO 60.0 FELIZ
FEMENINO CASADO 37 80.0 60.0 70.0 50.00 BUENO 60.0 FELIZ
FEMENINO SOLTERO 40 60.0 80.0 40.0 50.00 REGULAR 30.0 NO FELIZ
MASCULINO CASADO 40 60.0 70.0 50.0 30.00 BUENO 50.0 FELIZ
FEMENINO CASADO 43 95.0 80.0 90.0 90.00 BUENO 80.0 FELIZ
MASCULINO CASADO 55 70.0 70.0 65.0 89.00 MALO 75.0 FELIZ
MASCULINO SOLTERO 45 65.0 70.0 45.0 65.00 BUENO 45.0 FELIZ
FEMENINO CASADO 41 24.0 57.0 33.0 71.00 BUENO 100.0 NO FELIZ
FEMENINO SOLTERO 40 80.0 80.0 90.0 30.00 REGULAR 50.0 FELIZ
MASCULINO SOLTERO 39 60.0 80.0 48.0 50.00 BUENO 60.0 FELIZ
MASCULINO SOLTERO 42 90.0 80.0 50.0 100.00 REGULAR 80.0 FELIZ
FEMENINO SOLTERO 45 90.0 95.0 90.0 100.00 BUENO 90.0 FELIZ
MASCULINO VIUDO 88 65.0 66.0 89.0 87.00 REGULAR 45.0 NO FELIZ
MASCULINO CASADO 54 90.0 90.0 90.0 100.00 BUENO 75.0 FELIZ
MASCULINO SOLTERO 80 80.0 80.0 90.0 90.00 BUENO 90.0 FELIZ
MASCULINO SOLTERO 39 50.0 80.0 90.0 80.00 REGULAR 90.0 FELIZ
FEMENINO SOLTERO 40 30.0 60.0 80.0 50.00 REGULAR 50.0 NO FELIZ
FEMENINO SOLTERO 49 80.0 80.0 80.0 80.00 BUENO 70.0 FELIZ
MASCULINO SOLTERO 39 60.0 80.0 48.0 50.00 REGULAR 50.0 NO FELIZ
FEMENINO SOLTERO 30 100.0 100.0 100.0 100.00 BUENO 100.0 NO FELIZ
FEMENINO SOLTERO 32 70.0 80.0 80.0 80.00 BUENO 80.0 FELIZ

Describir los datos

summary(datos)
##        genero        esto.civil      edad       satisfaccion.laboral
##  FEMENINO :26   CASADO    :16   Min.   :25.00   Min.   : 24.00      
##  MASCULINO:26   DIVORCIADO: 6   1st Qu.:34.00   1st Qu.: 50.00      
##                 SOLTERO   :23   Median :39.50   Median : 60.00      
##                 VIUDO     : 7   Mean   :40.79   Mean   : 64.03      
##                                 3rd Qu.:45.00   3rd Qu.: 80.00      
##                                 Max.   :88.00   Max.   :100.00      
##  satisfaccion.profesional vida.familiar     vida.social         salud   
##  Min.   : 40.00           Min.   : 20.00   Min.   : 20.00   BUENO  :25  
##  1st Qu.: 60.00           1st Qu.: 50.00   1st Qu.: 50.00   MALO   :13  
##  Median : 70.00           Median : 61.00   Median : 60.00   REGULAR:14  
##  Mean   : 68.98           Mean   : 65.48   Mean   : 64.57               
##  3rd Qu.: 80.00           3rd Qu.: 80.00   3rd Qu.: 80.00               
##  Max.   :100.00           Max.   :100.00   Max.   :100.00               
##      dinero            estado  
##  Min.   : 20.00   FELIZ   :32  
##  1st Qu.: 48.00   NO FELIZ:20  
##  Median : 60.00                
##  Mean   : 60.86                
##  3rd Qu.: 80.00                
##  Max.   :100.00

Estructura de los datos

str(datos)
## 'data.frame':    52 obs. of  10 variables:
##  $ genero                  : Factor w/ 2 levels "FEMENINO","MASCULINO": 2 1 2 1 2 1 2 1 2 1 ...
##  $ esto.civil              : Factor w/ 4 levels "CASADO","DIVORCIADO",..: 3 1 2 4 1 3 4 2 1 3 ...
##  $ edad                    : int  25 35 45 54 52 28 56 32 35 29 ...
##  $ satisfaccion.laboral    : num  80 50 70 50 40 50 71.5 60 70 80 ...
##  $ satisfaccion.profesional: num  90 80 78 80 50 60 60.8 80 60 80 ...
##  $ vida.familiar           : num  70 60 80 60 60 54 86.9 30 72 90 ...
##  $ vida.social             : num  80 70 40 80 70 60 70.6 50 60 60 ...
##  $ salud                   : Factor w/ 3 levels "BUENO","MALO",..: 1 2 3 1 1 2 2 3 1 2 ...
##  $ dinero                  : num  90 30 70 20 60 50 70 20 70 80 ...
##  $ estado                  : Factor w/ 2 levels "FELIZ","NO FELIZ": 1 2 1 2 2 2 1 2 1 1 ...

Modelo de Clasificación

Tarea a resolver

Realizar una tarea de clasificación para predecir si una persona es FELIZ O NO FELIZ de acuerdo a ciertas características o variables independientes.

Definir métricas

  • El modelo debe tener un valor de exactitud mayor al 60%

  • El modelo debe garantizar una precisión de valores positivos mayor al 50%

  • El modelo debe garantizar una precisión de valores negativos mayor al 20%

  • Debe tener un valor de sensibilidad superior al 40%

  • Debe tener un valor de especificidad superior al 35%

Construir el modelo

modelo <- rpart(estado ~ ., data = datos)

sm <- summary(modelo)
## Call:
## rpart(formula = estado ~ ., data = datos)
##   n= 52 
## 
##     CP nsplit rel error xerror      xstd
## 1 0.55      0      1.00   1.00 0.1754116
## 2 0.05      1      0.45   0.55 0.1472504
## 3 0.01      2      0.40   0.75 0.1633484
## 
## Variable importance
##                   dinero            vida.familiar     satisfaccion.laboral 
##                       45                       17                       13 
##               esto.civil satisfaccion.profesional              vida.social 
##                       10                        8                        7 
## 
## Node number 1: 52 observations,    complexity param=0.55
##   predicted class=FELIZ     expected loss=0.3846154  P(node) =1
##     class counts:    32    20
##    probabilities: 0.615 0.385 
##   left son=2 (39 obs) right son=3 (13 obs)
##   Primary splits:
##       dinero               < 47    to the right, improve=10.051280, (0 missing)
##       vida.familiar        < 42.5  to the right, improve= 6.126496, (0 missing)
##       satisfaccion.laboral < 52    to the right, improve= 5.127096, (0 missing)
##       esto.civil           splits as  LLLR,      improve= 3.612210, (0 missing)
##       salud                splits as  LRR,       improve= 3.282051, (0 missing)
##   Surrogate splits:
##       vida.familiar            < 46.5  to the right, agree=0.827, adj=0.308, (0 split)
##       esto.civil               splits as  LLLR,      agree=0.808, adj=0.231, (0 split)
##       vida.social              < 42.75 to the right, agree=0.788, adj=0.154, (0 split)
##       satisfaccion.profesional < 47.5  to the right, agree=0.769, adj=0.077, (0 split)
## 
## Node number 2: 39 observations,    complexity param=0.05
##   predicted class=FELIZ     expected loss=0.2051282  P(node) =0.75
##     class counts:    31     8
##    probabilities: 0.795 0.205 
##   left son=4 (30 obs) right son=5 (9 obs)
##   Primary splits:
##       satisfaccion.laboral     < 52    to the right, improve=2.8735040, (0 missing)
##       vida.familiar            < 55    to the right, improve=2.3386380, (0 missing)
##       satisfaccion.profesional < 58.5  to the right, improve=2.2893770, (0 missing)
##       genero                   splits as  RL,        improve=1.0989010, (0 missing)
##       dinero                   < 62.95 to the right, improve=0.6255574, (0 missing)
##   Surrogate splits:
##       satisfaccion.profesional < 58.5  to the right, agree=0.846, adj=0.333, (0 split)
##       vida.familiar            < 44    to the right, agree=0.821, adj=0.222, (0 split)
## 
## Node number 3: 13 observations
##   predicted class=NO FELIZ  expected loss=0.07692308  P(node) =0.25
##     class counts:     1    12
##    probabilities: 0.077 0.923 
## 
## Node number 4: 30 observations
##   predicted class=FELIZ     expected loss=0.1  P(node) =0.5769231
##     class counts:    27     3
##    probabilities: 0.900 0.100 
## 
## Node number 5: 9 observations
##   predicted class=NO FELIZ  expected loss=0.4444444  P(node) =0.1730769
##     class counts:     4     5
##    probabilities: 0.444 0.556
sm
## n= 52 
## 
## node), split, n, loss, yval, (yprob)
##       * denotes terminal node
## 
## 1) root 52 20 FELIZ (0.61538462 0.38461538)  
##   2) dinero>=47 39  8 FELIZ (0.79487179 0.20512821)  
##     4) satisfaccion.laboral>=52 30  3 FELIZ (0.90000000 0.10000000) *
##     5) satisfaccion.laboral< 52 9  4 NO FELIZ (0.44444444 0.55555556) *
##   3) dinero< 47 13  1 NO FELIZ (0.07692308 0.92307692) *

Visualizar el árbol de clasificación

prp(modelo, main = "Arbol de Clasificación")

prp(modelo, main="Arbol de Clasificación",
    nn = TRUE, # display the node numbers
    fallen.leaves = TRUE,  # put the leaves on the bottom of the page
    shadow.col = "gray",   # shadows under the leaves
    branch.lty = 3,        # draw branches using dotted lines
    branch = .5,           # change angle of branch lines
    faclen = 0,            # faclen = 0 to print full factor names
    trace = 1,             # print the auto calculated cex, xlim, ylim
    split.cex = 1.2,       # make the split text larger than the node text
    split.prefix = "is ",  # put "is " before split text
    split.suffix = "?",    # put "?" after split text
    split.box.col = "lightblue",   # lightgray split boxes (default is white)
    split.border.col = "darkgray", # darkgray border on split boxes
    split.round = 0.5)             # round the split box corners a tad
## cex 1   xlim c(-0.2, 1.2)   ylim c(-0.15, 1.15)

Evaluar el modelo

Por medio de una matriz de confusión construida a partir de los valores reales de la variable estado de los datos y los valores de predicción de la misma variable estado. Se identifican las métricas generadas de la matriz de confusión y se comparan con los criterios establecidos inicialmente.

La variable datos.R.P (datos reales y predicción) tendrá dos columnas ,los datos reales y los de predicción de la variable estado conforme al modelo y a partir de ella construir la matriz de confusión.

Predicción con los datos originales

Se genera predicción con datos originales

prediccion <- predict(object = modelo, datos, type = "class")
prediccion
##        1        2        3        4        5        6        7        8 
##    FELIZ NO FELIZ    FELIZ NO FELIZ NO FELIZ NO FELIZ    FELIZ NO FELIZ 
##        9       10       11       12       13       14       15       16 
##    FELIZ    FELIZ    FELIZ    FELIZ NO FELIZ    FELIZ NO FELIZ NO FELIZ 
##       17       18       19       20       21       22       23       24 
## NO FELIZ    FELIZ    FELIZ NO FELIZ NO FELIZ    FELIZ    FELIZ NO FELIZ 
##       25       26       27       28       29       30       31       32 
## NO FELIZ NO FELIZ    FELIZ NO FELIZ    FELIZ NO FELIZ    FELIZ    FELIZ 
##       33       34       35       36       37       38       39       40 
##    FELIZ NO FELIZ    FELIZ    FELIZ    FELIZ NO FELIZ NO FELIZ    FELIZ 
##       41       42       43       44       45       46       47       48 
##    FELIZ    FELIZ    FELIZ NO FELIZ    FELIZ    FELIZ NO FELIZ NO FELIZ 
##       49       50       51       52 
##    FELIZ    FELIZ    FELIZ    FELIZ 
## Levels: FELIZ NO FELIZ
datos.R.P <- data.frame(realidad = datos$estado, prediccion)

kable(datos.R.P, caption = "Reales / Predicciones")
Reales / Predicciones
realidad prediccion
FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
NO FELIZ NO FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ FELIZ
NO FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
NO FELIZ NO FELIZ
FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ NO FELIZ
FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
NO FELIZ NO FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ NO FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
FELIZ FELIZ
FELIZ NO FELIZ
NO FELIZ NO FELIZ
FELIZ FELIZ
NO FELIZ FELIZ
NO FELIZ FELIZ
FELIZ FELIZ

Crear matriz de confusión

Antes de crear matriz de confusión asegurarse de que las etiquetas del datos.R.P son de tipo factor

datos.R.P$realidad <- as.factor(datos.R.P$realidad)

datos.R.P$prediccion <- as.factor(datos.R.P$prediccion)
matriz <- confusionMatrix(datos.R.P$realidad, datos.R.P$prediccion)

matriz
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction FELIZ NO FELIZ
##   FELIZ       27        5
##   NO FELIZ     3       17
##                                           
##                Accuracy : 0.8462          
##                  95% CI : (0.7192, 0.9312)
##     No Information Rate : 0.5769          
##     P-Value [Acc > NIR] : 3.104e-05       
##                                           
##                   Kappa : 0.681           
##                                           
##  Mcnemar's Test P-Value : 0.7237          
##                                           
##             Sensitivity : 0.9000          
##             Specificity : 0.7727          
##          Pos Pred Value : 0.8438          
##          Neg Pred Value : 0.8500          
##              Prevalence : 0.5769          
##          Detection Rate : 0.5192          
##    Detection Prevalence : 0.6154          
##       Balanced Accuracy : 0.8364          
##                                           
##        'Positive' Class : FELIZ           
## 

Interpretación

De acuerdo a los valores de las métricas de la matriz de confusión con el modelo de árbol de clasificación, las métricas superan las expectativas el ejercicio.

La exactitud es 84.62% que significa que el modelo se equivoca en un 16%.

La precisión de casos positivos es de 84.38% que significa que de acuerdo a la clase de FELIZ el modelo acierta en ese porcentaje.

La precisión de casos negativos es de 85.00% que significa que de acuerdo a la clase de NO FELIZ el modelo acierta en ese porcentaje.

La sensibilidad es del 90% y la especificidad es del 77% que significan e indican la capacidad de estimador para discriminar los casos positivos, de los negativos.

Sensibilidad significa la proporción de casos positivos que fueron correctamente identificadas por el modelo y especificidad significa que de los casos negativos que el modelo ha clasificado correctamente.

Predicciones con casos nuevos

Se crean tres casos nuevos :

genero <- c('MASCULINO', 'FEMENINO', 'FEMENINO')
esto.civil <- c('SOLTERO', 'CASADO', 'DIVORCIADO')
edad <- c(30, 25, 40)
satisfaccion.laboral <- c(40, 50, 60)
satisfaccion.profesional <- c(60, 50, 40)
vida.familiar <- c(80, 70, 60)
vida.social <- c(60,50,76)
salud <- c('BUENO', 'REGULAR', 'MALO')
dinero <- c(40, 50, 60)
prediccion = c('?', '?', '?')

datos.nuevos <- data.frame(genero, edad, satisfaccion.laboral, satisfaccion.profesional, vida.familiar, vida.social, dinero, prediccion )

kable(datos.nuevos, captio = "Datos nuevos")
Datos nuevos
genero edad satisfaccion.laboral satisfaccion.profesional vida.familiar vida.social dinero prediccion
MASCULINO 30 40 60 80 60 40 ?
FEMENINO 25 50 50 70 50 50 ?
FEMENINO 40 60 40 60 76 60 ?

Se hace la predicción

prediccion.nueva <- predict(object = modelo, newdata = datos.nuevos, type = 'class')
prediccion.nueva
##        1        2        3 
## NO FELIZ NO FELIZ    FELIZ 
## Levels: FELIZ NO FELIZ

Explicación / Conclusión

Pendiente …