1. Planteamiento del problema

En este notebook les mostraré paso a paso el análisis del problema propuesto. El objetivo de este ejercicio es la resolución de las siguientes incógnitas:

1. ¿Cómo son los clientes de lujo para enfocar las estrategias de marketing?

- Seleccionar las 10 variables más importantes del dataset

- ¿Son los precios similares a los de la realidad?

2. ¿Cómo hacer la campaña de marketing más efectiva?

- Seleccionar las variables más relevantes

- ¿De qué manera confirmaría que la propuesta es la adecuada?

2. Información general

Los pasos a seguir son los siguientes:

A) Limpieza de la data

B) Exploración de los datos

C) Construcción del modelo

D) Revisión de los resultados

3. Planeamiento del proyecto

Cuando estoy por empezar un proyecto, me gusta poner el plan que llevaré a cabo.

Entender la naturaleza de la data (summary(), str())

Histogramas y boxplots

Conteo de valores

Manipulación de valores nulos

Correlación entre métricas

Exploración de temas interesantes

Feature engineering

Construcción del modelo

Test del modelo (matriz de confusión)

4. Limpieza de la data

Lectura incial de datos

Para empezar, se leen los datos del csv y se ve las dimensiones

db<-read.csv("Base de datos caso práctico.csv")

#View(db)

dim(db)
[1] 5000  124

Son 5000 filas y 124 columnas

summary(db)
    custid              region         townsize         gender            age            agecat       birthmonth       
 Length:5000        Min.   :1.000   Min.   :1.000   Min.   :0.0000   Min.   :18.00   Min.   :2.000   Length:5000       
 Class :character   1st Qu.:2.000   1st Qu.:1.000   1st Qu.:0.0000   1st Qu.:31.00   1st Qu.:3.000   Class :character  
 Mode  :character   Median :3.000   Median :3.000   Median :1.0000   Median :47.00   Median :4.000   Mode  :character  
                    Mean   :3.001   Mean   :2.687   Mean   :0.5036   Mean   :47.03   Mean   :4.239                     
                    3rd Qu.:4.000   3rd Qu.:4.000   3rd Qu.:1.0000   3rd Qu.:62.00   3rd Qu.:5.000                     
                    Max.   :5.000   Max.   :5.000   Max.   :1.0000   Max.   :79.00   Max.   :6.000                     
                                    NA's   :2                                                                          
       ed            edcat           jobcat          union            employ          empcat          retire      
 Min.   : 6.00   Min.   :1.000   Min.   :1.000   Min.   :0.0000   Min.   : 0.00   Min.   :1.000   Min.   :0.0000  
 1st Qu.:12.00   1st Qu.:2.000   1st Qu.:1.000   1st Qu.:0.0000   1st Qu.: 2.00   1st Qu.:2.000   1st Qu.:0.0000  
 Median :14.00   Median :2.000   Median :2.000   Median :0.0000   Median : 7.00   Median :3.000   Median :0.0000  
 Mean   :14.54   Mean   :2.672   Mean   :2.753   Mean   :0.1512   Mean   : 9.73   Mean   :2.933   Mean   :0.1476  
 3rd Qu.:17.00   3rd Qu.:4.000   3rd Qu.:4.000   3rd Qu.:0.0000   3rd Qu.:15.00   3rd Qu.:4.000   3rd Qu.:0.0000  
 Max.   :23.00   Max.   :5.000   Max.   :6.000   Max.   :1.0000   Max.   :52.00   Max.   :5.000   Max.   :1.0000  
                                                                                                                  
     income            inccat         debtinc          creddebt           othdebt            default           jobsat     
 Min.   :   9.00   Min.   :1.000   Min.   : 0.000   Min.   :  0.0000   Min.   :  0.0000   Min.   :0.0000   Min.   :1.000  
 1st Qu.:  24.00   1st Qu.:1.000   1st Qu.: 5.100   1st Qu.:  0.3855   1st Qu.:  0.9803   1st Qu.:0.0000   1st Qu.:2.000  
 Median :  38.00   Median :2.000   Median : 8.800   Median :  0.9264   Median :  2.0985   Median :0.0000   Median :3.000  
 Mean   :  54.76   Mean   :2.392   Mean   : 9.954   Mean   :  1.8573   Mean   :  3.6545   Mean   :0.2342   Mean   :2.964  
 3rd Qu.:  67.00   3rd Qu.:3.000   3rd Qu.:13.600   3rd Qu.:  2.0638   3rd Qu.:  4.3148   3rd Qu.:0.0000   3rd Qu.:4.000  
 Max.   :1073.00   Max.   :5.000   Max.   :43.100   Max.   :109.0726   Max.   :141.4591   Max.   :1.0000   Max.   :5.000  
                                                                                                                          
    marital          spoused         spousedcat          reside           pets          pets_cats        pets_dogs     
 Min.   :0.0000   Min.   :-1.000   Min.   :-1.0000   Min.   :1.000   Min.   : 0.000   Min.   :0.0000   Min.   :0.0000  
 1st Qu.:0.0000   1st Qu.:-1.000   1st Qu.:-1.0000   1st Qu.:1.000   1st Qu.: 0.000   1st Qu.:0.0000   1st Qu.:0.0000  
 Median :0.0000   Median :-1.000   Median :-1.0000   Median :2.000   Median : 2.000   Median :0.0000   Median :0.0000  
 Mean   :0.4802   Mean   : 6.113   Mean   : 0.6414   Mean   :2.204   Mean   : 3.067   Mean   :0.5004   Mean   :0.3924  
 3rd Qu.:1.0000   3rd Qu.:14.000   3rd Qu.: 2.0000   3rd Qu.:3.000   3rd Qu.: 5.000   3rd Qu.:1.0000   3rd Qu.:0.0000  
 Max.   :1.0000   Max.   :24.000   Max.   : 5.0000   Max.   :9.000   Max.   :21.000   Max.   :6.0000   Max.   :7.0000  
                                                                                                                       
   pets_birds     pets_reptiles      pets_small     pets_saltfish    pets_freshfish      homeown          hometype    
 Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   : 0.000   Min.   :0.0000   Min.   :1.000  
 1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.: 0.000   1st Qu.:0.0000   1st Qu.:1.000  
 Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000   Median : 0.000   Median :1.0000   Median :2.000  
 Mean   :0.1104   Mean   :0.0556   Mean   :0.1146   Mean   :0.0466   Mean   : 1.847   Mean   :0.6296   Mean   :1.843  
 3rd Qu.:0.0000   3rd Qu.:0.0000   3rd Qu.:0.0000   3rd Qu.:0.0000   3rd Qu.: 4.000   3rd Qu.:1.0000   3rd Qu.:2.000  
 Max.   :5.0000   Max.   :6.0000   Max.   :7.0000   Max.   :8.0000   Max.   :16.000   Max.   :1.0000   Max.   :4.000  
                                                                                                                      
    address       addresscat         cars           carown           cartype           carvalue      carcatvalue    
 Min.   : 0.0   Min.   :1.000   Min.   :0.000   Min.   :-1.0000   Min.   :-1.0000   Min.   :-1.00   Min.   :-1.000  
 1st Qu.: 6.0   1st Qu.:2.000   1st Qu.:1.000   1st Qu.: 0.0000   1st Qu.: 0.0000   1st Qu.: 9.20   1st Qu.: 1.000  
 Median :14.0   Median :3.000   Median :2.000   Median : 1.0000   Median : 0.0000   Median :17.00   Median : 1.000  
 Mean   :16.4   Mean   :3.272   Mean   :2.131   Mean   : 0.6414   Mean   : 0.3438   Mean   :23.23   Mean   : 1.389  
 3rd Qu.:25.0   3rd Qu.:4.000   3rd Qu.:3.000   3rd Qu.: 1.0000   3rd Qu.: 1.0000   3rd Qu.:31.10   3rd Qu.: 2.000  
 Max.   :57.0   Max.   :5.000   Max.   :8.000   Max.   : 1.0000   Max.   : 1.0000   Max.   :99.60   Max.   : 3.000  
                                                                                                                    
   carbought          carbuy         commute         commutecat     commutetime      commutecar    commutemotorcycle
 Min.   :-1.000   Min.   :0.000   Min.   : 1.000   Min.   :1.000   Min.   : 8.00   Min.   :0.000   Min.   :0.0000   
 1st Qu.: 0.000   1st Qu.:0.000   1st Qu.: 1.000   1st Qu.:1.000   1st Qu.:21.00   1st Qu.:0.000   1st Qu.:0.0000   
 Median : 0.000   Median :0.000   Median : 1.000   Median :1.000   Median :25.00   Median :1.000   Median :0.0000   
 Mean   : 0.221   Mean   :0.361   Mean   : 2.996   Mean   :1.973   Mean   :25.35   Mean   :0.679   Mean   :0.1026   
 3rd Qu.: 1.000   3rd Qu.:1.000   3rd Qu.: 4.000   3rd Qu.:3.000   3rd Qu.:29.00   3rd Qu.:1.000   3rd Qu.:0.0000   
 Max.   : 1.000   Max.   :1.000   Max.   :10.000   Max.   :5.000   Max.   :48.00   Max.   :1.000   Max.   :1.0000   
                                                                   NA's   :2                                        
 commutecarpool     commutebus     commuterail     commutepublic     commutebike      commutewalk     commutenonmotor 
 Min.   :0.0000   Min.   :0.000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
 1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000  
 Median :0.0000   Median :0.000   Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000  
 Mean   :0.2718   Mean   :0.406   Mean   :0.2746   Mean   :0.0954   Mean   :0.1234   Mean   :0.3838   Mean   :0.0584  
 3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:1.0000   3rd Qu.:0.0000   3rd Qu.:0.0000   3rd Qu.:1.0000   3rd Qu.:0.0000  
 Max.   :1.0000   Max.   :1.000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
                                                                                                                      
  telecommute        reason         polview         polparty        polcontrib          vote            card      
 Min.   :0.000   Min.   :1.000   Min.   :1.000   Min.   :0.0000   Min.   :0.0000   Min.   :0.000   Min.   :1.000  
 1st Qu.:0.000   1st Qu.:9.000   1st Qu.:3.000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:2.000  
 Median :0.000   Median :9.000   Median :4.000   Median :0.0000   Median :0.0000   Median :1.000   Median :3.000  
 Mean   :0.188   Mean   :7.637   Mean   :4.089   Mean   :0.3814   Mean   :0.2384   Mean   :0.518   Mean   :2.714  
 3rd Qu.:0.000   3rd Qu.:9.000   3rd Qu.:5.000   3rd Qu.:1.0000   3rd Qu.:0.0000   3rd Qu.:1.000   3rd Qu.:4.000  
 Max.   :1.000   Max.   :9.000   Max.   :7.000   Max.   :1.0000   Max.   :1.0000   Max.   :1.000   Max.   :5.000  
                                                                                                                  
    cardtype      cardbenefit       cardfee         cardtenure    cardtenurecat       card2         card2type    
 Min.   :1.000   Min.   :1.000   Min.   :0.0000   Min.   : 0.00   Min.   :1.000   Min.   :1.000   Min.   :1.000  
 1st Qu.:2.000   1st Qu.:2.000   1st Qu.:0.0000   1st Qu.: 6.00   1st Qu.:3.000   1st Qu.:2.000   1st Qu.:2.000  
 Median :3.000   Median :3.000   Median :0.0000   Median :14.00   Median :4.000   Median :3.000   Median :3.000  
 Mean   :2.507   Mean   :2.506   Mean   :0.1898   Mean   :16.66   Mean   :3.782   Mean   :2.774   Mean   :2.541  
 3rd Qu.:4.000   3rd Qu.:3.250   3rd Qu.:0.0000   3rd Qu.:26.00   3rd Qu.:5.000   3rd Qu.:4.000   3rd Qu.:4.000  
 Max.   :4.000   Max.   :4.000   Max.   :1.0000   Max.   :40.00   Max.   :5.000   Max.   :5.000   Max.   :4.000  
                                                                                                                 
  card2benefit      card2fee       card2tenure    card2tenurecat    carditems       cardspent        card2items    
 Min.   :1.000   Min.   :0.0000   Min.   : 0.00   Min.   :1.000   Min.   : 0.00   Min.   :   0.0   Min.   : 0.000  
 1st Qu.:2.000   1st Qu.:0.0000   1st Qu.: 5.00   1st Qu.:2.000   1st Qu.: 8.00   1st Qu.: 183.4   1st Qu.: 3.000  
 Median :3.000   Median :0.0000   Median :12.00   Median :4.000   Median :10.00   Median : 276.4   Median : 5.000  
 Mean   :2.534   Mean   :0.1872   Mean   :13.08   Mean   :3.571   Mean   :10.18   Mean   : 337.2   Mean   : 4.667  
 3rd Qu.:4.000   3rd Qu.:0.0000   3rd Qu.:21.00   3rd Qu.:5.000   3rd Qu.:12.00   3rd Qu.: 418.5   3rd Qu.: 6.000  
 Max.   :4.000   Max.   :1.0000   Max.   :30.00   Max.   :5.000   Max.   :23.00   Max.   :3926.4   Max.   :15.000  
                                                                                                                   
   card2spent          active          bfast           tenure         churn           longmon          longten       
 Min.   :   0.00   Min.   :0.000   Min.   :1.000   Min.   : 0.0   Min.   :0.0000   Min.   :  0.90   Min.   :    0.9  
 1st Qu.:  66.97   1st Qu.:0.000   1st Qu.:1.000   1st Qu.:18.0   1st Qu.:0.0000   1st Qu.:  5.70   1st Qu.:  104.6  
 Median : 125.34   Median :0.000   Median :2.000   Median :38.0   Median :0.0000   Median :  9.55   Median :  350.0  
 Mean   : 160.88   Mean   :0.466   Mean   :2.059   Mean   :38.2   Mean   :0.2532   Mean   : 13.47   Mean   :  708.9  
 3rd Qu.: 208.31   3rd Qu.:1.000   3rd Qu.:3.000   3rd Qu.:59.0   3rd Qu.:1.0000   3rd Qu.: 16.55   3rd Qu.:  913.9  
 Max.   :2069.25   Max.   :1.000   Max.   :3.000   Max.   :72.0   Max.   :1.0000   Max.   :179.85   Max.   :13046.5  
                                                                                                    NA's   :3        
    tollfree         tollmon         lntollmon        tollten           equip           equipmon         equipten     
 Min.   :0.0000   Min.   :  0.00   Min.   :2.079   Min.   :   0.0   Min.   :0.0000   Min.   :  0.00   Min.   :   0.0  
 1st Qu.:0.0000   1st Qu.:  0.00   1st Qu.:2.970   1st Qu.:   0.0   1st Qu.:0.0000   1st Qu.:  0.00   1st Qu.:   0.0  
 Median :0.0000   Median :  0.00   Median :3.229   Median :   0.0   Median :0.0000   Median :  0.00   Median :   0.0  
 Mean   :0.4756   Mean   : 13.26   Mean   :3.243   Mean   : 577.8   Mean   :0.3408   Mean   : 12.99   Mean   : 470.2  
 3rd Qu.:1.0000   3rd Qu.: 24.50   3rd Qu.:3.519   3rd Qu.: 885.5   3rd Qu.:1.0000   3rd Qu.: 30.80   3rd Qu.: 510.2  
 Max.   :1.0000   Max.   :173.00   Max.   :4.622   Max.   :6923.4   Max.   :1.0000   Max.   :106.30   Max.   :6525.3  
                                   NA's   :2622                                                                       
   lnequipten       callcard         cardmon          cardten          lncardten        wireless         wiremon      
 Min.   :2.489   Min.   :0.0000   Min.   :  0.00   Min.   :    0.0   Min.   :1.558   Min.   :0.0000   Min.   :  0.00  
 1st Qu.:6.172   1st Qu.:0.0000   1st Qu.:  0.00   1st Qu.:    0.0   1st Qu.:5.858   1st Qu.:0.0000   1st Qu.:  0.00  
 Median :7.051   Median :1.0000   Median : 13.75   Median :  425.0   Median :6.640   Median :0.0000   Median :  0.00  
 Mean   :6.747   Mean   :0.7162   Mean   : 15.44   Mean   :  720.5   Mean   :6.426   Mean   :0.2688   Mean   : 10.70  
 3rd Qu.:7.650   3rd Qu.:1.0000   3rd Qu.: 22.75   3rd Qu.: 1080.0   3rd Qu.:7.219   3rd Qu.:1.0000   3rd Qu.: 20.96  
 Max.   :8.783   Max.   :1.0000   Max.   :188.50   Max.   :13705.0   Max.   :9.525   Max.   :1.0000   Max.   :186.25  
 NA's   :3296                                      NA's   :2         NA's   :1422                                     
   lnwiremon        wireten           lnwireten        multline          voice           pager           internet  
 Min.   :2.542   Min.   :    0.00   Min.   :2.542   Min.   :0.0000   Min.   :0.000   Min.   :0.0000   Min.   :0.0  
 1st Qu.:3.330   1st Qu.:    0.00   1st Qu.:6.158   1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:0.0  
 Median :3.598   Median :    0.00   Median :7.147   Median :0.0000   Median :0.000   Median :0.0000   Median :1.0  
 Mean   :3.605   Mean   :  421.99   Mean   :6.808   Mean   :0.4884   Mean   :0.303   Mean   :0.2436   Mean   :1.2  
 3rd Qu.:3.865   3rd Qu.:   89.96   3rd Qu.:7.755   3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:0.0000   3rd Qu.:2.0  
 Max.   :5.227   Max.   :12858.65   Max.   :9.462   Max.   :1.0000   Max.   :1.000   Max.   :1.0000   Max.   :4.0  
 NA's   :3656                       NA's   :3656                                                                   
     callid          callwait        forward           confer          ebill            owntv          hourstv     
 Min.   :0.0000   Min.   :0.000   Min.   :0.0000   Min.   :0.000   Min.   :0.0000   Min.   :0.000   Min.   : 0.00  
 1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:1.000   1st Qu.:17.00  
 Median :0.0000   Median :0.000   Median :0.0000   Median :0.000   Median :0.0000   Median :1.000   Median :20.00  
 Mean   :0.4752   Mean   :0.479   Mean   :0.4806   Mean   :0.478   Mean   :0.3486   Mean   :0.983   Mean   :19.64  
 3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:1.0000   3rd Qu.:1.000   3rd Qu.:23.00  
 Max.   :1.0000   Max.   :1.000   Max.   :1.0000   Max.   :1.000   Max.   :1.0000   Max.   :1.000   Max.   :36.00  
                                                                                                                   
     ownvcr           owndvd           owncd            ownpda          ownpc           ownipod          owngame      
 Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
 1st Qu.:1.0000   1st Qu.:1.0000   1st Qu.:1.0000   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000  
 Median :1.0000   Median :1.0000   Median :1.0000   Median :0.000   Median :1.0000   Median :0.0000   Median :0.0000  
 Mean   :0.9156   Mean   :0.9136   Mean   :0.9328   Mean   :0.201   Mean   :0.6328   Mean   :0.4792   Mean   :0.4748  
 3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:0.000   3rd Qu.:1.0000   3rd Qu.:1.0000   3rd Qu.:1.0000  
 Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
                                                                                                                      
     ownfax            news         response_01      response_02      response_03    
 Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000   Min.   :0.0000  
 1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:0.0000  
 Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000   Median :0.0000  
 Mean   :0.1788   Mean   :0.4726   Mean   :0.0836   Mean   :0.1298   Mean   :0.1026  
 3rd Qu.:0.0000   3rd Qu.:1.0000   3rd Qu.:0.0000   3rd Qu.:0.0000   3rd Qu.:0.0000  
 Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000   Max.   :1.0000  
                                                                                     

Busqueda de duplicados

Se ve, por si acaso, si es que hay duplicados en el id de cliente

n_occur<-data.frame(table(db$custid))
n_occur[n_occur$Freq>1,]

No hay customers duplicados

Cambio de variables categóricas a factor

Se cambian todas las variables categóricas a factores:

db$region<-as.factor(db$region)
db$townsize<-as.factor(db$townsize)
db$gender<-as.factor(db$gender)
db$agecat<-as.factor(db$agecat)
db$edcat<-as.factor(db$edcat)
db$jobcat<-as.factor(db$jobcat)
db$union<-as.factor(db$union)
db$empcat<-as.factor(db$empcat)
db$retire<-as.factor(db$retire)
db$inccat<-as.factor(db$inccat)
db$default<-as.factor(db$default)
db$jobsat<-as.factor(db$jobsat)
db$marital<-as.factor(db$marital)
db$spousedcat<-as.factor(db$spousedcat)
db$homeown<-as.factor(db$homeown)
db$hometype<-as.factor(db$hometype)
db$addresscat<-as.factor(db$addresscat)
db$carown<-as.factor(db$carown)
db$cartype<-as.factor(db$cartype)
db$carcatvalue<-as.factor(db$carcatvalue)
db$carbought<-as.factor(db$carbought)
db$carbuy<-as.factor(db$carbuy)
db$carcatvalue<-as.factor(db$carcatvalue)
db$commute<-as.factor(db$commute)
db$commutecat<-as.factor(db$commutecat)
db$commutecar<-as.factor(db$commutecar)
db$commuterail<-as.factor(db$commuterail)
db$commutebus<-as.factor(db$commutebus)
db$commutemotorcycle<-as.factor(db$commutemotorcycle)
db$commutepublic<-as.factor(db$commutepublic)
db$commutebike<-as.factor(db$commutebike)
db$commutewalk<-as.factor(db$commutewalk)
db$commutenonmotor<-as.factor(db$commutenonmotor)
db$telecommute<-as.factor(db$telecommute)
db$reason<-as.factor(db$reason)
db$birthmonth<-as.factor(db$birthmonth)
db$polview<-as.factor(db$polview)
db$ebill<-as.factor(db$ebill)
db$polparty<-as.factor(db$polparty)
db$vote<-as.factor(db$vote)
db$card<-as.factor(db$card)
db$cardtype<-as.factor(db$cardtype)
db$cardbenefit<-as.factor(db$cardbenefit)
db$card2<-as.factor(db$card2)
db$card2type<-as.factor(db$card2type)
db$card2benefit<-as.factor(db$card2benefit)
db$active<-as.factor(db$active)
db$bfast<-as.factor(db$bfast)
db$churn<-as.factor(db$churn)
db$tollfree<-as.factor(db$tollfree)
db$equip<-as.factor(db$equip)
db$callcard<-as.factor(db$callcard)
db$wireless<-as.factor(db$wireless)
db$wiremon<-as.factor(db$wiremon)
db$multline<-as.factor(db$multline)
db$voice<-as.factor(db$voice)
db$pager<-as.factor(db$pager)
db$internet<-as.factor(db$internet)
db$callid<-as.factor(db$callid)
db$forward<-as.factor(db$forward)
db$confer<-as.factor(db$confer)
db$owntv<-as.factor(db$owntv)
db$ownvcr<-as.factor(db$ownvcr)
db$owndvd<-as.factor(db$owndvd)
db$owncd<-as.factor(db$owncd)
db$ownpda<-as.factor(db$ownpda)
db$ownpc<-as.factor(db$ownpc)
db$ownipod<-as.factor(db$ownipod)
db$owngame<-as.factor(db$owngame)
db$ownfax<-as.factor(db$ownfax)
db$news<-as.factor(db$news)
db$card2fee<-as.factor(db$card2fee)
db$response_01<-as.factor(db$response_01)
db$response_02<-as.factor(db$response_02)
db$response_03<-as.factor(db$response_03)
db$polcontrib<-as.factor(db$polcontrib)
db$cardfee<-as.factor(db$cardfee)
db$commutecarpool<-as.factor(db$commutecarpool)
db$callwait<-as.factor(db$callwait)
db$ebill<-as.factor(db$ebill)

Visualización de valores nulos

Ahora veamos qué columnas tienen una alta cantidad de valores nulos

plot_missing(db,missing_only = TRUE)

Se pasan a eliminar las columans con datos faltantes mayores al 20% (5 columnas)

db<-db[, colMeans(is.na(db)) <= .2]
dim(db)
[1] 5000  119

A continuación podemos ver las columnas que quedan con datos faltantes

plot_missing(db,missing_only = TRUE)

Ahora, se pasará a imputar estas columnas

db<-kNN(db)
db<-db%>%select(-ends_with("_imp")) #Para eliminar las columnas adicionales que se generan en la imputación

Se crea una columna condicional que indica las personas que tienen un auto de lujo (carcatvalue=3)

db$lujo_si<-ifelse(db$carcatvalue==3,1,0)

db$lujo_si<-as.factor(db$lujo_si)

Finalmente, guardamos una copia de seguridad de los datos tratados

write.csv(db,"db_clean.csv")

5. Creación del modelo

Separemos primero las columnas numéricas de las categóricas

db_num<-db %>% dplyr::select(where(is.numeric))
db_cat<-db %>% dplyr::select(where(is.factor))

Datos Numéricos


par(mfrow=c(2,2))

for (i in 1:ncol(db_num)){
  hist(db_num[[i]], main=paste("Plot ", colnames(db_num[i])), xlab = paste("Values Plot",i)) 
  box(lty = "solid")
}

NA
NA

Veamos la comparación de los boxplots por categoría de auto


ggplot(db,aes(x=carcatvalue,y=carvalue,color=carcatvalue))+

Podemos ver que los datos para la categoría de lujo están bastante más dispersos que en las otras categorías. Además, su mediana tiende a la baja.

Veamos también más detenidamente la cantidad de personas por valor del auto

std_values<-ddply(db,"carcatvalue",summarise,Min=min(carvalue),Max=max(carvalue),Mean=mean(carvalue),sd=sd(carvalue))


ggplot(db,aes(x=carvalue,color=carcatvalue))+geom_histogram(fill="white",alpha=0.5,position = "identity")+
  geom_vline(data = std_values,aes(xintercept=Mean,color=carcatvalue),linetype="dashed")+
  theme(axis.text.x = element_text(angle = 90,size = 10))

Podemos ver que a medida que crece el valor del auto, decrece la cantidad de personas que lo tienen.

Datos generales

Comparemos a las personas que tienen autos de lujo vs las que no, de acuerdo a las medias de sus valores numéricos

Son personas de una edad mayor a las personas que no tienen autos de lujo. Además, su educación es un poco mayor en promedio, pero no tanto como para decir que es un rasgo preponderante.

Con el género y estado civil sucede algo similar. Se puede ver que la mayoría son mujeres y que el mayor estado civil es soltero; no obstante, la diferencia es muy pequeña:

jcat<-db%>%group_by(lujo_si,jobcat)%>%summarise(count=n())
`summarise()` has grouped output by 'lujo_si'. You can override using the `.groups` argument.
cast(jcat,jobcat~lujo_si,value = "count")

Datos de empleo e ingresos

db%>%group_by(lujo_si)%>%summarise(mean(income),mean(employ),mean(creddebt),mean(cardspent))

Otro rasgo característico de estas personas es que tienen unos sueldos muy altos (más de 136 000 al año) y están en el mismo trabajo desde hace 16 años (employ). El débito en sus tarjetas de crédito también es mayor.

Veamos también lo correspondiente a las tarjetas

card_tb<-db%>%group_by(lujo_si,cardtype)%>%summarise(count=n())
`summarise()` has grouped output by 'lujo_si'. You can override using the `.groups` argument.
cast(card_tb,cardtype~lujo_si,value = "count")

Respecto a si realizan facturaciones electrónicas

elect<-db%>%group_by(lujo_si,ebill)%>%summarise(count=n())
`summarise()` has grouped output by 'lujo_si'. You can override using the `.groups` argument.
cast(elect,ebill~lujo_si,value = "count")

Datos de publicidad

db%>%group_by(lujo_si)%>%summarise(mean(hourstv))
nw<-db%>%group_by(lujo_si,news)%>%summarise(count=n())
`summarise()` has grouped output by 'lujo_si'. You can override using the `.groups` argument.
cast(nw,news~lujo_si,value = "count")

5. Planteamiento del modelo

Se plantea realizar un modelo de regresión logistica para predecir en base a las variables seleccionadas la posibilidad de que una persona posea un auto de lujo. Esto permitirá comprobar que las variables seleccionadas son las más adecuadas para el caso planteado

Ahora se pasará a tomar una muestra aleatoria del total

#Se dividen los datos para entrenamiento (75% de train y 25% de test)

set.seed(88)
split=sample.split(db$lujo_si,SplitRatio = 0.75)


#Crear el training y testing data sets

dt=subset(db,split==TRUE)  #Train
de=subset(db,split==FALSE) #Test

Modelo de regresión

RL_Eur<-glm(lujo_si~income+tollfree+cardtype+forward+ebill+cardspent+spoused+forward+jobcat+pets_reptiles,data=dt,family = binomial())
glm.fit: fitted probabilities numerically 0 or 1 occurred
summary(RL_Eur)

Call:
glm(formula = lujo_si ~ income + tollfree + cardtype + forward + 
    ebill + cardspent + spoused + forward + jobcat + pets_reptiles, 
    family = binomial(), data = dt)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-5.7045  -0.2479  -0.1289  -0.0767   2.3865  

Coefficients:
                Estimate Std. Error z value Pr(>|z|)    
(Intercept)   -6.5825378  0.3171776 -20.753  < 2e-16 ***
income         0.0724357  0.0030602  23.670  < 2e-16 ***
tollfree1     -0.6437073  0.1912504  -3.366 0.000763 ***
cardtype2     -0.4858296  0.2064148  -2.354 0.018590 *  
cardtype3     -0.1285183  0.1970437  -0.652 0.514251    
cardtype4     -0.5206139  0.2084453  -2.498 0.012504 *  
forward1       0.4726924  0.1908615   2.477 0.013263 *  
ebill1        -0.4204455  0.1577652  -2.665 0.007699 ** 
cardspent      0.0005434  0.0002685   2.024 0.042966 *  
spoused        0.0173578  0.0091474   1.898 0.057755 .  
jobcat2       -0.0814042  0.2051047  -0.397 0.691448    
jobcat3        0.1716952  0.2328781   0.737 0.460955    
jobcat4        0.0304426  0.3767898   0.081 0.935605    
jobcat5        0.1700695  0.2705825   0.629 0.529656    
jobcat6        0.4527598  0.2212254   2.047 0.040697 *  
pets_reptiles -0.4833516  0.2793629  -1.730 0.083596 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 3388.8  on 3749  degrees of freedom
Residual deviance: 1298.9  on 3734  degrees of freedom
AIC: 1330.9

Number of Fisher Scoring iterations: 7
predictions<-predict(RL_Eur,de)

6. Comprobación de resultados

sigmoide=function(x){1/(1+exp(-x))}

plot(predictions,sigmoide(predictions),col="blue")

mod_pred<-ifelse(predictions>0.5,1,0)
mod_pred<-factor(mod_pred)

head(mod_pred)
 5  6  9 12 18 24 
 0  1  0  0  1  0 
Levels: 0 1
de$lujo_si<-factor(de$lujo_si)

head(de$lujo_si)
[1] 0 0 0 0 1 0
Levels: 0 1
confusionMatrix(mod_pred,de$lujo_si)
Confusion Matrix and Statistics

          Reference
Prediction    0    1
         0 1023   64
         1   18  145
                                          
               Accuracy : 0.9344          
                 95% CI : (0.9192, 0.9475)
    No Information Rate : 0.8328          
    P-Value [Acc > NIR] : < 2.2e-16       
                                          
                  Kappa : 0.7417          
                                          
 Mcnemar's Test P-Value : 6.715e-07       
                                          
            Sensitivity : 0.9827          
            Specificity : 0.6938          
         Pos Pred Value : 0.9411          
         Neg Pred Value : 0.8896          
             Prevalence : 0.8328          
         Detection Rate : 0.8184          
   Detection Prevalence : 0.8696          
      Balanced Accuracy : 0.8382          
                                          
       'Positive' Class : 0               
                                          

7. Comparación de precios de autos con el dataset

Se hizo un scrape de precios de algunas marcas de lujo

car_prices<-readxl::read_excel("Scrapes.xlsx")
head(car_prices)
dim(car_prices)
[1] 46  3

ggplot(car_prices,aes(x=Marca,y=Price,color=Marca))+
  geom_boxplot(outlier.colour = "black",notch = FALSE)+
  scale_fill_viridis(discrete = TRUE, alpha=0.6) +
  geom_jitter(color="gray", size=0.4, alpha=0.15)

db%>% filter(lujo_si==1)%>%summarise(mean(carvalue),median(carvalue),min(carvalue),max(carvalue))
NA
NA
LS0tDQp0aXRsZTogIkNhc28gRXVyb21vdG9ycyINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCg0KbGlicmFyeShEYXRhRXhwbG9yZXIpICNwYXJhIGRhdG9zIGZhbHRhbnRlcw0KbGlicmFyeShWSU0pICNwYXJhIGltcHV0YWNpw7NuIGRlIGRhdG9zIGZhbHRhbnRlcw0KbGlicmFyeShkcGx5cikgI1BhcmEgbGEgbWFuaXB1bGFjacOzbiBkZSBiYXNlcyBkZSBkYXRvcw0KbGlicmFyeShjYVRvb2xzKSAjUGFyYSBwcmVkaWNjacOzbiBkZSBkYXRvcw0KbGlicmFyeShWSU0pICNwYXJhIGltcHV0YWNpw7NuIGRlIGRhdG9zIGZhbHRhbnRlcw0KbGlicmFyeShyYW5kb21Gb3Jlc3QpDQpsaWJyYXJ5KHRpYmJsZSkNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeSh2aXJpZGlzKQ0KbGlicmFyeShwbHlyKQ0KbGlicmFyeShoZWF0bWFwbHkpDQpsaWJyYXJ5KGNhcmV0KQ0KbGlicmFyeShyZXNoYXBlKQ0KDQpgYGANCg0KIyAxLiBQbGFudGVhbWllbnRvIGRlbCBwcm9ibGVtYQ0KDQpFbiBlc3RlIG5vdGVib29rIGxlcyBtb3N0cmFyw6kgcGFzbyBhIHBhc28gZWwgYW7DoWxpc2lzIGRlbCBwcm9ibGVtYSBwcm9wdWVzdG8uIEVsIG9iamV0aXZvIGRlIGVzdGUgZWplcmNpY2lvIGVzIGxhIHJlc29sdWNpw7NuIGRlIGxhcyBzaWd1aWVudGVzIGluY8OzZ25pdGFzOg0KDQoqKjEuIMK/Q8OzbW8gc29uIGxvcyBjbGllbnRlcyBkZSBsdWpvIHBhcmEgZW5mb2NhciBsYXMgZXN0cmF0ZWdpYXMgZGUgbWFya2V0aW5nPyoqDQoNCiAgICAtIFNlbGVjY2lvbmFyIGxhcyAxMCB2YXJpYWJsZXMgbcOhcyBpbXBvcnRhbnRlcyBkZWwgZGF0YXNldA0KICAgIA0KICAgIC0gwr9Tb24gbG9zIHByZWNpb3Mgc2ltaWxhcmVzIGEgbG9zIGRlIGxhIHJlYWxpZGFkPw0KICAgIA0KKioyLiDCv0PDs21vIGhhY2VyIGxhIGNhbXBhw7FhIGRlIG1hcmtldGluZyBtw6FzIGVmZWN0aXZhPyoqDQoNCiAgICAtIFNlbGVjY2lvbmFyIGxhcyB2YXJpYWJsZXMgbcOhcyByZWxldmFudGVzDQogICAgDQogICAgLSDCv0RlIHF1w6kgbWFuZXJhIGNvbmZpcm1hcsOtYSBxdWUgbGEgcHJvcHVlc3RhIGVzIGxhIGFkZWN1YWRhPw0KDQpccGFnZWJyZWFrDQoNCiMgMi4gSW5mb3JtYWNpw7NuIGdlbmVyYWwNCg0KTG9zIHBhc29zIGEgc2VndWlyIHNvbiBsb3Mgc2lndWllbnRlczoNCg0KKipBKSBMaW1waWV6YSBkZSBsYSBkYXRhKioNCg0KKipCKSBFeHBsb3JhY2nDs24gZGUgbG9zIGRhdG9zKioNCg0KKipDKSBDb25zdHJ1Y2Npw7NuIGRlbCBtb2RlbG8qKg0KDQoqKkQpIFJldmlzacOzbiBkZSBsb3MgcmVzdWx0YWRvcyoqDQogIA0KXHBhZ2VicmVhaw0KDQoNCiMgMy4gUGxhbmVhbWllbnRvIGRlbCBwcm95ZWN0bw0KDQpDdWFuZG8gZXN0b3kgcG9yIGVtcGV6YXIgdW4gcHJveWVjdG8sIG1lIGd1c3RhIHBvbmVyIGVsIHBsYW4gcXVlIGxsZXZhcsOpIGEgY2Fiby4NCg0KKkVudGVuZGVyIGxhIG5hdHVyYWxlemEgZGUgbGEgZGF0YSAoc3VtbWFyeSgpLCBzdHIoKSkqDQoNCipIaXN0b2dyYW1hcyB5IGJveHBsb3RzKg0KDQoqQ29udGVvIGRlIHZhbG9yZXMqDQoNCipNYW5pcHVsYWNpw7NuIGRlIHZhbG9yZXMgbnVsb3MqDQoNCipDb3JyZWxhY2nDs24gZW50cmUgbcOpdHJpY2FzKg0KDQoqRXhwbG9yYWNpw7NuIGRlIHRlbWFzIGludGVyZXNhbnRlcyoNCg0KICAtIMK/QSBtYXlvcmVzIGluZ3Jlc29zIHRpZW5lbiBtw6FzIHBvc2liaWxpZGFkZXMgZGUgdGVuZXIgdW4gYXV0byBkZSBsdWpvPw0KICAgIA0KICAgIC0gU2Vyw61hIGludGVyZXNhbnRlIGxhIHJldmlzacOzbiBkZSBsYXMgdGFyamV0YXMgZGUgY3LDqWRpdG8geSBkZXVkYXMNCiAgDQogIC0gwr9FbCB0aXBvIGRlIHRyYWJham8gZXN0w6EgcmVsYWNpb25hZG8gY29uIHRlbmVyIHVuIGF1dG8gZGUgbHVqbz8NCiAgDQogIC0gwr9Qb3IgcXXDqSB0aXBvIGRlIG1lZGlvIHNlIGluZm9ybWFuIGxhcyBwZXJzb25hcyBjb24gYXV0b3MgZGUgbHVqbz8NCiAgICANCiAgICAtIEhheSBkYXRvcyBzb2JyZSBwZXJpw7NkaWNvcywgaW50ZXJuZXQgeSBub3RpY2lhcyBlbiBnZW5lcmFsDQogIA0KICAtIMK/TGEgZWRhZCB5IGVsIHNleG8gZXN0w6FuIHJlbGFjaW9uYWRvcyBjb24gdGVuZXIgdW4gYXV0byBkZSBsdWpvPw0KICANCipGZWF0dXJlIGVuZ2luZWVyaW5nKg0KDQoqQ29uc3RydWNjacOzbiBkZWwgbW9kZWxvKg0KDQoqVGVzdCBkZWwgbW9kZWxvIChtYXRyaXogZGUgY29uZnVzacOzbikqDQoNClxwYWdlYnJlYWsNCg0KDQojIDQuIExpbXBpZXphIGRlIGxhIGRhdGENCg0KIyMgTGVjdHVyYSBpbmNpYWwgZGUgZGF0b3MNCg0KUGFyYSBlbXBlemFyLCBzZSBsZWVuIGxvcyBkYXRvcyBkZWwgY3N2IHkgc2UgdmUgbGFzIGRpbWVuc2lvbmVzDQoNCmBgYHtyfQ0KZGI8LXJlYWQuY3N2KCJCYXNlIGRlIGRhdG9zIGNhc28gcHLDoWN0aWNvLmNzdiIpDQoNCiNWaWV3KGRiKQ0KDQpkaW0oZGIpDQoNCmBgYA0KDQpTb24gNTAwMCBmaWxhcyB5IDEyNCBjb2x1bW5hcw0KDQpgYGB7cn0NCnN1bW1hcnkoZGIpDQpgYGANCg0KDQoNCiMjIEJ1c3F1ZWRhIGRlIGR1cGxpY2Fkb3MNCg0KU2UgdmUsIHBvciBzaSBhY2Fzbywgc2kgZXMgcXVlIGhheSBkdXBsaWNhZG9zIGVuIGVsIGlkIGRlIGNsaWVudGUNCg0KYGBge3J9DQpuX29jY3VyPC1kYXRhLmZyYW1lKHRhYmxlKGRiJGN1c3RpZCkpDQpuX29jY3VyW25fb2NjdXIkRnJlcT4xLF0NCmBgYA0KDQoNCk5vIGhheSBjdXN0b21lcnMgZHVwbGljYWRvcw0KDQoNCiMjIENhbWJpbyBkZSB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzIGEgZmFjdG9yDQoNClNlIGNhbWJpYW4gdG9kYXMgbGFzIHZhcmlhYmxlcyBjYXRlZ8OzcmljYXMgYSBmYWN0b3JlczoNCg0KYGBge3J9DQpkYiRyZWdpb248LWFzLmZhY3RvcihkYiRyZWdpb24pDQpkYiR0b3duc2l6ZTwtYXMuZmFjdG9yKGRiJHRvd25zaXplKQ0KZGIkZ2VuZGVyPC1hcy5mYWN0b3IoZGIkZ2VuZGVyKQ0KZGIkYWdlY2F0PC1hcy5mYWN0b3IoZGIkYWdlY2F0KQ0KZGIkZWRjYXQ8LWFzLmZhY3RvcihkYiRlZGNhdCkNCmRiJGpvYmNhdDwtYXMuZmFjdG9yKGRiJGpvYmNhdCkNCmRiJHVuaW9uPC1hcy5mYWN0b3IoZGIkdW5pb24pDQpkYiRlbXBjYXQ8LWFzLmZhY3RvcihkYiRlbXBjYXQpDQpkYiRyZXRpcmU8LWFzLmZhY3RvcihkYiRyZXRpcmUpDQpkYiRpbmNjYXQ8LWFzLmZhY3RvcihkYiRpbmNjYXQpDQpkYiRkZWZhdWx0PC1hcy5mYWN0b3IoZGIkZGVmYXVsdCkNCmRiJGpvYnNhdDwtYXMuZmFjdG9yKGRiJGpvYnNhdCkNCmRiJG1hcml0YWw8LWFzLmZhY3RvcihkYiRtYXJpdGFsKQ0KZGIkc3BvdXNlZGNhdDwtYXMuZmFjdG9yKGRiJHNwb3VzZWRjYXQpDQpkYiRob21lb3duPC1hcy5mYWN0b3IoZGIkaG9tZW93bikNCmRiJGhvbWV0eXBlPC1hcy5mYWN0b3IoZGIkaG9tZXR5cGUpDQpkYiRhZGRyZXNzY2F0PC1hcy5mYWN0b3IoZGIkYWRkcmVzc2NhdCkNCmRiJGNhcm93bjwtYXMuZmFjdG9yKGRiJGNhcm93bikNCmRiJGNhcnR5cGU8LWFzLmZhY3RvcihkYiRjYXJ0eXBlKQ0KZGIkY2FyY2F0dmFsdWU8LWFzLmZhY3RvcihkYiRjYXJjYXR2YWx1ZSkNCmRiJGNhcmJvdWdodDwtYXMuZmFjdG9yKGRiJGNhcmJvdWdodCkNCmRiJGNhcmJ1eTwtYXMuZmFjdG9yKGRiJGNhcmJ1eSkNCmRiJGNhcmNhdHZhbHVlPC1hcy5mYWN0b3IoZGIkY2FyY2F0dmFsdWUpDQpkYiRjb21tdXRlPC1hcy5mYWN0b3IoZGIkY29tbXV0ZSkNCmRiJGNvbW11dGVjYXQ8LWFzLmZhY3RvcihkYiRjb21tdXRlY2F0KQ0KZGIkY29tbXV0ZWNhcjwtYXMuZmFjdG9yKGRiJGNvbW11dGVjYXIpDQpkYiRjb21tdXRlcmFpbDwtYXMuZmFjdG9yKGRiJGNvbW11dGVyYWlsKQ0KZGIkY29tbXV0ZWJ1czwtYXMuZmFjdG9yKGRiJGNvbW11dGVidXMpDQpkYiRjb21tdXRlbW90b3JjeWNsZTwtYXMuZmFjdG9yKGRiJGNvbW11dGVtb3RvcmN5Y2xlKQ0KZGIkY29tbXV0ZXB1YmxpYzwtYXMuZmFjdG9yKGRiJGNvbW11dGVwdWJsaWMpDQpkYiRjb21tdXRlYmlrZTwtYXMuZmFjdG9yKGRiJGNvbW11dGViaWtlKQ0KZGIkY29tbXV0ZXdhbGs8LWFzLmZhY3RvcihkYiRjb21tdXRld2FsaykNCmRiJGNvbW11dGVub25tb3RvcjwtYXMuZmFjdG9yKGRiJGNvbW11dGVub25tb3RvcikNCmRiJHRlbGVjb21tdXRlPC1hcy5mYWN0b3IoZGIkdGVsZWNvbW11dGUpDQpkYiRyZWFzb248LWFzLmZhY3RvcihkYiRyZWFzb24pDQpkYiRiaXJ0aG1vbnRoPC1hcy5mYWN0b3IoZGIkYmlydGhtb250aCkNCmRiJHBvbHZpZXc8LWFzLmZhY3RvcihkYiRwb2x2aWV3KQ0KZGIkZWJpbGw8LWFzLmZhY3RvcihkYiRlYmlsbCkNCmRiJHBvbHBhcnR5PC1hcy5mYWN0b3IoZGIkcG9scGFydHkpDQpkYiR2b3RlPC1hcy5mYWN0b3IoZGIkdm90ZSkNCmRiJGNhcmQ8LWFzLmZhY3RvcihkYiRjYXJkKQ0KZGIkY2FyZHR5cGU8LWFzLmZhY3RvcihkYiRjYXJkdHlwZSkNCmRiJGNhcmRiZW5lZml0PC1hcy5mYWN0b3IoZGIkY2FyZGJlbmVmaXQpDQpkYiRjYXJkMjwtYXMuZmFjdG9yKGRiJGNhcmQyKQ0KZGIkY2FyZDJ0eXBlPC1hcy5mYWN0b3IoZGIkY2FyZDJ0eXBlKQ0KZGIkY2FyZDJiZW5lZml0PC1hcy5mYWN0b3IoZGIkY2FyZDJiZW5lZml0KQ0KZGIkYWN0aXZlPC1hcy5mYWN0b3IoZGIkYWN0aXZlKQ0KZGIkYmZhc3Q8LWFzLmZhY3RvcihkYiRiZmFzdCkNCmRiJGNodXJuPC1hcy5mYWN0b3IoZGIkY2h1cm4pDQpkYiR0b2xsZnJlZTwtYXMuZmFjdG9yKGRiJHRvbGxmcmVlKQ0KZGIkZXF1aXA8LWFzLmZhY3RvcihkYiRlcXVpcCkNCmRiJGNhbGxjYXJkPC1hcy5mYWN0b3IoZGIkY2FsbGNhcmQpDQpkYiR3aXJlbGVzczwtYXMuZmFjdG9yKGRiJHdpcmVsZXNzKQ0KZGIkd2lyZW1vbjwtYXMuZmFjdG9yKGRiJHdpcmVtb24pDQpkYiRtdWx0bGluZTwtYXMuZmFjdG9yKGRiJG11bHRsaW5lKQ0KZGIkdm9pY2U8LWFzLmZhY3RvcihkYiR2b2ljZSkNCmRiJHBhZ2VyPC1hcy5mYWN0b3IoZGIkcGFnZXIpDQpkYiRpbnRlcm5ldDwtYXMuZmFjdG9yKGRiJGludGVybmV0KQ0KZGIkY2FsbGlkPC1hcy5mYWN0b3IoZGIkY2FsbGlkKQ0KZGIkZm9yd2FyZDwtYXMuZmFjdG9yKGRiJGZvcndhcmQpDQpkYiRjb25mZXI8LWFzLmZhY3RvcihkYiRjb25mZXIpDQpkYiRvd250djwtYXMuZmFjdG9yKGRiJG93bnR2KQ0KZGIkb3dudmNyPC1hcy5mYWN0b3IoZGIkb3dudmNyKQ0KZGIkb3duZHZkPC1hcy5mYWN0b3IoZGIkb3duZHZkKQ0KZGIkb3duY2Q8LWFzLmZhY3RvcihkYiRvd25jZCkNCmRiJG93bnBkYTwtYXMuZmFjdG9yKGRiJG93bnBkYSkNCmRiJG93bnBjPC1hcy5mYWN0b3IoZGIkb3ducGMpDQpkYiRvd25pcG9kPC1hcy5mYWN0b3IoZGIkb3duaXBvZCkNCmRiJG93bmdhbWU8LWFzLmZhY3RvcihkYiRvd25nYW1lKQ0KZGIkb3duZmF4PC1hcy5mYWN0b3IoZGIkb3duZmF4KQ0KZGIkbmV3czwtYXMuZmFjdG9yKGRiJG5ld3MpDQpkYiRjYXJkMmZlZTwtYXMuZmFjdG9yKGRiJGNhcmQyZmVlKQ0KZGIkcmVzcG9uc2VfMDE8LWFzLmZhY3RvcihkYiRyZXNwb25zZV8wMSkNCmRiJHJlc3BvbnNlXzAyPC1hcy5mYWN0b3IoZGIkcmVzcG9uc2VfMDIpDQpkYiRyZXNwb25zZV8wMzwtYXMuZmFjdG9yKGRiJHJlc3BvbnNlXzAzKQ0KZGIkcG9sY29udHJpYjwtYXMuZmFjdG9yKGRiJHBvbGNvbnRyaWIpDQpkYiRjYXJkZmVlPC1hcy5mYWN0b3IoZGIkY2FyZGZlZSkNCmRiJGNvbW11dGVjYXJwb29sPC1hcy5mYWN0b3IoZGIkY29tbXV0ZWNhcnBvb2wpDQpkYiRjYWxsd2FpdDwtYXMuZmFjdG9yKGRiJGNhbGx3YWl0KQ0KZGIkZWJpbGw8LWFzLmZhY3RvcihkYiRlYmlsbCkNCmBgYA0KDQoNCiMjIFZpc3VhbGl6YWNpw7NuIGRlIHZhbG9yZXMgbnVsb3MNCg0KQWhvcmEgdmVhbW9zIHF1w6kgY29sdW1uYXMgdGllbmVuIHVuYSBhbHRhIGNhbnRpZGFkIGRlIHZhbG9yZXMgbnVsb3MNCg0KYGBge3J9DQpwbG90X21pc3NpbmcoZGIsbWlzc2luZ19vbmx5ID0gVFJVRSkNCmBgYA0KDQpTZSBwYXNhbiBhIGVsaW1pbmFyIGxhcyBjb2x1bWFucyBjb24gZGF0b3MgZmFsdGFudGVzIG1heW9yZXMgYWwgMjAlICg1IGNvbHVtbmFzKQ0KDQpgYGB7cn0NCmRiPC1kYlssIGNvbE1lYW5zKGlzLm5hKGRiKSkgPD0gLjJdDQpkaW0oZGIpDQpgYGANCg0KQSBjb250aW51YWNpw7NuIHBvZGVtb3MgdmVyIGxhcyBjb2x1bW5hcyBxdWUgcXVlZGFuIGNvbiBkYXRvcyBmYWx0YW50ZXMNCg0KYGBge3J9DQpwbG90X21pc3NpbmcoZGIsbWlzc2luZ19vbmx5ID0gVFJVRSkNCmBgYA0KQWhvcmEsIHNlIHBhc2Fyw6EgYSBpbXB1dGFyIGVzdGFzIGNvbHVtbmFzDQoNCmBgYHtyfQ0KZGI8LWtOTihkYikNCmRiPC1kYiU+JXNlbGVjdCgtZW5kc193aXRoKCJfaW1wIikpICNQYXJhIGVsaW1pbmFyIGxhcyBjb2x1bW5hcyBhZGljaW9uYWxlcyBxdWUgc2UgZ2VuZXJhbiBlbiBsYSBpbXB1dGFjacOzbg0KYGBgDQoNClNlIGNyZWEgdW5hIGNvbHVtbmEgY29uZGljaW9uYWwgcXVlIGluZGljYSBsYXMgcGVyc29uYXMgcXVlIHRpZW5lbiB1biBhdXRvIGRlIGx1am8gKGNhcmNhdHZhbHVlPTMpDQoNCmBgYHtyfQ0KZGIkbHVqb19zaTwtaWZlbHNlKGRiJGNhcmNhdHZhbHVlPT0zLDEsMCkNCg0KZGIkbHVqb19zaTwtYXMuZmFjdG9yKGRiJGx1am9fc2kpDQpgYGANCg0KRmluYWxtZW50ZSwgZ3VhcmRhbW9zIHVuYSBjb3BpYSBkZSBzZWd1cmlkYWQgZGUgbG9zIGRhdG9zIHRyYXRhZG9zDQoNCmBgYHtyfQ0Kd3JpdGUuY3N2KGRiLCJkYl9jbGVhbi5jc3YiKQ0KYGBgDQoNCg0KIyA1LiBDcmVhY2nDs24gZGVsIG1vZGVsbw0KDQpTZXBhcmVtb3MgcHJpbWVybyBsYXMgY29sdW1uYXMgbnVtw6lyaWNhcyBkZSBsYXMgY2F0ZWfDs3JpY2FzDQoNCmBgYHtyfQ0KZGJfbnVtPC1kYiAlPiUgZHBseXI6OnNlbGVjdCh3aGVyZShpcy5udW1lcmljKSkNCmRiX2NhdDwtZGIgJT4lIGRwbHlyOjpzZWxlY3Qod2hlcmUoaXMuZmFjdG9yKSkNCmBgYA0KDQoqKkRhdG9zIE51bcOpcmljb3MqKg0KDQpgYGB7cn0NCg0KcGFyKG1mcm93PWMoMiwyKSkNCg0KZm9yIChpIGluIDE6bmNvbChkYl9udW0pKXsNCiAgaGlzdChkYl9udW1bW2ldXSwgbWFpbj1wYXN0ZSgiUGxvdCAiLCBjb2xuYW1lcyhkYl9udW1baV0pKSwgeGxhYiA9IHBhc3RlKCJWYWx1ZXMgUGxvdCIsaSkpIA0KICBib3gobHR5ID0gInNvbGlkIikNCn0NCg0KDQpgYGANCg0KVmVhbW9zIGxhIGNvbXBhcmFjacOzbiBkZSBsb3MgYm94cGxvdHMgcG9yIGNhdGVnb3LDrWEgZGUgYXV0bw0KDQpgYGB7cn0NCg0KZ2dwbG90KGRiLGFlcyh4PWNhcmNhdHZhbHVlLHk9Y2FydmFsdWUsY29sb3I9Y2FyY2F0dmFsdWUpKSsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gImJsYWNrIixub3RjaCA9IEZBTFNFKSsNCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgYWxwaGE9MC42KSArDQogIGdlb21faml0dGVyKGNvbG9yPSJncmF5Iiwgc2l6ZT0wLjQsIGFscGhhPTAuMTUpDQoNCmBgYA0KUG9kZW1vcyB2ZXIgcXVlIGxvcyBkYXRvcyBwYXJhIGxhIGNhdGVnb3LDrWEgZGUgbHVqbyBlc3TDoW4gYmFzdGFudGUgbcOhcyBkaXNwZXJzb3MgcXVlIGVuIGxhcyBvdHJhcyBjYXRlZ29yw61hcy4gQWRlbcOhcywgc3UgbWVkaWFuYSB0aWVuZGUgYSBsYSBiYWphLg0KDQoNClZlYW1vcyB0YW1iacOpbiBtw6FzIGRldGVuaWRhbWVudGUgbGEgY2FudGlkYWQgZGUgcGVyc29uYXMgcG9yIHZhbG9yIGRlbCBhdXRvDQoNCmBgYHtyfQ0Kc3RkX3ZhbHVlczwtZGRwbHkoZGIsImNhcmNhdHZhbHVlIixzdW1tYXJpc2UsTWluPW1pbihjYXJ2YWx1ZSksTWF4PW1heChjYXJ2YWx1ZSksTWVhbj1tZWFuKGNhcnZhbHVlKSxzZD1zZChjYXJ2YWx1ZSkpDQoNCg0KZ2dwbG90KGRiLGFlcyh4PWNhcnZhbHVlLGNvbG9yPWNhcmNhdHZhbHVlKSkrZ2VvbV9oaXN0b2dyYW0oZmlsbD0id2hpdGUiLGFscGhhPTAuNSxwb3NpdGlvbiA9ICJpZGVudGl0eSIpKw0KICBnZW9tX3ZsaW5lKGRhdGEgPSBzdGRfdmFsdWVzLGFlcyh4aW50ZXJjZXB0PU1lYW4sY29sb3I9Y2FyY2F0dmFsdWUpLGxpbmV0eXBlPSJkYXNoZWQiKSsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCxzaXplID0gMTApKQ0KYGBgDQoNClBvZGVtb3MgdmVyIHF1ZSBhIG1lZGlkYSBxdWUgY3JlY2UgZWwgdmFsb3IgZGVsIGF1dG8sIGRlY3JlY2UgbGEgY2FudGlkYWQgZGUgcGVyc29uYXMgcXVlIGxvIHRpZW5lbi4NCg0KKkRhdG9zIGdlbmVyYWxlcyoNCg0KQ29tcGFyZW1vcyBhIGxhcyBwZXJzb25hcyBxdWUgdGllbmVuIGF1dG9zIGRlIGx1am8gdnMgbGFzIHF1ZSBubywgZGUgYWN1ZXJkbyBhIGxhcyBtZWRpYXMgZGUgc3VzIHZhbG9yZXMgbnVtw6lyaWNvcw0KDQpgYGB7cn0NCmRiJT4lZ3JvdXBfYnkobHVqb19zaSklPiVzdW1tYXJpc2UobWVhbihhZ2UpLG1lZGlhbihhZ2UpLG1lYW4oZWQpLG1lYW4oc3BvdXNlZCkpDQpgYGANCg0KU29uIHBlcnNvbmFzIGRlIHVuYSBlZGFkIG1heW9yIGEgbGFzIHBlcnNvbmFzIHF1ZSBubyB0aWVuZW4gYXV0b3MgZGUgbHVqby4gQWRlbcOhcywgc3UgZWR1Y2FjacOzbiBlcyB1biBwb2NvIG1heW9yIGVuIHByb21lZGlvLCBwZXJvIG5vIHRhbnRvIGNvbW8gcGFyYSBkZWNpciBxdWUgZXMgdW4gcmFzZ28gcHJlcG9uZGVyYW50ZS4gDQoNCkNvbiBlbCBnw6luZXJvIHkgZXN0YWRvIGNpdmlsIHN1Y2VkZSBhbGdvIHNpbWlsYXIuIFNlIHB1ZWRlIHZlciBxdWUgbGEgbWF5b3LDrWEgc29uIG11amVyZXMgeSBxdWUgZWwgbWF5b3IgZXN0YWRvIGNpdmlsIGVzIHNvbHRlcm87IG5vIG9ic3RhbnRlLCBsYSBkaWZlcmVuY2lhIGVzIG11eSBwZXF1ZcOxYToNCg0KYGBge3IsZWNobz1GQUxTRX0NCmRiX2x1am88LWRiICU+JSBmaWx0ZXIobHVqb19zaT09MSkNCg0KZ2VuZGVyX3RhYmxlPC1jb3VudChkYl9sdWpvLCJnZW5kZXIiKQ0KDQphbGxfbHVqbzwtc3VtKGdlbmRlcl90YWJsZSRmcmVxKQ0KDQpnZW5kZXJfdGFibGUkcGVyY2VudGFnZTwtKGdlbmRlcl90YWJsZSRmcmVxL2FsbF9sdWpvKSoxMDANCg0KbWFyaXRhbF90YWJsZTwtY291bnQoZGJfbHVqbywibWFyaXRhbCIpDQoNCm1hcml0YWxfdGFibGUkcGVyY2VudGFnZTwtKG1hcml0YWxfdGFibGUkZnJlcS9hbGxfbHVqbykqMTAwDQoNCmdncGxvdChnZW5kZXJfdGFibGUsYWVzKHg9IiIsIHk9cGVyY2VudGFnZSAsZmlsbD1nZW5kZXIpKSsNCiAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKSsNCiAgY29vcmRfcG9sYXIoInkiLHN0YXJ0PTApKw0KICB0aGVtZV92b2lkKCkNCg0KZ2VuZGVyX3RhYmxlDQoNCmdncGxvdChtYXJpdGFsX3RhYmxlLGFlcyh4PSIiLCB5PXBlcmNlbnRhZ2UgLGZpbGw9bWFyaXRhbCkpKw0KICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpKw0KICBjb29yZF9wb2xhcigieSIsc3RhcnQ9MCkrDQogIHRoZW1lX3ZvaWQoKQ0KDQptYXJpdGFsX3RhYmxlDQoNCg0KYGBgDQoNCmBgYHtyfQ0KamNhdDwtZGIlPiVncm91cF9ieShsdWpvX3NpLGpvYmNhdCklPiVzdW1tYXJpc2UoY291bnQ9bigpKQ0KY2FzdChqY2F0LGpvYmNhdH5sdWpvX3NpLHZhbHVlID0gImNvdW50IikNCmBgYA0KDQoNCipEYXRvcyBkZSBlbXBsZW8gZSBpbmdyZXNvcyoNCg0KYGBge3J9DQpkYiU+JWdyb3VwX2J5KGx1am9fc2kpJT4lc3VtbWFyaXNlKG1lYW4oaW5jb21lKSxtZWFuKGVtcGxveSksbWVhbihjcmVkZGVidCksbWVhbihjYXJkc3BlbnQpKQ0KYGBgDQoNCk90cm8gcmFzZ28gY2FyYWN0ZXLDrXN0aWNvIGRlIGVzdGFzIHBlcnNvbmFzIGVzIHF1ZSB0aWVuZW4gdW5vcyBzdWVsZG9zIG11eSBhbHRvcyAobcOhcyBkZSAxMzYgMDAwIGFsIGHDsW8pIHkgZXN0w6FuIGVuIGVsIG1pc21vIHRyYWJham8gZGVzZGUgaGFjZSAxNiBhw7FvcyAoZW1wbG95KS4gRWwgZMOpYml0byBlbiBzdXMgdGFyamV0YXMgZGUgY3LDqWRpdG8gdGFtYmnDqW4gZXMgbWF5b3IuDQoNClZlYW1vcyB0YW1iacOpbiBsbyBjb3JyZXNwb25kaWVudGUgYSBsYXMgdGFyamV0YXMNCg0KYGBge3J9DQpjYXJkX3RiPC1kYiU+JWdyb3VwX2J5KGx1am9fc2ksY2FyZHR5cGUpJT4lc3VtbWFyaXNlKGNvdW50PW4oKSkNCmNhc3QoY2FyZF90YixjYXJkdHlwZX5sdWpvX3NpLHZhbHVlID0gImNvdW50IikNCmBgYA0KDQpSZXNwZWN0byBhIHNpIHJlYWxpemFuIGZhY3R1cmFjaW9uZXMgZWxlY3Ryw7NuaWNhcw0KDQpgYGB7cn0NCmVsZWN0PC1kYiU+JWdyb3VwX2J5KGx1am9fc2ksZWJpbGwpJT4lc3VtbWFyaXNlKGNvdW50PW4oKSkNCmNhc3QoZWxlY3QsZWJpbGx+bHVqb19zaSx2YWx1ZSA9ICJjb3VudCIpDQpgYGANCg0KKkRhdG9zIGRlIHB1YmxpY2lkYWQqDQoNCmBgYHtyfQ0KZGIlPiVncm91cF9ieShsdWpvX3NpKSU+JXN1bW1hcmlzZShtZWFuKGhvdXJzdHYpKQ0KYGBgDQoNCg0KYGBge3J9DQpkYiU+JWdyb3VwX2J5KGx1am9fc2kpJT4lc3VtbWFyaXNlKG1lYW4oaG91cnN0dikpDQpgYGANCg0KDQoNCmBgYHtyfQ0Kbnc8LWRiJT4lZ3JvdXBfYnkobHVqb19zaSxuZXdzKSU+JXN1bW1hcmlzZShjb3VudD1uKCkpDQpjYXN0KG53LG5ld3N+bHVqb19zaSx2YWx1ZSA9ICJjb3VudCIpDQpgYGANCg0KDQojIDUuIFBsYW50ZWFtaWVudG8gZGVsIG1vZGVsbw0KDQpTZSBwbGFudGVhIHJlYWxpemFyIHVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxvZ2lzdGljYSBwYXJhIHByZWRlY2lyIGVuIGJhc2UgYSBsYXMgdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMgbGEgcG9zaWJpbGlkYWQgZGUgcXVlIHVuYSBwZXJzb25hIHBvc2VhIHVuIGF1dG8gZGUgbHVqby4gRXN0byBwZXJtaXRpcsOhIGNvbXByb2JhciBxdWUgbGFzIHZhcmlhYmxlcyBzZWxlY2Npb25hZGFzIHNvbiBsYXMgbcOhcyBhZGVjdWFkYXMgcGFyYSBlbCBjYXNvIHBsYW50ZWFkbw0KDQpBaG9yYSBzZSBwYXNhcsOhIGEgdG9tYXIgdW5hIG11ZXN0cmEgYWxlYXRvcmlhIGRlbCB0b3RhbA0KDQpgYGB7cn0NCiNTZSBkaXZpZGVuIGxvcyBkYXRvcyBwYXJhIGVudHJlbmFtaWVudG8gKDc1JSBkZSB0cmFpbiB5IDI1JSBkZSB0ZXN0KQ0KDQpzZXQuc2VlZCg4OCkNCnNwbGl0PXNhbXBsZS5zcGxpdChkYiRsdWpvX3NpLFNwbGl0UmF0aW8gPSAwLjc1KQ0KDQoNCiNDcmVhciBlbCB0cmFpbmluZyB5IHRlc3RpbmcgZGF0YSBzZXRzDQoNCmR0PXN1YnNldChkYixzcGxpdD09VFJVRSkgICNUcmFpbg0KZGU9c3Vic2V0KGRiLHNwbGl0PT1GQUxTRSkgI1Rlc3QNCmBgYA0KDQpNb2RlbG8gZGUgcmVncmVzacOzbg0KDQpgYGB7cn0NClJMX0V1cjwtZ2xtKGx1am9fc2l+aW5jb21lK3RvbGxmcmVlK2NhcmR0eXBlK2ZvcndhcmQrZWJpbGwrY2FyZHNwZW50K3Nwb3VzZWQrZm9yd2FyZCtqb2JjYXQrcGV0c19yZXB0aWxlcyxkYXRhPWR0LGZhbWlseSA9IGJpbm9taWFsKCkpDQoNCnN1bW1hcnkoUkxfRXVyKQ0KYGBgDQoNCmBgYHtyfQ0KcHJlZGljdGlvbnM8LXByZWRpY3QoUkxfRXVyLGRlKQ0KYGBgDQoNCiMgNi4gQ29tcHJvYmFjacOzbiBkZSByZXN1bHRhZG9zDQoNCmBgYHtyfQ0Kc2lnbW9pZGU9ZnVuY3Rpb24oeCl7MS8oMStleHAoLXgpKX0NCg0KcGxvdChwcmVkaWN0aW9ucyxzaWdtb2lkZShwcmVkaWN0aW9ucyksY29sPSJibHVlIikNCmBgYA0KDQpgYGB7cn0NCm1vZF9wcmVkPC1pZmVsc2UocHJlZGljdGlvbnM+MC41LDEsMCkNCmBgYA0KDQoNCmBgYHtyfQ0KbW9kX3ByZWQ8LWZhY3Rvcihtb2RfcHJlZCkNCg0KaGVhZChtb2RfcHJlZCkNCg0KZGUkbHVqb19zaTwtZmFjdG9yKGRlJGx1am9fc2kpDQoNCmhlYWQoZGUkbHVqb19zaSkNCg0KYGBgDQoNCg0KYGBge3J9DQpjb25mdXNpb25NYXRyaXgobW9kX3ByZWQsZGUkbHVqb19zaSkNCmBgYA0KDQojIDcuIENvbXBhcmFjacOzbiBkZSBwcmVjaW9zIGRlIGF1dG9zIGNvbiBlbCBkYXRhc2V0DQoNClNlIGhpem8gdW4gc2NyYXBlIGRlIHByZWNpb3MgZGUgYWxndW5hcyBtYXJjYXMgZGUgbHVqbw0KDQpgYGB7cn0NCmNhcl9wcmljZXM8LXJlYWR4bDo6cmVhZF9leGNlbCgiU2NyYXBlcy54bHN4IikNCmhlYWQoY2FyX3ByaWNlcykNCmRpbShjYXJfcHJpY2VzKQ0KYGBgDQoNCg0KYGBge3J9DQoNCmdncGxvdChjYXJfcHJpY2VzLGFlcyh4PU1hcmNhLHk9UHJpY2UsY29sb3I9TWFyY2EpKSsNCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuY29sb3VyID0gImJsYWNrIixub3RjaCA9IEZBTFNFKSsNCiAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgYWxwaGE9MC42KSArDQogIGdlb21faml0dGVyKGNvbG9yPSJncmF5Iiwgc2l6ZT0wLjQsIGFscGhhPTAuMTUpDQoNCmBgYA0KDQpgYGB7cn0NCmNhcl9wcmljZXMlPiVzdW1tYXJpc2UobWVhbihQcmljZSksbWVkaWFuKFByaWNlKSxtaW4oUHJpY2UpLG1heChQcmljZSkpDQpgYGANCmBgYHtyfQ0KZGIlPiUgZmlsdGVyKGx1am9fc2k9PTEpJT4lc3VtbWFyaXNlKG1lYW4oY2FydmFsdWUpLG1lZGlhbihjYXJ2YWx1ZSksbWluKGNhcnZhbHVlKSxtYXgoY2FydmFsdWUpKQ0KYGBgDQoNCg0KDQoNCg0K