Antes de nada voy a cargar los datos y a echarles un ojo, además incorporo las librerías que voy a necesitar, para posteriormente elegir las variables.
source("FuncionesAida.R")
library(readxl)
library(questionr)
library(psych)
library(car)
library(corrplot)
library(ggplot2)
library(gridExtra)
library(dplyr)
library(caret)
library(lmSupport)
library(glmnet)
library(pROC)
DatosEleccionesEspaña <- read_excel("DatosEleccionesEspaña.xlsx")
datos<- as.data.frame(DatosEleccionesEspaña)
Name | CodigoProvincia | CCAA | Population | TotalCensus | AbstentionPtge | AbstencionAlta | Izda_Pct | Dcha_Pct | Otros_Pct | Izquierda | Derecha | Age_0-4_Ptge | Age_under19_Ptge | Age_19_65_pct | Age_over65_pct | WomanPopulationPtge | ForeignersPtge | SameComAutonPtge | SameComAutonDiffProvPtge | DifComAutonPtge | UnemployLess25_Ptge | Unemploy25_40_Ptge | UnemployMore40_Ptge | AgricultureUnemploymentPtge | IndustryUnemploymentPtge | ConstructionUnemploymentPtge | ServicesUnemploymentPtge | totalEmpresas | Industria | Construccion | ComercTTEHosteleria | Servicios | ActividadPpal | inmuebles | Pob2010 | SUPERFICIE | Densidad | PobChange_pct | PersonasInmueble | Explotaciones |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Abadía | 10 | Extremadura | 336 | 282 | 20,21 | 0 | 60,44 | 35,55 | 1,78 | 1 | 0 | 3,87 | 18,16 | 55,06 | 26,79 | 44,05 | 0,89 | 79,76 | 0,30 | 19,34 | 2,38 | 54,76 | 42,86 | 4,76 | 9,52 | 11,90 | 73,81 | 15 | 0 | 0 | 0 | 0 | Otro | 216 | 326 | 4507,56 | MuyBaja | 3,07 | 1,56 | 28 |
Abertura | 10 | Extremadura | 429 | 364 | 25,27 | 0 | 54,78 | 44,12 | 0,37 | 1 | 0 | 1,63 | 13,05 | 56,64 | 30,30 | 50,12 | 1,63 | 90,91 | 2,80 | 7,23 | 16,22 | 32,43 | 51,35 | 8,11 | 8,11 | 10,81 | 67,57 | 11 | 0 | 0 | 0 | 0 | Otro | 382 | 459 | 6270,76 | MuyBaja | -6,54 | 1,12 | 67 |
Acebo | 10 | Extremadura | 569 | 569 | 27,24 | 0 | 44,20 | 53,14 | 0,97 | 0 | 1 | 1,23 | 9,14 | 54,83 | 36,03 | 49,03 | 0,70 | 78,91 | 0,70 | 18,10 | 8,20 | 36,07 | 55,74 | 22,95 | 9,84 | 13,12 | 49,18 | 49 | 0 | 0 | 0 | 0 | Otro | 918 | 674 | 5702,10 | MuyBaja | -15,58 | 0,62 | 74 |
Acehúche | 10 | Extremadura | 822 | 704 | 30,11 | 1 | 50,81 | 45,33 | 0,00 | 1 | 0 | 4,26 | 14,96 | 60,10 | 24,94 | 51,09 | 0,12 | 93,92 | 0,49 | 5,11 | 7,41 | 61,11 | 31,48 | 16,67 | 5,56 | 16,67 | 59,26 | 50 | 0 | 0 | 0 | 0 | Otro | 599 | 842 | 9106,46 | MuyBaja | -2,38 | 1,37 | 66 |
Aceituna | 10 | Extremadura | 623 | 540 | 30,18 | 1 | 44,56 | 49,87 | 0,80 | 0 | 1 | 3,53 | 15,57 | 59,39 | 25,04 | 48,15 | 0,64 | 93,26 | 0,16 | 4,17 | 15,38 | 48,08 | 36,54 | 21,15 | 0,00 | 11,54 | 61,54 | 22 | 0 | 0 | 0 | 0 | Otro | 394 | 625 | 4007,61 | MuyBaja | -0,32 | 1,58 | 96 |
Ahigal | 10 | Extremadura | 1421 | 1263 | 22,57 | 0 | 53,07 | 45,50 | 0,41 | 1 | 0 | 3,17 | 13,30 | 56,51 | 30,19 | 47,78 | 0,56 | 92,96 | 0,63 | 6,33 | 4,22 | 47,89 | 47,89 | 21,13 | 5,63 | 12,68 | 56,34 | 90 | 5 | 18 | 56 | 11 | ComercTTEHosteleria | 1023 | 1451 | 5207,35 | MuyBaja | -2,07 | 1,39 | 281 |
Ya en primer lugar llama la atención el inmenso número de columnas que tenermos (41), así que nos enfrentamos a un problema de alta dimensionalidad. Como por algo hay que empezar, voy a elegir mis variables objetivo. Las que he elegido para predecir son {Izda_Pct y Derecha} así ambas predicciones a parte de distinguirse por su tipología lo harán por su naturaleza y esto puede resultar en variaciones interesantes entre los modelos. Además voy a generar una variable identificativa combinando el código de provincia y el nombre, que usaré para denominar las filas, de esta forma me puedo deshacer de la variable Name.
ID<- c()
for(i in c(0:nrow(datos))){
ID<- c(ID, paste(datos$CodigoProvincia[i], datos$Name[i], sep='-'))
}
rownames(datos)<- ID
valid.cols = c(c(2:5), c(8), c(12:ncol(datos)))
datos<- datos[,valid.cols]
summary(datos)
## CodigoProvincia CCAA Population TotalCensus
## Min. : 1.00 Length:8119 Min. : 5 Min. : 5
## 1st Qu.:13.00 Class :character 1st Qu.: 166 1st Qu.: 140
## Median :26.00 Mode :character Median : 549 Median : 447
## Mean :26.67 Mean : 5742 Mean : 4261
## 3rd Qu.:41.00 3rd Qu.: 2428 3rd Qu.: 1846
## Max. :52.00 Max. :3141991 Max. :2363829
##
## Izda_Pct Derecha Age_0-4_Ptge Age_under19_Ptge
## Min. : 0.00 Min. :0.0000 Min. : 0.000 Min. : 0.000
## 1st Qu.:21.89 1st Qu.:0.0000 1st Qu.: 1.389 1st Qu.: 8.334
## Median :35.16 Median :1.0000 Median : 2.978 Median :13.889
## Mean :34.40 Mean :0.6211 Mean : 3.019 Mean :13.568
## 3rd Qu.:46.03 3rd Qu.:1.0000 3rd Qu.: 4.533 3rd Qu.:19.058
## Max. :94.12 Max. :1.0000 Max. :13.245 Max. :33.696
##
## Age_19_65_pct Age_over65_pct WomanPopulationPtge ForeignersPtge
## Min. : 23.46 Min. : 0.00 Min. :11.77 Min. :-8.96
## 1st Qu.: 53.84 1st Qu.:19.82 1st Qu.:45.73 1st Qu.: 1.06
## Median : 58.66 Median :27.56 Median :48.48 Median : 3.59
## Mean : 57.37 Mean :29.07 Mean :47.30 Mean : 5.62
## 3rd Qu.: 61.82 3rd Qu.:36.91 3rd Qu.:50.00 3rd Qu.: 8.18
## Max. :100.00 Max. :76.47 Max. :72.68 Max. :71.47
##
## SameComAutonPtge SameComAutonDiffProvPtge DifComAutonPtge
## Min. : 0.00 Min. : 0.000 Min. : 0.000
## 1st Qu.: 75.81 1st Qu.: 0.676 1st Qu.: 4.933
## Median : 84.49 Median : 2.190 Median : 8.271
## Mean : 81.63 Mean : 4.337 Mean : 10.729
## 3rd Qu.: 90.46 3rd Qu.: 5.277 3rd Qu.: 13.898
## Max. :127.16 Max. :67.308 Max. :100.000
##
## UnemployLess25_Ptge Unemploy25_40_Ptge UnemployMore40_Ptge
## Min. : 0.000 Min. : 0.00 Min. : 0.00
## 1st Qu.: 0.000 1st Qu.: 28.57 1st Qu.: 41.67
## Median : 5.882 Median : 39.94 Median : 50.00
## Mean : 7.322 Mean : 37.00 Mean : 50.18
## 3rd Qu.: 10.470 3rd Qu.: 46.67 3rd Qu.: 60.04
## Max. :100.000 Max. :100.00 Max. :100.00
##
## AgricultureUnemploymentPtge IndustryUnemploymentPtge
## Min. : 0.000 Min. : 0.000
## 1st Qu.: 0.000 1st Qu.: 0.000
## Median : 3.493 Median : 7.143
## Mean : 8.401 Mean : 10.008
## 3rd Qu.: 11.732 3rd Qu.: 14.286
## Max. :100.000 Max. :100.000
##
## ConstructionUnemploymentPtge ServicesUnemploymentPtge totalEmpresas
## Min. : 0.000 Min. : 0.00 Min. : 0.0
## 1st Qu.: 0.000 1st Qu.: 50.00 1st Qu.: 7.0
## Median : 8.333 Median : 62.02 Median : 30.0
## Mean : 10.838 Mean : 58.65 Mean : 398.6
## 3rd Qu.: 14.286 3rd Qu.: 72.12 3rd Qu.: 147.0
## Max. :100.000 Max. :100.00 Max. :299397.0
## NA's :5
## Industria Construccion ComercTTEHosteleria
## Min. : 0.00 Min. : 0.00 Min. : 0.0
## 1st Qu.: 0.00 1st Qu.: 0.00 1st Qu.: 0.0
## Median : 0.00 Median : 0.00 Median : 0.0
## Mean : 23.42 Mean : 48.88 Mean : 146.7
## 3rd Qu.: 14.00 3rd Qu.: 25.00 3rd Qu.: 65.0
## Max. :10521.00 Max. :30343.00 Max. :80856.0
## NA's :188 NA's :139 NA's :9
## Servicios ActividadPpal inmuebles Pob2010
## Min. : 0.0 Length:8119 Min. : 6 Min. : 5
## 1st Qu.: 0.0 Class :character 1st Qu.: 180 1st Qu.: 178
## Median : 0.0 Mode :character Median : 486 Median : 582
## Mean : 172.2 Mean : 3246 Mean : 5796
## 3rd Qu.: 40.0 3rd Qu.: 1589 3rd Qu.: 2483
## Max. :177677.0 Max. :1615548 Max. :3273049
## NA's :62 NA's :138 NA's :7
## SUPERFICIE Densidad PobChange_pct
## Min. : 2.58 Length:8119 Min. :-52.2700
## 1st Qu.: 1839.19 Class :character 1st Qu.:-10.4000
## Median : 3487.74 Mode :character Median : -4.9600
## Mean : 6214.70 Mean : -4.8974
## 3rd Qu.: 6893.88 3rd Qu.: 0.0925
## Max. :175022.91 Max. :138.4600
## NA's :9 NA's :7
## PersonasInmueble Explotaciones
## Min. :0.110 Min. : 1
## 1st Qu.:0.850 1st Qu.: 22
## Median :1.250 Median : 52
## Mean :1.296 Mean : 2447
## 3rd Qu.:1.730 3rd Qu.: 137
## Max. :3.330 Max. :99999
## NA's :138
En el ‘summary’ detectamos varias cosas que tendremos que tener en cuenta:
Las columnas totalEmpresas, Industria, Construccion, ComercTTEHosteleria, Servicios, inmuebles, Pob2010, SUPERFICIE, PobChange_pct y PersonasInmueble presentan datos ‘missing’ en proporción variable que tendré que tratar. Además las columnas Densidad, ForeignersPtge toman valores sospechosos como ‘?’ y negativos por lo que los pasaré a datos ‘missing’.
Las columnas CCAA, ActividadPpal y Densidad son tipo ‘character’ y seguramente deba pasarlas a tipo ‘factor’.
Varias columnas numéricas tienen un valor máximo muy alejado del 3º cuartil, resultan especialmente sospechosas Industria, Construcción, ComercTTEHostelería y Servicios, donde más de la mitad de los datos son ceros y el máximo es del orden de las decenas de millar. Por su parte en Explotaciones el máximo es 99999, y parece un input incorrecto.
Las variables tipo porcentaje acaban en Ptge y en pct lo que resulta confuso. Además las referidas al desempleo alcanzan un valor máximo del 100% lo que me hace pensar que se trate de medidas relativas.
Lo primero que hacemos es pasar a factores las columnas tipo ‘character’ y comprobar que no hay columnas numéricas con una cantidad de valores suficientemente baja como para que nos interese convertirlas también.
datos[,c(2,6,28,32)] <- lapply(datos[,c(2,6,28,32)], factor)
# Cuento el n?mero de valores diferentes para las numéricas
sapply(Filter(is.numeric, datos),function(x) length(unique(x)))
## CodigoProvincia Population
## 52 3597
## TotalCensus Izda_Pct
## 3310 6569
## Age_0-4_Ptge Age_under19_Ptge
## 3761 5891
## Age_19_65_pct Age_over65_pct
## 6215 6778
## WomanPopulationPtge ForeignersPtge
## 4524 2329
## SameComAutonPtge SameComAutonDiffProvPtge
## 6151 4207
## DifComAutonPtge UnemployLess25_Ptge
## 5574 2342
## Unemploy25_40_Ptge UnemployMore40_Ptge
## 2681 2751
## AgricultureUnemploymentPtge IndustryUnemploymentPtge
## 2525 2538
## ConstructionUnemploymentPtge ServicesUnemploymentPtge
## 2505 2904
## totalEmpresas Industria
## 1226 308
## Construccion ComercTTEHosteleria
## 457 803
## Servicios inmuebles
## 758 3088
## Pob2010 SUPERFICIE
## 3625 8110
## PobChange_pct PersonasInmueble
## 3049 283
## Explotaciones
## 758
vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CodigoProvincia | 1 | 8119 | 26,67 | 14,90 | 26,00 | 26,71 | 20,76 | 1,00 | 52,00 | 51,00 | 0,01 | -1,32 | 0,17 |
Population | 2 | 8119 | 5741,85 | 46215,20 | 549,00 | 1401,04 | 698,30 | 5,00 | 3141991,00 | 3141986,00 | 45,98 | 2814,43 | 512,90 |
TotalCensus | 3 | 8119 | 4260,67 | 34428,89 | 447,00 | 1079,86 | 560,42 | 5,00 | 2363829,00 | 2363824,00 | 46,49 | 2888,34 | 382,10 |
Izda_Pct | 4 | 8119 | 34,40 | 16,48 | 35,16 | 34,35 | 17,91 | 0,00 | 94,12 | 94,12 | 0,06 | -0,49 | 0,18 |
Age_0-4_Ptge | 5 | 8119 | 3,02 | 2,05 | 2,98 | 2,94 | 2,33 | 0,00 | 13,24 | 13,24 | 0,34 | -0,21 | 0,02 |
Age_under19_Ptge | 6 | 8119 | 13,57 | 6,78 | 13,89 | 13,68 | 7,90 | 0,00 | 33,70 | 33,70 | -0,10 | -0,79 | 0,08 |
Age_19_65_pct | 7 | 8119 | 57,37 | 6,82 | 58,66 | 57,92 | 5,56 | 23,46 | 100,00 | 76,54 | -0,81 | 2,15 | 0,08 |
Age_over65_pct | 8 | 8119 | 29,07 | 11,75 | 27,56 | 28,32 | 12,33 | 0,00 | 76,47 | 76,47 | 0,60 | 0,07 | 0,13 |
WomanPopulationPtge | 9 | 8119 | 47,30 | 4,36 | 48,48 | 47,89 | 2,76 | 11,77 | 72,68 | 60,92 | -1,67 | 5,80 | 0,05 |
ForeignersPtge | 10 | 8119 | 5,62 | 7,35 | 3,59 | 4,54 | 4,60 | -8,96 | 71,47 | 80,43 | 2,50 | 11,34 | 0,08 |
SameComAutonPtge | 11 | 8119 | 81,63 | 12,29 | 84,49 | 83,22 | 10,20 | 0,00 | 127,16 | 127,16 | -1,52 | 3,47 | 0,14 |
SameComAutonDiffProvPtge | 12 | 8119 | 4,34 | 6,39 | 2,19 | 2,97 | 2,95 | 0,00 | 67,31 | 67,31 | 3,29 | 14,55 | 0,07 |
DifComAutonPtge | 13 | 8119 | 10,73 | 8,85 | 8,27 | 9,34 | 5,94 | 0,00 | 100,00 | 100,00 | 2,42 | 9,65 | 0,10 |
UnemployLess25_Ptge | 14 | 8119 | 7,32 | 9,41 | 5,88 | 5,81 | 8,72 | 0,00 | 100,00 | 100,00 | 4,15 | 31,63 | 0,10 |
Unemploy25_40_Ptge | 15 | 8119 | 37,00 | 20,32 | 39,94 | 37,04 | 12,39 | 0,00 | 100,00 | 100,00 | 0,21 | 1,41 | 0,23 |
UnemployMore40_Ptge | 16 | 8119 | 50,18 | 22,80 | 50,00 | 50,93 | 14,12 | 0,00 | 100,00 | 100,00 | -0,23 | 0,85 | 0,25 |
AgricultureUnemploymentPtge | 17 | 8119 | 8,40 | 12,96 | 3,49 | 5,69 | 5,18 | 0,00 | 100,00 | 100,00 | 3,23 | 15,56 | 0,14 |
IndustryUnemploymentPtge | 18 | 8119 | 10,01 | 12,53 | 7,14 | 7,85 | 10,59 | 0,00 | 100,00 | 100,00 | 3,09 | 16,04 | 0,14 |
ConstructionUnemploymentPtge | 19 | 8119 | 10,84 | 13,28 | 8,33 | 8,44 | 10,08 | 0,00 | 100,00 | 100,00 | 3,09 | 14,61 | 0,15 |
ServicesUnemploymentPtge | 20 | 8119 | 58,65 | 24,26 | 62,02 | 60,69 | 17,72 | 0,00 | 100,00 | 100,00 | -0,81 | 0,80 | 0,27 |
totalEmpresas | 21 | 8114 | 398,60 | 4219,37 | 30,00 | 85,36 | 44,48 | 0,00 | 299397,00 | 299397,00 | 53,68 | 3472,00 | 46,84 |
Industria | 22 | 7931 | 23,42 | 158,61 | 0,00 | 6,39 | 0,00 | 0,00 | 10521,00 | 10521,00 | 44,26 | 2642,01 | 1,78 |
Construccion | 23 | 7980 | 48,88 | 421,86 | 0,00 | 11,57 | 0,00 | 0,00 | 30343,00 | 30343,00 | 52,56 | 3503,51 | 4,72 |
ComercTTEHosteleria | 24 | 8110 | 146,74 | 1233,02 | 0,00 | 31,86 | 0,00 | 0,00 | 80856,00 | 80856,00 | 45,40 | 2646,94 | 13,69 |
Servicios | 25 | 8057 | 172,15 | 2446,81 | 0,00 | 22,01 | 0,00 | 0,00 | 177677,00 | 177677,00 | 57,48 | 3830,74 | 27,26 |
inmuebles | 26 | 7981 | 3246,16 | 24314,71 | 486,00 | 927,86 | 555,98 | 6,00 | 1615548,00 | 1615542,00 | 44,53 | 2643,65 | 272,17 |
Pob2010 | 27 | 8112 | 5795,81 | 47535,68 | 582,00 | 1433,66 | 730,92 | 5,00 | 3273049,00 | 3273044,00 | 47,15 | 2939,56 | 527,78 |
SUPERFICIE | 28 | 8110 | 6214,70 | 9218,19 | 3487,74 | 4414,91 | 3029,12 | 2,58 | 175022,91 | 175020,33 | 6,07 | 62,28 | 102,36 |
PobChange_pct | 29 | 8112 | -4,90 | 10,38 | -4,96 | -5,11 | 7,83 | -52,27 | 138,46 | 190,73 | 1,50 | 15,08 | 0,12 |
PersonasInmueble | 30 | 7981 | 1,30 | 0,57 | 1,25 | 1,28 | 0,64 | 0,11 | 3,33 | 3,22 | 0,26 | -0,63 | 0,01 |
Explotaciones | 31 | 8119 | 2447,20 | 15062,74 | 52,00 | 80,85 | 54,86 | 1,00 | 99999,00 | 99998,00 | 6,32 | 37,95 | 167,17 |
De momento voy a dejarlo así, ya que los datos son funcionales, pero me incomodan la columna CCAA, sobre la que trataré de agrupar categorías con cierto criterio más adelante, y la de CódigoProvincia, esta columna implica una agrupación de los datos, pero contiene demasiadas categorías (52), y puede aportar información aunque haya sido empleada como identificativa, así que voy a conservarla como numérica, pese a que no me entusiasma la idea.
Lo siguiente que voy a hacer es convertir en ‘NAs’ esos valores que hemos visto que parecían inputs incorrectos, además voy a echarle un ojo a las variables cualitativas para ver si puedo agrupar categorías poco representadas.
# Missings no declarados (99999, ?)
datos$Explotaciones<-recode.na(datos$Explotaciones,99999,as.numeric = T)
datos$Densidad<-recode.na(datos$Densidad,"?")
# Valores fuera de rango
datos$ForeignersPtge<-replace(datos$ForeignersPtge, which(datos$ForeignersPtge < 0), NA)
Miramos las variables categóricas para detectar categorías poco representadas. La forma de categorizar CCAA no es trivial ya que sabemos que subyacen relaciones geográficas, demográficas, históricas, … que debemos tener en cuenta. En este caso, dado que no podía extenderme en exceso, he decidido crear 4 categorías atendiendo esencialmente a variables demográficas. Primero agrupo el resto de variables categóricas.
Vemos que lo lógico es agrupar Servicios, Construcción e Industria (y aprovechar para renombrar Hosteleria) para la variable ActividadPpal. Por su parte en densidad vamos a agrupar Alta y Baja como Alta y a renombrar MuyBaja como Baja. De esta forma reducimos las categorías en ambos casos, teniendo categorías más representadas pero que conservan el significado de las categorías originales.
# Agrupamos las categorías poco representadas
# Interesa agrupar Construcción/Industria y Servicios
datos$ActividadPpal<- car::recode(datos$ActividadPpal,
"c('Construccion', 'Industria', 'Servicios')='Const/Indus/Servi';
c('ComercTTEHosteleria') ='Hosteleria'")
datos$Densidad<- car::recode(datos$Densidad,
"c('Alta', 'Baja')='Alta';c('MuyBaja') ='Baja'")
# Renombro además las variables asociadas
names(datos)[26]<- 'Hosteleria'
Las categorías de ActividadPpal tenían asociada su propia columna, que a priori pensé que procedían de generar ‘dummies’ pero toman valores bastante extraños, en Construcción el 61% de los datos son 0, en Servicios el 61%, en Industria el 61% y en Hosteleria el 61%, son porcentajes muy altos para columnas que tienen valores máximos del orden de las decenas de millar, así que voy a generarme una variable nueva en la que diga si el valor es mayor que cero o no, que creo que es la información que realmente podemos extraer de estas columnas.
Abordo ahora la agrupación de la variable Comunidad Autónoma, que he realizado basándome en mi propio criterio sobre una preagrupación en las variables Population, Age_under19_Ptge y ForeignersPtge (lo que sería un ‘clustering’ a ojímetro).
datos$ActPpal.bin <- as.factor(apply(ifelse(datos[,c(24:27)]<=0,0,1), 1, prod, na.rm=T))
# Agrupo las comunidades autónomas
CCAA.grouped <- as.data.frame(datos[,c(2,3,8,12)] %>%
group_by(CCAA) %>%
summarise(
Population = mean(Population, na.rm=T),
Age_under19_Ptge = mean(Age_under19_Ptge, na.rm=T),
ForeignersPtge = mean(ForeignersPtge, na.rm=T)
))
rownames(CCAA.grouped) <- CCAA.grouped$CCAA
CCAA.grouped <- CCAA.grouped[,c(2:4)]
factor_3 <- function (values, desired.labels){
lim0 <- min(values)
lim1 <- mean(values) - sqrt(var(values))
lim3 <- mean(values) + sqrt(var(values))
lim4 <- max(values)
category <- cut(values, c(lim0,lim1,lim3,lim4), include.lowest=c(T,F,F), labels=desired.labels)
}
CCAA.grouped$Population <- factor_3(CCAA.grouped$Population, c("poco poblado", "normal poblado",
"muy poblado"))
CCAA.grouped$Age_under19_Ptge <- factor_3(CCAA.grouped$Age_under19_Ptge, c("poco joven", "normal joven",
"muy joven"))
CCAA.grouped$ForeignersPtge <- factor_3(CCAA.grouped$ForeignersPtge, c("pocos extranjero", "normal extranjero",
"muy extranjero"))
datos$CCAA.grouped<- car::recode(datos$CCAA,
"c('Asturias', 'Cantabria', 'Extremadura', 'Galicia')='PE-NJ';
c('Andalucía', 'Canarias', 'CastillaMancha','Cataluña', 'Ceuta',
'ComValenciana', 'Navarra', 'PaísVasco') ='NE-NJ';
c('Aragón', 'CastillaLeón', 'Rioja')='NE-PJ';
c('Madrid', 'Baleares', 'Melilla', 'Murcia')='ME-NJ'")
Population | Age_under19_Ptge | ForeignersPtge | |
---|---|---|---|
Asturias | normal poblado | normal joven | pocos extranjero |
Cantabria | normal poblado | normal joven | pocos extranjero |
Extremadura | normal poblado | normal joven | pocos extranjero |
Galicia | normal poblado | normal joven | pocos extranjero |
Andalucía | normal poblado | normal joven | normal extranjero |
Aragón | normal poblado | poco joven | normal extranjero |
Canarias | normal poblado | normal joven | normal extranjero |
CastillaLeón | poco poblado | poco joven | normal extranjero |
CastillaMancha | normal poblado | normal joven | normal extranjero |
Cataluña | normal poblado | normal joven | normal extranjero |
Ceuta | muy poblado | muy joven | normal extranjero |
ComValenciana | normal poblado | normal joven | normal extranjero |
Navarra | normal poblado | normal joven | normal extranjero |
PaísVasco | normal poblado | normal joven | normal extranjero |
Rioja | normal poblado | poco joven | normal extranjero |
Baleares | normal poblado | normal joven | muy extranjero |
Madrid | normal poblado | normal joven | muy extranjero |
Melilla | muy poblado | muy joven | muy extranjero |
Murcia | normal poblado | normal joven | muy extranjero |
Las agrupaciones las he decidido basándome en la última tabla, el porcentaje de extranjeros define las categorías y dentro de las comunidades ‘normal extranjero’ las que tienen ‘normal joven’ y ‘muy joven’ van juntas y las ‘poco joven’ aparte. Visto así nos quedan los siguientes 4 grupos: (Asturias, Cantabria, Extremadura y Galicia), (Andalucía, Canarias, Castilla la Mancha, Cataluña, Ceuta, Valencia, Navarra y País Vasco), (Aragón, Castilla y León y la Rioja) y (Baleares, Madrid, Melilla y Murcia). Vemos que los grupos son de tamaños razonables y de alguna forma es más preciso que una agrupación basada únicamente en nuestros prejuicios, por supuesto están generados a partir de otros datos, luego recogen la información ya presente en estos, en cualquier caso conservaré tanto la columna original como la agrupada y ya veremos cual aporta mayor información.
A partir de este momento ya separo mis variables objetivo de mis variables input y continuo trabajando únicamente sobre las variables input. En primer lugar voy a calcular el porcentaje de ‘outliers’ presentes en cada variable, si los porcentajes son pequeños, los sustituiré por valores ‘missing’.
varObjCont<- datos$Izda_Pct
varObjBin<- datos$Derecha
input<- as.data.frame(datos[,-c(5,6)])
# Porcentaje por variable
sapply(Filter(is.numeric, input), function(x) atipicosAmissing(x)[[2]])/nrow(input)
## CodigoProvincia Population
## 0.0000000000 0.0992733095
## TotalCensus Age_0-4_Ptge
## 0.0961941126 0.0000000000
## Age_under19_Ptge Age_19_65_pct
## 0.0000000000 0.0029560291
## Age_over65_pct WomanPopulationPtge
## 0.0000000000 0.0025865254
## ForeignersPtge SameComAutonPtge
## 0.0052962187 0.0001231679
## SameComAutonDiffProvPtge DifComAutonPtge
## 0.0203226998 0.0049267151
## UnemployLess25_Ptge Unemploy25_40_Ptge
## 0.0032023648 0.0000000000
## UnemployMore40_Ptge AgricultureUnemploymentPtge
## 0.0000000000 0.0199531962
## IndustryUnemploymentPtge ConstructionUnemploymentPtge
## 0.0059120581 0.0065278975
## ServicesUnemploymentPtge totalEmpresas
## 0.0000000000 0.1050621998
## Industria Construccion
## 0.0874491933 0.0891735435
## Hosteleria Servicios
## 0.0985343023 0.1187338342
## inmuebles Pob2010
## 0.0886808720 0.0975489592
## SUPERFICIE PobChange_pct
## 0.0270969331 0.0012316788
## PersonasInmueble Explotaciones
## 0.0000000000 0.0454489469
# Modifico los atípicos como missings
input[,as.vector(which(sapply(input, class)=="numeric"))]<- sapply(Filter(is.numeric, input),
function(x) atipicosAmissing(x)[[1]])
Podemos ver que las variables con mayor porcentaje de ‘outliers’ apenas rondan el 10%. Seguramente incorporarlos como ‘missing’ favorezca el comportamiento del modelo. Por supuesto este proceso podría repetirse ad-infinitum ya que si busco ‘outliers’ en el nuevo ‘set’ aparecerán nuevos que antes no lo eran. Tal vez la aplicación de estas líneas sobre el ‘set’ de datos de forma recurrente hasta alcanzar una tolerancia podría resultar en unos datos exquisitamente centrados pero los estarían tan maquillados que habríamos perdido demasiada información. Una única aplicación para eliminar el factor lotería parece lo razonable.
Una vez tratadas todas las posibles fuentes de datos ‘missing’ tenemos que abordar estos casos. En primer lugar debemos mirar nuestra estructura de datos, para ello voy a representar la correlación entre los datos perdidos y no perdidos (en binario) de nuestras variables.
Hay varias variables que aparecen fuertementemente correlacionadas, en principio la correlacion entre Population, TotalCensus y Pob2010 es trivial y debería conservarse al tratar las propias variables que seguramente estén muy correlacionadas, incluso podríamos considerarlas dependientes. Por otro lado es bastante sugerente que allí donde a estas variables les faltan datos les falten también a totalEmpresas, Inmuebles y Industria, Construccion, Hosteleria y Servicios. Deben existir algunas localidades que no recogen estos datos o que no están queriendo publicarlos, así que añadiremos una variable con la proporción de missings de cada localidad, ya que si podría resultar indicativa. De igual forma miraremos el porcentaje de ‘missings’ en cada columna, por si alguna conviniese directamente eliminarla.
input$prop_missings<-apply(is.na(input),1,mean)
summary(input$prop_missings)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00000 0.00000 0.00000 0.03508 0.02857 0.34286
apply(is.na(input), 2, mean)
## CodigoProvincia CCAA
## 0.0000000000 0.0000000000
## Population TotalCensus
## 0.0992733095 0.0961941126
## Age_0-4_Ptge Age_under19_Ptge
## 0.0000000000 0.0000000000
## Age_19_65_pct Age_over65_pct
## 0.0029560291 0.0000000000
## WomanPopulationPtge ForeignersPtge
## 0.0025865254 0.0857248430
## SameComAutonPtge SameComAutonDiffProvPtge
## 0.0001231679 0.0203226998
## DifComAutonPtge UnemployLess25_Ptge
## 0.0049267151 0.0032023648
## Unemploy25_40_Ptge UnemployMore40_Ptge
## 0.0000000000 0.0000000000
## AgricultureUnemploymentPtge IndustryUnemploymentPtge
## 0.0199531962 0.0059120581
## ConstructionUnemploymentPtge ServicesUnemploymentPtge
## 0.0065278975 0.0000000000
## totalEmpresas Industria
## 0.1056780392 0.1106047543
## Construccion Hosteleria
## 0.1062938786 0.0996428132
## Servicios ActividadPpal
## 0.1263702426 0.0000000000
## inmuebles Pob2010
## 0.1056780392 0.0984111344
## SUPERFICIE Densidad
## 0.0282054440 0.0113314448
## PobChange_pct PersonasInmueble
## 0.0020938539 0.0169971671
## Explotaciones ActPpal.bin
## 0.0687276758 0.0000000000
## CCAA.grouped prop_missings
## 0.0000000000 0.0000000000
Entre las columnas numéricas los valores mayores se encuentran en torno al 10% así que en principio voy a conservarlas todas, eso sí, inputaré valores en esos missings. Para las categóricas solo hay ‘missings’ en Densidad, algo más de un 1%, así que también inputaré los valores. De entre las filas hasta el 75% de las observaciones está por debajo del 4% de características ‘missing’, sin embargo preocupa el máximo, que es del 35%. De momento voy a dejarlas todas ya que ninguna supera el límite del 50%, igual que en las columnas sustituiré estos ‘missings’ por valores similares a los observados en la varible. Dependiendo de como estén distribuidos los datos en las variables inputaré aleatorios, valores iguales a la media o a la mediana, así que primero miro las distribuciones de las variables numéricas que voy a imputar.
vars | n | mean | sd | median | trimmed | mad | min | max | range | skew | kurtosis | se | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Population | 1 | 7313 | 1255,87 | 1840,51 | 431,00 | 817,60 | 521,88 | 5,00 | 9208,00 | 9203,00 | 2,18 | 4,42 | 21,52 |
TotalCensus | 2 | 7338 | 988,49 | 1415,14 | 358,00 | 653,92 | 424,02 | 5,00 | 6958,00 | 6953,00 | 2,15 | 4,25 | 16,52 |
Age_19_65_pct | 3 | 8095 | 57,44 | 6,60 | 58,67 | 57,94 | 5,55 | 30,36 | 85,72 | 55,36 | -0,75 | 1,13 | 0,07 |
WomanPopulationPtge | 4 | 8098 | 47,36 | 4,17 | 48,49 | 47,91 | 2,75 | 26,47 | 69,23 | 42,76 | -1,39 | 3,53 | 0,05 |
ForeignersPtge | 5 | 7423 | 6,09 | 6,32 | 4,10 | 5,03 | 4,48 | 0,00 | 40,09 | 40,09 | 1,86 | 4,46 | 0,07 |
SameComAutonPtge | 6 | 8118 | 81,64 | 12,26 | 84,49 | 83,22 | 10,20 | 15,41 | 127,16 | 111,74 | -1,50 | 3,30 | 0,14 |
SameComAutonDiffProvPtge | 7 | 7954 | 3,70 | 4,52 | 2,12 | 2,79 | 2,83 | 0,00 | 25,73 | 25,73 | 2,02 | 4,48 | 0,05 |
DifComAutonPtge | 8 | 8079 | 10,46 | 7,98 | 8,24 | 9,27 | 5,89 | 0,00 | 55,56 | 55,56 | 1,76 | 4,24 | 0,09 |
UnemployLess25_Ptge | 9 | 8093 | 7,03 | 7,84 | 5,86 | 5,77 | 8,69 | 0,00 | 75,00 | 75,00 | 2,10 | 8,10 | 0,09 |
AgricultureUnemploymentPtge | 10 | 7957 | 7,19 | 9,37 | 3,23 | 5,31 | 4,78 | 0,00 | 46,43 | 46,43 | 1,62 | 2,21 | 0,11 |
IndustryUnemploymentPtge | 11 | 8071 | 9,47 | 10,46 | 7,01 | 7,74 | 10,40 | 0,00 | 82,00 | 82,00 | 1,70 | 4,15 | 0,12 |
ConstructionUnemploymentPtge | 12 | 8066 | 10,25 | 11,18 | 8,33 | 8,32 | 9,88 | 0,00 | 86,49 | 86,49 | 2,04 | 6,14 | 0,12 |
totalEmpresas | 13 | 7261 | 72,93 | 113,95 | 23,00 | 45,29 | 34,10 | 0,00 | 566,00 | 566,00 | 2,28 | 4,88 | 1,34 |
Industria | 14 | 7221 | 6,23 | 11,84 | 0,00 | 3,22 | 0,00 | 0,00 | 56,00 | 56,00 | 2,17 | 4,18 | 0,14 |
Construccion | 15 | 7256 | 11,15 | 21,17 | 0,00 | 5,77 | 0,00 | 0,00 | 100,00 | 100,00 | 2,17 | 4,16 | 0,25 |
Hosteleria | 16 | 7310 | 28,67 | 54,07 | 0,00 | 14,95 | 0,00 | 0,00 | 260,00 | 260,00 | 2,19 | 4,34 | 0,63 |
Servicios | 17 | 7093 | 15,90 | 32,48 | 0,00 | 7,29 | 0,00 | 0,00 | 160,00 | 160,00 | 2,44 | 5,58 | 0,39 |
inmuebles | 18 | 7261 | 882,30 | 1138,88 | 399,00 | 625,43 | 431,44 | 6,00 | 5811,00 | 5805,00 | 2,12 | 4,30 | 13,37 |
Pob2010 | 19 | 7320 | 1300,47 | 1875,47 | 460,50 | 857,38 | 549,30 | 5,00 | 9361,00 | 9356,00 | 2,15 | 4,26 | 21,92 |
SUPERFICIE | 20 | 7890 | 5080,93 | 4910,05 | 3375,00 | 4144,00 | 2859,54 | 2,58 | 27681,20 | 27678,62 | 1,92 | 3,87 | 55,28 |
Densidad* | 21 | 8027 | 1,80 | 0,40 | 2,00 | 1,87 | 0,00 | 1,00 | 2,00 | 1,00 | -1,50 | 0,24 | 0,00 |
PobChange_pct | 22 | 8102 | -5,01 | 9,80 | -4,97 | -5,13 | 7,81 | -52,27 | 54,05 | 106,32 | 0,45 | 3,31 | 0,11 |
PersonasInmueble | 23 | 7981 | 1,30 | 0,57 | 1,25 | 1,28 | 0,64 | 0,11 | 3,33 | 3,22 | 0,26 | -0,63 | 0,01 |
Explotaciones | 24 | 7561 | 83,48 | 93,74 | 46,00 | 64,17 | 45,96 | 1,00 | 465,00 | 464,00 | 1,86 | 3,11 | 1,08 |
Pese a que todas las distribuciones son leptocúrticas, y por lo tanto están de alguna forma concentradas en torno a la media, no voy a inputar siempre por medidas centrales. Tanto si hay mucha diferencia entre la media y la mediana como si el porcentaje de ‘missings’ es alto inputaré con datos aleatorios, y si la diferencia es pequeña (aqui ‘mucha’ y ‘pequeña’ obedecerán a mi criterio) inputaré mediante la mayor o menor de ellas dependiendo del signo del coeficiente de simetría. Por otro lado, variables cualitativas con ‘missings’ solo hay una, y con un pocentaje de ‘missings’ realmente bajo, así que haré la inputación aleatoria.
Todo aparece dentro de un bucle while porque no se me estaban sustituyendo todos los ‘missing’ en una sola ejecución
## Imputaciones
while(length(which(apply(is.na(input),2, mean) >0))){
# Imputo todas las cuantitativas con la media
inputando <- c("Age_19_65_pct", "SameComAutonDiffProvPtge", "DifComAutonPtge", "SUPERFICIE",
"PobChange_pct", 'WomanPopulationPtge', 'UnemployLess25_Ptge',
'IndustryUnemploymentPtge', 'ConstructionUnemploymentPtge', 'SameComAutonPtge',
'PersonasInmueble')
input[,inputando]<- sapply(input[, inputando], function(x) ImputacionCuant(x,"media"))
# Imputo todas las cuantitativas con aleatorios
inputando <- c("Population", "TotalCensus", "ForeignersPtge", "totalEmpresas", "Industria", "Construccion",
"Hosteleria", "Servicios", "inmuebles", "Pob2010", 'AgricultureUnemploymentPtge',
"Explotaciones")
input[,inputando]<- sapply(input[, inputando], function(x) ImputacionCuant(x,"aleatorio"))
# Imputo todas las cualitativas
input[,as.vector(which(sapply(input, class)=="factor"))]<-sapply(Filter(is.factor, input),
function(x) ImputacionCuali(x,"aleatorio"))
# A veces se cambia el tipo de factor a character al imputar, así que hay que indicarle que es factor
input[,as.vector(which(sapply(input, class)=="character"))] <- lapply(input[,as.vector(which(sapply(input, class)=="character"))] , factor)
}
# Reviso que no queden datos missings
which(apply(is.na(input),2,sum) >0)
## named integer(0)
Hecho esto doy por terminada la depuración, ya he corregido los errores que traían los datos y dispongo de unos datos tratables estadísticamente.
Aunque durante la eliminación de los inputs erróneos y los outliers y la sustitución de los valores missings hemos alcanzado cierta perspectiva sobre el contenido de los datos, vamos ahora a explorarlos y transformalos para intentar facilitar la tarea de predicción al modelo.
Lo primero que hago es añadir un par de variables aleatorias para establecer que me permita valorar el contenido de información de las demás. Por otro lado veo mediante la V de Cramer la asociación presente entre mis variable objetivo y el resto.
# Primera visualización ----
# Creo la variable aleatoria
input$aleatorio<-runif(nrow(input))
input$aleatorio2<-runif(nrow(input))
# Obtengo la importancia de las variables.
par(mfrow=c(1,2), mar=c(4.1, 14, 4.1, 2.1))
graficoVcramer(input,varObjBin, "V de Cramer para Derecha")
graficoVcramer(input,varObjCont, "V de Cramer para Izda_Pct")
par(mfrow=c(1,1))
Ya vemos que como nos barruntábamos la variable CCAA tiene una importancia muy destacada sobre el resto, nuestra agrupación no es del todo absurda ya que se mantiene en segunda lugar pero presenta una pérdida de información considerable respecto a la variable original. También debe preocuparnos la importancia del código de provincia, que a priori debería ser identificativa (nosotros la hemos usado como tal) pero por lo visto en nuestro país la influencia del entorno es muy fuerte (al menos en política). A la vista de que la variable ForeignersPtge aparece por debajo de las variables aleatorias para Derecha, y que esta variable la usé yo para generar mi agrupación de Comunidades Autónomas, voy a repetir la agrupación, mirando con un ojo la tabla y con el otro cerrado, y voy a ver genero una agrupación que sea más útil.
# Nueva agrupación
input$CCAA.grouped2<- car::recode(input$CCAA,
"c('Asturias', 'Cantabria', 'Rioja', 'Aragón', 'Galicia') = 'norteños';
c('Andalucía', 'Canarias', 'ComValenciana', 'Baleares') = 'sureños';
c('CastillaMancha','CastillaLeón', 'Extremadura', 'Murcia', 'Ceuta',
'Melilla') = 'intereños';
c('Madrid', 'Cataluña', 'PaísVasco', 'Navarra') ='pijeños'")
# Obtengo la importancia de las variables.
par(mfrow=c(1,2), mar=c(4.1, 14, 4.1, 2.1))
graficoVcramer(input,varObjBin, "V de Cramer para Derecha")
graficoVcramer(input,varObjCont, "V de Cramer para Izda_Pct")
par(mfrow=c(1,1))
# La nueva agrupación mejora a la anterior así que elimino la anterior
input$CCAA.grouped<- input$CCAA.grouped2
input$CCAA.grouped2<- NULL
Dado que la nueva agrupación ha mejorado la antigua será la que conserve. Posiblemente para generar ‘dummies’ pueda usar las Comunidades Autónomas como categorías pero su versión agrupada me será útil para introducir alguna interacción, ya que si quisiera hacer la interacción de CCAA y ActividadPpal (que parece que va a dar juego) tendría 57 combinaciones que supera el número de variables actual.
Mirando también el resto de variables resulta interesante ver que ActividadPpal y ActividadPpal.bin (que generé a partir de los ceros de las variables Industria, Hosteleria, etc.) son prácticamente igual de influyentes, incluso para la variable binaria hay mayor asociación con el factor generado por nosostros, mientras que Hosteleria, Industria, Servicios, … son variables que aparecen a la cola del gráfico.
Visto esto procede ahora ver la distribución de las variables cualitativas y las cuantitativas más significativas sobre nuestras variables objetivo, empiezo por la binaria
# Nombro los factores
factores<- c("CCAA", "ActividadPpal", "Densidad", "ActPpal.bin", "CCAA.grouped")
# Veo el efecto en forma de mosaico (nop lo muestro por no excederme)
# for(name in factores){
# mosaico_targetbinaria(input[[name]],varObjBin,name)
# }
# Y ahora en un diagrama de barras
p1<- barras_targetbinaria(input[["ActividadPpal"]],varObjBin,"ActividadPpal")
p2<- barras_targetbinaria(input[["Densidad"]],varObjBin,"Densidad")
p3<- barras_targetbinaria(input[["ActPpal.bin"]],varObjBin,"ActPpal.bin")
p4<- barras_targetbinaria(input[["CCAA.grouped"]],varObjBin,"CCAA.grouped")
gridExtra::grid.arrange(p1, p2, p3, p4, ncol=4, nrow=1)
Debo indicar que no he representado la variable CCAA porque el elevado número de valores impedía sacar alguna conclusión. En este gráfico podemos ver que la agrupación que hicimos para ActividadPpal pudo haber sido más drástica, juntando Hostelería con Const/Indud/Servi y al menos las predicciones sobre Derecha dudo que cambiasen significativamente. En el resto de casos la distribución de ceros y unos entre las categorías si parece lo suficientemente dispar, salvo entre las categorías intereños y norteños de las recién agrupadas Comunidades Autónomas, pero agrupándolas aglutinaríamos en una categoría demasiados datos. Como el efecto de tener la variable ActividadPpal como binaria parece que ya lo tenemos recogido en ActPpal.bin creo que no introduciré cambios en los datos.
Toca ahora ver la influencia de las variables cuantitativas, para ello vamos a ver si hay diferencia entre como están distribuídos los ceros y los unos de nuestra variable objetivo en las ocho (hay 33, debía elegir una muestra) variables cuantitativas que salieron más relevantes en los gráficos de la V de Cramer.
#Veo gráficamente el efecto de ocho variables cuantitativas sobre la binaria
# dput(names(Filter(is.numeric, input)))
numericas.mainbin<- c("Age_under19_Ptge", "Age_over65_pct","PersonasInmueble",
"Age_0-4_Ptge", "CodigoProvincia", "Age_19_65_pct",
"PobChange_pct", "UnemployMore40_Ptge")
p1<- boxplot_targetbinaria(input$Age_under19_Ptge,varObjBin,"Age_under19_Ptge")
p2<- boxplot_targetbinaria(input$Age_over65_pct,varObjBin,"Age_over65_pct")
p3<- boxplot_targetbinaria(input$PersonasInmueble,varObjBin,"PersonasInmueble")
p4<- boxplot_targetbinaria(input[["Age_0-4_Ptge"]],varObjBin,"Age_0-4_Ptge")
p5<- boxplot_targetbinaria(input$CodigoProvincia,varObjBin,"CodigoProvincia")
p6<- boxplot_targetbinaria(input$Age_19_65_pct,varObjBin,"Age_19_65_pct")
p7<- boxplot_targetbinaria(input$PobChange_pct,varObjBin,"PobChange_pct")
p8<- boxplot_targetbinaria(input$UnemployMore40_Ptge,varObjBin,"UnemployMore40_Ptge")
gridExtra::grid.arrange(p1, p2, p3, p4, p5, p6, p7, p8, ncol=4, nrow=2)
# Histograma para las más interesantes
p1<- hist_targetbinaria(input$Age_under19_Ptge,varObjBin,"Age_under19_Ptge")
p2<- hist_targetbinaria(input$Age_over65_pct,varObjBin,"Age_over65_pct")
p3<- hist_targetbinaria(input$PersonasInmueble,varObjBin,"PersonasInmueble")
p4<- hist_targetbinaria(input[["Age_0-4_Ptge"]],varObjBin,"Age_0-4_Ptge")
p5<- hist_targetbinaria(input$CodigoProvincia,varObjBin,"CodigoProvincia")
p6<- hist_targetbinaria(input$Age_19_65_pct,varObjBin,"Age_19_65_pct")
gridExtra::grid.arrange(p1, p2, p3, p4, p5, p6, ncol=3, nrow=2)
Podemos ver que hasta Age_19_65_pct las distribuciones son bastante diferentes y es a partir de esta variable cuando las cajas comienzan a solaparse en el mismo rango de valores. De esta forma corroboramos que al menos de esas 5 primeras variables cuantitativas podremos extraer bastante información. Con los gráficos de densidad podemos ver de forma más precisa como las distribuciones de esas 5 o 6 variables cuantitativas que encabezaban la V de Cramer tienen amplias regiones de no solapamiento. No obstante tanto el CodigoProvincia como Age_19_65_pct muestran menor poder discriminante que el resto. En el caso CódigoProvincia se deberá seguro a que es una variable en la que los números tienen un valor cualitativo y no cuantitativo, no obstante adopta length(unique(input$CodigoProvincia))
valores diferentes lo que imposibilita un tratamiento diferente.
Miro ahora el impacto de las 8 variables cuantitativas más influyentes según la V de Cramer sobre la variable objetivo contínua (Izda_Pct).
numericas.maincon<- c("UnemployLess25_Ptge", "SameComAutonDiffProvPtge","UnemployMore40_Ptge",
"AgricultureUnemploymentPtge", "Age_under19_Ptge", "Age_over65_pct",
"CodigoProvincia", "Age_0-4_Ptge")
#Principales variables numéricas frente a la objetivo continua
graficoCorrelacion(varObjCont,input[numericas.maincon])
par(mfrow=c(1,2), mar=c(4.1, 4.1, 4.1, 4.1))
corrplot(cor(cbind(varObjCont,Filter(is.numeric, input)), use="pairwise", method="pearson"), method = "ellipse",type = "upper")
corrplot(cor(cbind(varObjCont,input[numericas.maincon]), use="pairwise", method="pearson"), method = "ellipse",type = "upper")
par(mfrow=c(1,1))
De estos tres gráficos podemos extraer bastante información. El superior nos muestra como se distribuyen las variables unas en función de las otras. Tanto mirando la primera linea (donde están directamente representados los pares de puntos y una línea de tendencia) como la primera columna (donde aparece el índice de correlación lineal) podemos ver como nuestra variable objetivo no presenta una correlación fuerte con ninguna variable cuantitativa. Si se aprecia ya una tendencia fuerte entre otras variables, pero nada sorprendente ya que todas nuestras variables son medidas de edad y empleo, que son supercategorías que están además relacionadas entre sí. Estas relaciones entre variables podría conducirnos a eliminarlas, sin embargo, para ello emplearemos métodos destinados a ese fin. Esta etapa es fundamentalmente descriptiva y clave para garantizar la consistencia en la construcción del modelo.
En la pareja de gráficas inferiores vemos primero la correlación entre todas las variables. Aquí se ven los grupos relacionados con la edad y el empleo fuertemente relacionados no sólo internamente sino también entre sí. En segundo lugar vemos como según vamos avanzando en la primera fila el color de las variables va perdiendo fuerza, corroborando este gráfico la información extraida de la V de Cramer (las variables están ordenadas).
Toca por fin elavorar los modelos predictivos sobre nuestros datos, ya perfectamente preparados. La idea es elaborar múltiples modelos que vayan ganando complejidad e ir viendo que variables son las que tienen mayor impacto, para acabar teniendo un modelo lo más competitivo posible.
En primer lugar vamos a enfocarnos en la variable contínua, lo primero que hacemos es cargar los datos (sin las transformaciones) y elaborar un primer modelo con todas las variables que nos sirva como tanteo.
Elaboro los primeros modelos con todas las variables. Para evitar la multicolinealidad pruebo con las generadas por mí en el proceso de depuración y exploración y con las originales.
#Obtengo la partición
set.seed(123456)
names(input)[names(input) == "Age_0-4_Ptge"] <- "Age_0_4_Ptge"
todo<-data.frame(input,varObjCont)
trainIndex <- createDataPartition(todo$varObjCont, p=0.8, list=FALSE)
data_train <- todo[trainIndex,]
data_test <- todo[-trainIndex,]
#Construyo un modelo preliminar con todas las variables
data_train <- todo[trainIndex,-c(34,35)]
data_test <- todo[-trainIndex,-c(34,35)]
modelo1<-lm(varObjCont~.,data=data_train)
summary(modelo1)
##
## Call:
## lm(formula = varObjCont ~ ., data = data_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -40.854 -5.823 -0.339 5.533 52.757
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.897e+01 7.964e+00 2.382 0.017259 *
## CodigoProvincia 2.140e-02 9.702e-03 2.206 0.027426 *
## CCAAAragón -1.114e+01 6.965e-01 -15.999 < 2e-16 ***
## CCAAAsturias -5.164e+00 1.364e+00 -3.785 0.000155 ***
## CCAABaleares -1.027e+01 1.459e+00 -7.037 2.17e-12 ***
## CCAACanarias -1.517e+01 1.327e+00 -11.431 < 2e-16 ***
## CCAACantabria -1.790e+01 1.247e+00 -14.351 < 2e-16 ***
## CCAACastillaLeón -1.966e+01 5.747e-01 -34.212 < 2e-16 ***
## CCAACastillaMancha -1.199e+01 6.394e-01 -18.754 < 2e-16 ***
## CCAACataluña -4.330e+01 6.428e-01 -67.371 < 2e-16 ***
## CCAACeuta -2.209e+01 1.003e+01 -2.202 0.027691 *
## CCAAComValenciana -3.154e+01 6.908e-01 -45.663 < 2e-16 ***
## CCAAExtremadura -3.666e+00 7.325e-01 -5.004 5.76e-07 ***
## CCAAGalicia -3.118e+01 8.062e-01 -38.670 < 2e-16 ***
## CCAAMadrid -1.651e+01 1.024e+00 -16.116 < 2e-16 ***
## CCAAMelilla -1.842e+01 1.003e+01 -1.836 0.066407 .
## CCAAMurcia -1.773e+01 1.779e+00 -9.970 < 2e-16 ***
## CCAANavarra -1.348e+01 8.745e-01 -15.411 < 2e-16 ***
## CCAAPaísVasco -2.267e+01 8.757e-01 -25.892 < 2e-16 ***
## CCAARioja -1.602e+01 1.068e+00 -15.000 < 2e-16 ***
## Population -9.015e-05 1.558e-04 -0.579 0.562759
## TotalCensus 4.730e-04 1.945e-04 2.432 0.015040 *
## Age_0_4_Ptge -3.556e-01 1.241e-01 -2.864 0.004193 **
## Age_under19_Ptge 1.173e-01 8.738e-02 1.343 0.179459
## Age_19_65_pct 2.984e-01 7.676e-02 3.887 0.000102 ***
## Age_over65_pct 7.389e-02 7.461e-02 0.990 0.322036
## WomanPopulationPtge 1.629e-01 3.696e-02 4.408 1.06e-05 ***
## ForeignersPtge -1.013e-01 2.825e-02 -3.585 0.000340 ***
## SameComAutonPtge -7.710e-03 2.153e-02 -0.358 0.720299
## SameComAutonDiffProvPtge -1.263e-03 3.199e-02 -0.039 0.968516
## DifComAutonPtge 2.528e-01 2.772e-02 9.120 < 2e-16 ***
## UnemployLess25_Ptge 8.431e-02 1.874e-02 4.500 6.92e-06 ***
## Unemploy25_40_Ptge 1.516e-02 1.049e-02 1.444 0.148681
## UnemployMore40_Ptge 1.645e-02 9.885e-03 1.664 0.096146 .
## AgricultureUnemploymentPtge 1.145e-01 1.688e-02 6.786 1.26e-11 ***
## IndustryUnemploymentPtge 4.655e-02 1.519e-02 3.065 0.002189 **
## ConstructionUnemploymentPtge 5.959e-02 1.363e-02 4.373 1.25e-05 ***
## ServicesUnemploymentPtge 3.285e-02 8.874e-03 3.702 0.000216 ***
## totalEmpresas -3.284e-03 2.112e-03 -1.555 0.120045
## Industria -1.908e-03 1.535e-02 -0.124 0.901036
## Construccion -3.014e-02 9.730e-03 -3.098 0.001956 **
## Hosteleria -3.753e-03 4.561e-03 -0.823 0.410617
## Servicios -2.559e-03 6.020e-03 -0.425 0.670759
## ActividadPpalHosteleria 2.282e+00 5.433e-01 4.199 2.71e-05 ***
## ActividadPpalOtro -1.016e+00 6.947e-01 -1.462 0.143767
## inmuebles 2.953e-04 1.886e-04 1.566 0.117370
## Pob2010 2.584e-05 1.552e-04 0.166 0.867791
## SUPERFICIE 4.304e-05 2.917e-05 1.476 0.140078
## DensidadBaja -7.591e-01 4.884e-01 -1.554 0.120167
## PobChange_pct -1.030e-02 1.570e-02 -0.656 0.511538
## PersonasInmueble -2.355e-01 3.806e-01 -0.619 0.536034
## Explotaciones 1.963e-03 1.675e-03 1.172 0.241348
## prop_missings -7.786e+00 2.426e+00 -3.210 0.001336 **
## aleatorio -6.894e-01 4.314e-01 -1.598 0.110081
## aleatorio2 1.706e-01 4.305e-01 0.396 0.691941
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 9.969 on 6442 degrees of freedom
## Multiple R-squared: 0.6346, Adjusted R-squared: 0.6316
## F-statistic: 207.2 on 54 and 6442 DF, p-value: < 2.2e-16
Rsq(modelo1,"varObjCont",data_test)
## [1] 0.6335737
# Pruebo con las variables generadas por mí
data_train <- todo[trainIndex, -c(22:25, 2)]
data_test <- todo[-trainIndex, -c(22:25, 2)]
modelo2<-lm(varObjCont~.,data=data_train)
summary(modelo2)
##
## Call:
## lm(formula = varObjCont ~ ., data = data_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -42.085 -9.764 -0.586 8.828 59.558
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.049e+01 1.224e+01 -2.492 0.01274 *
## CodigoProvincia 1.219e-02 1.183e-02 1.030 0.30306
## Population -1.082e-04 2.078e-04 -0.520 0.60276
## TotalCensus 2.960e-05 2.577e-04 0.115 0.90856
## Age_0_4_Ptge -5.066e-01 1.663e-01 -3.047 0.00232 **
## Age_under19_Ptge 4.623e-01 1.165e-01 3.967 7.37e-05 ***
## Age_19_65_pct 4.164e-01 1.032e-01 4.036 5.51e-05 ***
## Age_over65_pct 1.533e-01 1.003e-01 1.529 0.12628
## WomanPopulationPtge 9.212e-02 4.899e-02 1.880 0.06009 .
## ForeignersPtge -1.801e-01 3.733e-02 -4.823 1.44e-06 ***
## SameComAutonPtge 7.846e-02 2.837e-02 2.766 0.00569 **
## SameComAutonDiffProvPtge -5.054e-01 3.865e-02 -13.076 < 2e-16 ***
## DifComAutonPtge 4.649e-01 3.646e-02 12.752 < 2e-16 ***
## UnemployLess25_Ptge 2.960e-01 2.477e-02 11.946 < 2e-16 ***
## Unemploy25_40_Ptge 3.833e-02 1.405e-02 2.729 0.00638 **
## UnemployMore40_Ptge -2.670e-03 1.324e-02 -0.202 0.84024
## AgricultureUnemploymentPtge 2.118e-01 2.227e-02 9.509 < 2e-16 ***
## IndustryUnemploymentPtge -1.006e-01 2.002e-02 -5.024 5.19e-07 ***
## ConstructionUnemploymentPtge 7.826e-02 1.814e-02 4.313 1.63e-05 ***
## ServicesUnemploymentPtge 1.241e-02 1.182e-02 1.050 0.29385
## totalEmpresas -6.189e-03 2.496e-03 -2.480 0.01317 *
## ActividadPpalHosteleria 4.941e+00 7.116e-01 6.944 4.17e-12 ***
## ActividadPpalOtro 1.279e+01 6.113e+00 2.093 0.03638 *
## inmuebles 4.285e-04 2.467e-04 1.737 0.08239 .
## Pob2010 4.358e-05 2.067e-04 0.211 0.83298
## SUPERFICIE 2.412e-04 3.859e-05 6.250 4.37e-10 ***
## DensidadBaja 1.334e+00 6.504e-01 2.051 0.04029 *
## PobChange_pct 6.298e-03 2.100e-02 0.300 0.76430
## PersonasInmueble 4.608e-01 5.057e-01 0.911 0.36220
## Explotaciones 1.460e-03 2.213e-03 0.660 0.50946
## ActPpal.bin1 9.581e+00 6.116e+00 1.566 0.11729
## CCAA.groupednorteños 3.222e-01 5.024e-01 0.641 0.52130
## CCAA.groupedpijeños -1.372e+01 5.572e-01 -24.624 < 2e-16 ***
## CCAA.groupedsureños 2.740e+00 5.409e-01 5.066 4.17e-07 ***
## prop_missings -7.114e+00 3.208e+00 -2.217 0.02663 *
## aleatorio -3.434e-01 5.793e-01 -0.593 0.55335
## aleatorio2 -3.242e-03 5.782e-01 -0.006 0.99553
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 13.41 on 6460 degrees of freedom
## Multiple R-squared: 0.3374, Adjusted R-squared: 0.3337
## F-statistic: 91.39 on 36 and 6460 DF, p-value: < 2.2e-16
Rsq(modelo2,"varObjCont",data_test)
## [1] 0.3419729
# Nos fijamos en la importancia de las variables. Podemos sacar un gráfico que muestra lo que se pierde en R2 en train al quitarlas del modelomodelEffectSizes(modelo2)
par(mfrow=c(1,2), mar=c(4.1, 14.1, 4.1, 6.1))
barplot(sort(modelEffectSizes(modelo1)$Effects[-1,4],decreasing =T),horiz=T,las=2,main="Importancia de las variables (R2)")
## lm(formula = varObjCont ~ ., data = data_train)
##
## Coefficients
## SSR df pEta-sqr dR-sqr
## (Intercept) 563.8159 1 0.0009 NA
## CodigoProvincia 483.6273 1 0.0008 0.0003
## CCAA 671787.9965 18 0.5120 0.3833
## Population 33.2938 1 0.0001 0.0000
## TotalCensus 587.8858 1 0.0009 0.0003
## Age_0_4_Ptge 815.4237 1 0.0013 0.0005
## Age_under19_Ptge 179.1482 1 0.0003 0.0001
## Age_19_65_pct 1501.6910 1 0.0023 0.0009
## Age_over65_pct 97.4819 1 0.0002 0.0001
## WomanPopulationPtge 1930.8135 1 0.0030 0.0011
## ForeignersPtge 1277.3175 1 0.0020 0.0007
## SameComAutonPtge 12.7434 1 0.0000 0.0000
## SameComAutonDiffProvPtge 0.1548 1 0.0000 0.0000
## DifComAutonPtge 8267.3733 1 0.0127 0.0047
## UnemployLess25_Ptge 2012.4035 1 0.0031 0.0011
## Unemploy25_40_Ptge 207.3490 1 0.0003 0.0001
## UnemployMore40_Ptge 275.2233 1 0.0004 0.0002
## AgricultureUnemploymentPtge 4576.9445 1 0.0071 0.0026
## IndustryUnemploymentPtge 933.4113 1 0.0015 0.0005
## ConstructionUnemploymentPtge 1900.6025 1 0.0030 0.0011
## ServicesUnemploymentPtge 1362.1709 1 0.0021 0.0008
## totalEmpresas 240.2615 1 0.0004 0.0001
## Industria 1.5370 1 0.0000 0.0000
## Construccion 953.9576 1 0.0015 0.0005
## Hosteleria 67.2968 1 0.0001 0.0000
## Servicios 17.9628 1 0.0000 0.0000
## ActividadPpal 4908.2890 2 0.0076 0.0028
## inmuebles 243.7747 1 0.0004 0.0001
## Pob2010 2.7544 1 0.0000 0.0000
## SUPERFICIE 216.4345 1 0.0003 0.0001
## Densidad 240.1032 1 0.0004 0.0001
## PobChange_pct 42.8336 1 0.0001 0.0000
## PersonasInmueble 38.0643 1 0.0001 0.0000
## Explotaciones 136.4574 1 0.0002 0.0001
## prop_missings 1023.8263 1 0.0016 0.0006
## aleatorio 253.8170 1 0.0004 0.0001
## aleatorio2 15.6048 1 0.0000 0.0000
##
## Sum of squared errors (SSE): 640266.4
## Sum of squared total (SST): 1752458.9
barplot(sort(modelEffectSizes(modelo2)$Effects[-1,4],decreasing =T),horiz=T,las=2,main="Importancia de las variables (R2)")
## lm(formula = varObjCont ~ ., data = data_train)
##
## Coefficients
## SSR df pEta-sqr dR-sqr
## (Intercept) 1115.8805 1 0.0010 NA
## CodigoProvincia 190.6820 1 0.0002 0.0001
## Population 48.6898 1 0.0000 0.0000
## TotalCensus 2.3714 1 0.0000 0.0000
## Age_0_4_Ptge 1668.7240 1 0.0014 0.0010
## Age_under19_Ptge 2828.0957 1 0.0024 0.0016
## Age_19_65_pct 2927.4973 1 0.0025 0.0017
## Age_over65_pct 420.2711 1 0.0004 0.0002
## WomanPopulationPtge 635.5771 1 0.0005 0.0004
## ForeignersPtge 4181.8396 1 0.0036 0.0024
## SameComAutonPtge 1375.2438 1 0.0012 0.0008
## SameComAutonDiffProvPtge 30732.3158 1 0.0258 0.0175
## DifComAutonPtge 29229.2950 1 0.0246 0.0167
## UnemployLess25_Ptge 25652.4178 1 0.0216 0.0146
## Unemploy25_40_Ptge 1338.2407 1 0.0012 0.0008
## UnemployMore40_Ptge 7.3046 1 0.0000 0.0000
## AgricultureUnemploymentPtge 16253.2594 1 0.0138 0.0093
## IndustryUnemploymentPtge 4537.1402 1 0.0039 0.0026
## ConstructionUnemploymentPtge 3343.6338 1 0.0029 0.0019
## ServicesUnemploymentPtge 198.0928 1 0.0002 0.0001
## totalEmpresas 1105.2863 1 0.0010 0.0006
## ActividadPpal 9080.7903 2 0.0078 0.0052
## inmuebles 542.4684 1 0.0005 0.0003
## Pob2010 7.9937 1 0.0000 0.0000
## SUPERFICIE 7021.1868 1 0.0060 0.0040
## Densidad 756.2107 1 0.0007 0.0004
## PobChange_pct 16.1604 1 0.0000 0.0000
## PersonasInmueble 149.2516 1 0.0001 0.0001
## Explotaciones 78.2298 1 0.0001 0.0000
## ActPpal.bin 441.0395 1 0.0004 0.0003
## CCAA.grouped 153925.5690 3 0.1170 0.0878
## prop_missings 883.7963 1 0.0008 0.0005
## aleatorio 63.1577 1 0.0001 0.0000
## aleatorio2 0.0057 1 0.0000 0.0000
##
## Sum of squared errors (SSE): 1161132.8
## Sum of squared total (SST): 1752458.9
par(mfrow=c(1,1))
data_train<- todo[trainIndex, -c(34,35)]
data_test<- todo[-trainIndex, -c(34,35)]
Bueno aquí podemos observar que la pérdida de información para la regresión con las variables generadas por mí a lo largo del proceso es excesiva. El \(R^2\) pasa a ser prácticamente la mitad ya que la importancia de CCAA con respecto al resto es altísima y seguramente al avanzar veamos como es prácticamente la variable que explica en mayor medida los resultados. De ahora en adelante el proceso en continuará con las variables originales, iré intentando mejorar el desempeño del modelo y reducir el número de variables implicadas. Debo comentar que los valores de \(R^2\) sobre los datos train y test es muy similar, así que en este sentido y pese a haber implicado una cantidad muy elevada de variables no hemos sobreajustado el modelo.
Pruebo ahora con algunos modelos cuyas configuraciones creo que pueden ser competitivas.
#Pruebo un modelo con menos variables. Sobreescribo el modelo2 anterior
cramer.con<- c("CCAA", "ActividadPpal", "UnemployLess25_Ptge", "SameComAutonDiffProvPtge",
"UnemployMore40_Ptge", "AgricultureUnemploymentPtge", "Age_under19_Ptge",
"Age_over65_pct", "CodigoProvincia", "Age_0_4_Ptge")
frml<- as.formula(paste("varObjCont", paste(cramer.con, collapse="+"), sep="~"))
modelo2<-lm(frml, data=data_train)
summary(modelo2)
##
## Call:
## lm(formula = frml, data = data_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -51.200 -5.966 -0.435 5.834 57.987
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 57.614475 1.376176 41.866 < 2e-16 ***
## CCAAAragón -9.867380 0.676436 -14.587 < 2e-16 ***
## CCAAAsturias -3.817137 1.388471 -2.749 0.00599 **
## CCAABaleares -9.065714 1.472604 -6.156 7.90e-10 ***
## CCAACanarias -15.697205 1.342980 -11.688 < 2e-16 ***
## CCAACantabria -15.951512 1.267625 -12.584 < 2e-16 ***
## CCAACastillaLeón -19.211423 0.565147 -33.994 < 2e-16 ***
## CCAACastillaMancha -9.475128 0.593772 -15.958 < 2e-16 ***
## CCAACataluña -42.922112 0.614327 -69.868 < 2e-16 ***
## CCAACeuta -22.620147 10.254456 -2.206 0.02743 *
## CCAAComValenciana -30.692838 0.668067 -45.943 < 2e-16 ***
## CCAAExtremadura -1.813571 0.736126 -2.464 0.01378 *
## CCAAGalicia -30.591377 0.809948 -37.770 < 2e-16 ***
## CCAAMadrid -15.128887 1.019338 -14.842 < 2e-16 ***
## CCAAMelilla -20.970561 10.258337 -2.044 0.04097 *
## CCAAMurcia -18.799859 1.792784 -10.486 < 2e-16 ***
## CCAANavarra -11.961098 0.852148 -14.036 < 2e-16 ***
## CCAAPaísVasco -21.366642 0.857971 -24.904 < 2e-16 ***
## CCAARioja -14.450775 1.045415 -13.823 < 2e-16 ***
## ActividadPpalHosteleria 2.104048 0.534064 3.940 8.24e-05 ***
## ActividadPpalOtro -0.892443 0.571823 -1.561 0.11864
## UnemployLess25_Ptge 0.096167 0.018022 5.336 9.82e-08 ***
## SameComAutonDiffProvPtge -0.014498 0.032493 -0.446 0.65549
## UnemployMore40_Ptge 0.036224 0.005770 6.278 3.65e-10 ***
## AgricultureUnemploymentPtge 0.069474 0.014638 4.746 2.12e-06 ***
## Age_under19_Ptge -0.096835 0.050322 -1.924 0.05436 .
## Age_over65_pct -0.219831 0.022218 -9.894 < 2e-16 ***
## CodigoProvincia 0.017399 0.009871 1.763 0.07800 .
## Age_0_4_Ptge -0.380630 0.123252 -3.088 0.00202 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 10.24 on 6468 degrees of freedom
## Multiple R-squared: 0.6133, Adjusted R-squared: 0.6117
## F-statistic: 366.4 on 28 and 6468 DF, p-value: < 2.2e-16
Rsq(modelo2,"varObjCont",data_test)
## [1] 0.6129429
#Pruebo un modelo con (más o menos) la mitad de variables, basánndome en la importancia su variables
impor.con<- c("CCAA", "DifComAutonPtge", "ActividadPpal", "AgricultureUnemploymentPtge",
"UnemployLess25_Ptge", "ConstructionUnemploymentPtge")
frml<- as.formula(paste("varObjCont", paste(impor.con, collapse="+"), sep="~"))
modelo3<-lm(frml,data=data_train)
summary(modelo3)
##
## Call:
## lm(formula = frml, data = data_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -44.112 -5.776 -0.288 5.690 52.765
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 48.44473 0.71481 67.773 < 2e-16 ***
## CCAAAragón -11.76531 0.64896 -18.130 < 2e-16 ***
## CCAAAsturias -4.55315 1.35343 -3.364 0.000772 ***
## CCAABaleares -11.37601 1.45658 -7.810 6.62e-15 ***
## CCAACanarias -13.98393 1.31393 -10.643 < 2e-16 ***
## CCAACantabria -17.06383 1.23402 -13.828 < 2e-16 ***
## CCAACastillaLeón -20.39346 0.53460 -38.147 < 2e-16 ***
## CCAACastillaMancha -13.06049 0.61680 -21.175 < 2e-16 ***
## CCAACataluña -43.37001 0.59761 -72.573 < 2e-16 ***
## CCAACeuta -25.30136 10.17395 -2.487 0.012912 *
## CCAAComValenciana -31.32625 0.66364 -47.204 < 2e-16 ***
## CCAAExtremadura -3.56423 0.71695 -4.971 6.82e-07 ***
## CCAAGalicia -30.76833 0.77384 -39.761 < 2e-16 ***
## CCAAMadrid -16.62150 1.00256 -16.579 < 2e-16 ***
## CCAAMelilla -23.22358 10.17251 -2.283 0.022464 *
## CCAAMurcia -19.03084 1.77026 -10.750 < 2e-16 ***
## CCAANavarra -13.44646 0.83724 -16.060 < 2e-16 ***
## CCAAPaísVasco -22.65009 0.84680 -26.748 < 2e-16 ***
## CCAARioja -17.06323 1.04175 -16.379 < 2e-16 ***
## DifComAutonPtge 0.27327 0.01795 15.225 < 2e-16 ***
## ActividadPpalHosteleria 2.54639 0.52902 4.813 1.52e-06 ***
## ActividadPpalOtro -0.96821 0.52059 -1.860 0.062952 .
## AgricultureUnemploymentPtge 0.10643 0.01460 7.292 3.43e-13 ***
## UnemployLess25_Ptge 0.10612 0.01748 6.070 1.35e-09 ***
## ConstructionUnemploymentPtge 0.05272 0.01138 4.631 3.70e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 10.16 on 6472 degrees of freedom
## Multiple R-squared: 0.6188, Adjusted R-squared: 0.6174
## F-statistic: 437.7 on 24 and 6472 DF, p-value: < 2.2e-16
Rsq(modelo3,"varObjCont",data_test)
## [1] 0.6230918
#Pruebo con una interaccion sobre el anterior
inter1.con<- c("CCAA", "DifComAutonPtge", "ActividadPpal", "AgricultureUnemploymentPtge",
"UnemployLess25_Ptge", "ConstructionUnemploymentPtge", "CCAA:ActividadPpal")
frml<- as.formula(paste("varObjCont", paste(inter1.con, collapse="+"), sep="~"))
modelo4<-lm(frml,data=data_train)
summary(modelo4)
##
## Call:
## lm(formula = frml, data = data_train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -43.277 -5.553 -0.245 5.492 51.679
##
## Coefficients: (4 not defined because of singularities)
## Estimate Std. Error t value
## (Intercept) 41.97278 1.64922 25.450
## CCAAAragón -2.96408 3.23078 -0.917
## CCAAAsturias 1.44578 6.02670 0.240
## CCAABaleares -1.67458 2.44043 -0.686
## CCAACanarias -4.30085 3.72552 -1.154
## CCAACantabria -8.18989 4.41706 -1.854
## CCAACastillaLeón -10.51932 2.32229 -4.530
## CCAACastillaMancha -9.51406 2.59754 -3.663
## CCAACataluña -35.09041 1.81056 -19.381
## CCAACeuta -25.11012 10.06585 -2.495
## CCAAComValenciana -26.84497 2.00800 -13.369
## CCAAExtremadura -7.96741 5.28333 -1.508
## CCAAGalicia -21.85057 2.69293 -8.114
## CCAAMadrid -12.46682 2.09441 -5.952
## CCAAMelilla -23.09025 10.06438 -2.294
## CCAAMurcia -13.31971 6.02611 -2.210
## CCAANavarra -2.47639 3.23359 -0.766
## CCAAPaísVasco -10.34221 2.73537 -3.781
## CCAARioja -10.29323 5.28952 -1.946
## DifComAutonPtge 0.25377 0.01806 14.052
## ActividadPpalHosteleria 9.28927 1.71370 5.421
## ActividadPpalOtro 7.36130 1.81019 4.067
## AgricultureUnemploymentPtge 0.09885 0.01458 6.780
## UnemployLess25_Ptge 0.10170 0.01734 5.864
## ConstructionUnemploymentPtge 0.05128 0.01133 4.525
## CCAAAragón:ActividadPpalHosteleria -7.77634 3.48909 -2.229
## CCAAAsturias:ActividadPpalHosteleria -7.20352 6.23227 -1.156
## CCAABaleares:ActividadPpalHosteleria -12.61596 3.31600 -3.805
## CCAACanarias:ActividadPpalHosteleria -10.24630 3.98499 -2.571
## CCAACantabria:ActividadPpalHosteleria -10.36316 4.70154 -2.204
## CCAACastillaLeón:ActividadPpalHosteleria -5.75374 2.50478 -2.297
## CCAACastillaMancha:ActividadPpalHosteleria -4.74443 2.72365 -1.742
## CCAACataluña:ActividadPpalHosteleria -8.15664 2.00743 -4.063
## CCAACeuta:ActividadPpalHosteleria NA NA NA
## CCAAComValenciana:ActividadPpalHosteleria -6.28080 2.19614 -2.860
## CCAAExtremadura:ActividadPpalHosteleria 3.59381 5.37661 0.668
## CCAAGalicia:ActividadPpalHosteleria -9.78888 2.82434 -3.466
## CCAAMadrid:ActividadPpalHosteleria -3.65886 2.63779 -1.387
## CCAAMelilla:ActividadPpalHosteleria NA NA NA
## CCAAMurcia:ActividadPpalHosteleria -5.36389 6.31863 -0.849
## CCAANavarra:ActividadPpalHosteleria -9.36800 3.54165 -2.645
## CCAAPaísVasco:ActividadPpalHosteleria -9.36853 2.94701 -3.179
## CCAARioja:ActividadPpalHosteleria -5.72642 5.83891 -0.981
## CCAAAragón:ActividadPpalOtro -10.51847 3.35723 -3.133
## CCAAAsturias:ActividadPpalOtro -3.88546 6.60659 -0.588
## CCAABaleares:ActividadPpalOtro -17.10590 5.64084 -3.033
## CCAACanarias:ActividadPpalOtro -10.39324 10.74436 -0.967
## CCAACantabria:ActividadPpalOtro -8.61198 4.84419 -1.778
## CCAACastillaLeón:ActividadPpalOtro -11.96851 2.46414 -4.857
## CCAACastillaMancha:ActividadPpalOtro -4.19563 2.74249 -1.530
## CCAACataluña:ActividadPpalOtro -10.58630 2.03982 -5.190
## CCAACeuta:ActividadPpalOtro NA NA NA
## CCAAComValenciana:ActividadPpalOtro -3.04611 2.28846 -1.331
## CCAAExtremadura:ActividadPpalOtro 3.84766 5.39260 0.714
## CCAAGalicia:ActividadPpalOtro -5.48262 3.49935 -1.567
## CCAAMadrid:ActividadPpalOtro -1.68920 2.77357 -0.609
## CCAAMelilla:ActividadPpalOtro NA NA NA
## CCAAMurcia:ActividadPpalOtro -10.05774 9.35140 -1.076
## CCAANavarra:ActividadPpalOtro -13.37857 3.42157 -3.910
## CCAAPaísVasco:ActividadPpalOtro -19.13164 3.05608 -6.260
## CCAARioja:ActividadPpalOtro -8.35738 5.43095 -1.539
## Pr(>|t|)
## (Intercept) < 2e-16 ***
## CCAAAragón 0.358941
## CCAAAsturias 0.810418
## CCAABaleares 0.492622
## CCAACanarias 0.248368
## CCAACantabria 0.063764 .
## CCAACastillaLeón 6.01e-06 ***
## CCAACastillaMancha 0.000252 ***
## CCAACataluña < 2e-16 ***
## CCAACeuta 0.012635 *
## CCAAComValenciana < 2e-16 ***
## CCAAExtremadura 0.131596
## CCAAGalicia 5.82e-16 ***
## CCAAMadrid 2.78e-09 ***
## CCAAMelilla 0.021808 *
## CCAAMurcia 0.027117 *
## CCAANavarra 0.443803
## CCAAPaísVasco 0.000158 ***
## CCAARioja 0.051702 .
## DifComAutonPtge < 2e-16 ***
## ActividadPpalHosteleria 6.16e-08 ***
## ActividadPpalOtro 4.83e-05 ***
## AgricultureUnemploymentPtge 1.31e-11 ***
## UnemployLess25_Ptge 4.76e-09 ***
## ConstructionUnemploymentPtge 6.15e-06 ***
## CCAAAragón:ActividadPpalHosteleria 0.025864 *
## CCAAAsturias:ActividadPpalHosteleria 0.247789
## CCAABaleares:ActividadPpalHosteleria 0.000143 ***
## CCAACanarias:ActividadPpalHosteleria 0.010156 *
## CCAACantabria:ActividadPpalHosteleria 0.027545 *
## CCAACastillaLeón:ActividadPpalHosteleria 0.021645 *
## CCAACastillaMancha:ActividadPpalHosteleria 0.081567 .
## CCAACataluña:ActividadPpalHosteleria 4.90e-05 ***
## CCAACeuta:ActividadPpalHosteleria NA
## CCAAComValenciana:ActividadPpalHosteleria 0.004251 **
## CCAAExtremadura:ActividadPpalHosteleria 0.503892
## CCAAGalicia:ActividadPpalHosteleria 0.000532 ***
## CCAAMadrid:ActividadPpalHosteleria 0.165462
## CCAAMelilla:ActividadPpalHosteleria NA
## CCAAMurcia:ActividadPpalHosteleria 0.395968
## CCAANavarra:ActividadPpalHosteleria 0.008187 **
## CCAAPaísVasco:ActividadPpalHosteleria 0.001485 **
## CCAARioja:ActividadPpalHosteleria 0.326761
## CCAAAragón:ActividadPpalOtro 0.001738 **
## CCAAAsturias:ActividadPpalOtro 0.556473
## CCAABaleares:ActividadPpalOtro 0.002435 **
## CCAACanarias:ActividadPpalOtro 0.333420
## CCAACantabria:ActividadPpalOtro 0.075485 .
## CCAACastillaLeón:ActividadPpalOtro 1.22e-06 ***
## CCAACastillaMancha:ActividadPpalOtro 0.126100
## CCAACataluña:ActividadPpalOtro 2.17e-07 ***
## CCAACeuta:ActividadPpalOtro NA
## CCAAComValenciana:ActividadPpalOtro 0.183212
## CCAAExtremadura:ActividadPpalOtro 0.475557
## CCAAGalicia:ActividadPpalOtro 0.117222
## CCAAMadrid:ActividadPpalOtro 0.542524
## CCAAMelilla:ActividadPpalOtro NA
## CCAAMurcia:ActividadPpalOtro 0.282176
## CCAANavarra:ActividadPpalOtro 9.32e-05 ***
## CCAAPaísVasco:ActividadPpalOtro 4.09e-10 ***
## CCAARioja:ActividadPpalOtro 0.123892
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 10.05 on 6440 degrees of freedom
## Multiple R-squared: 0.629, Adjusted R-squared: 0.6258
## F-statistic: 195 on 56 and 6440 DF, p-value: < 2.2e-16
Rsq(modelo4,"varObjCont",data_test)
## [1] 0.6281302
El segundo (que reemplaza al modelo fallido con las variables imputadas) lo he definido mirando la importancia de las variables en el gráfico de la V de Cramer y seleccionando las 10 variables más relevantes, el tercero siguiendo los gráficos de relevancia de las variables según \(R^2\) para el primer modelo y seleccionando las 5 más importantes y el cuarto definiendo una interacción adicional entre las dos variables cualitativas (CCAA y ActividadPpal) involucradas en el tercer modelo. Mirando el summary de cada modelo podemos ver que en el segundo hay varias variables poco significativas, lo que nos indica que uno no debe sobrestimar el poder descriptivo de la V de Cramer. En el tercero prácticamente todas tienen una significación alta, salvo alguna de las ‘dummies’. En el último la interacción ha introducido muchas variables y vuelve a aumentar el número de variables poco significativas. Si miramos el valor de \(R^2\) podemos ver que la variación entre los modelos se mueve en una franja inferior a 30 milésimas.
Hago validación cruzada sobre los modelos para seleccionar el más competitivo.
# Hago validación repetida para ver qué modelo es mejor
modelo1VC <- train(formula(modelo1),
data = todo,method = "lm",
trControl = trainControl(method="repeatedcv", number=5, repeats=20, returnResamp="all")
)
modelo2VC <- train(formula(modelo2),
data = todo,method = "lm",
trControl = trainControl(method="repeatedcv", number=5, repeats=20, returnResamp="all")
)
modelo3VC <- train(formula(modelo3),
data = todo,method = "lm",
trControl = trainControl(method="repeatedcv", number=5, repeats=20, returnResamp="all")
)
modelo4VC <- train(formula(modelo4),
data = todo,method = "lm",
trControl = trainControl(method="repeatedcv", number=5, repeats=20, returnResamp="all")
)
results<-data.frame(rbind(modelo1VC$resample,modelo2VC$resample,modelo3VC$resample,modelo4VC$resample),modelo=c(rep(1,100),rep(2,100),rep(3,100),rep(4,100)))
comparativa<- data.frame(row.names = c("modelo1", "modelo2", "modelo3", "modelo4"))
comparativa$mean_R2<- aggregate(Rsquared~modelo, data = results, mean)$Rsquared
comparativa$std_R2<- aggregate(Rsquared~modelo, data = results, sd)$Rsquared
comparativa$variables<- c(length(coef(modelo1)), length(coef(modelo2)), length(coef(modelo3)),
length(coef(modelo4)))
comparativa$test_R2<- c(Rsq(modelo1,"varObjCont",data_test), Rsq(modelo2,"varObjCont",data_test),
Rsq(modelo3,"varObjCont",data_test), Rsq(modelo4,"varObjCont",data_test))
# Elijo el modelo 3 por el bajo número de variables y la escasa diferencia con el R2 de los demás
mean_R2 | std_R2 | variables | test_R2 | |
---|---|---|---|---|
modelo1 | 0,629 | 0,014 | 55 | 0,634 |
modelo2 | 0,611 | 0,014 | 29 | 0,613 |
modelo3 | 0,617 | 0,013 | 25 | 0,623 |
modelo4 | 0,625 | 0,013 | 61 | 0,628 |
## lm(formula = frml, data = data_train)
##
## Coefficients
## SSR df pEta-sqr dR-sqr
## (Intercept) 474126.578 1 0.4151 NA
## CCAA 827203.600 18 0.5532 0.4720
## DifComAutonPtge 23928.201 1 0.0346 0.0137
## ActividadPpal 11867.188 2 0.0175 0.0068
## AgricultureUnemploymentPtge 5488.217 1 0.0081 0.0031
## UnemployLess25_Ptge 3803.520 1 0.0057 0.0022
## ConstructionUnemploymentPtge 2214.045 1 0.0033 0.0013
##
## Sum of squared errors (SSE): 668059.8
## Sum of squared total (SST): 1752458.9
La validación cruzada sobre estos modelos construidos a mano nos permite ver que los resultados se mueven ya en una franja bastante estrecha. Pese a que el mejor en cuanto a \(R^2\) es el que hemos construído con todas las variables su número de variables es muy elevado con respecto al resto. Para mi gusto el más competitivo es el tercer modelo, construído eligiendo las 6 variables más significativas del modelo que las contenía todas, ya que con tan solo 25 permite un ajuste prácticamente igual de bueno que el del resto.
Llegado este punto vamos a buscar en las variables las transformaciones fundamentales que puedan mejorar la predicción de las variables objetivos. Como las transformaciones no serán comunes a ambas variables a partir de aqui separaremos los datos que emplearemos para cada la predicción de cada variable objetivo.
input <- input[, -c(34,35)]
input_cont<-cbind(input,Transf_Auto(Filter(is.numeric, input[,-c(35,36)]),varObjCont))
input_bin<-cbind(input,Transf_Auto(Filter(is.numeric, input[,-c(35,36)]),varObjBin))
saveRDS(data.frame(input, varObjBin, varObjCont),"todoNoTrans")
saveRDS(data.frame(input_bin,varObjBin),"todo_bin")
saveRDS(data.frame(input_cont,varObjCont),"todo_cont")
saveRDS(modelo3, 'modeloManual')
saveRDS(modelo1, 'modeloFull')
Ahora voy a emplear los métodos de selección de variables estudiados en clase, aunque usaré de forma predominante el Stepwise, probaremos también con Lasso y un un método consistente en la incorporación al azar de una submuestra de nuestros datos sobre la que aplicar el método Stepwise (aquí se ha comentado debido al tiempo de ejecución, en el código aparece sin comentar y lo ejecuté para obtener las fórmulas de los modelos aleatorios). Para elegir el mejor modelo usaremos los criterios de información también vistos: \[ \text{Akaike: }n\ln\left(\frac{SSE}{n}\right) + 2 \cdot p\\ \text{Schwarz: }n\ln\left(\frac{SSE}{n}\right) + p \cdot \ln(n)\\ \text{Siendo }n \text{ el número de observaciones y }p \text{ el número de parámetros} \]
Con ellos determinaré las variables que escogeré en cada modelo. En este caso la introduciré también interacciones (todas las posibles) entre las variables y las transformaciones de las variables.
## Modelos básicos ----
datos<-readRDS("todo_cont")
set.seed(123456)
trainIndex <- createDataPartition(datos$varObjCont, p=0.8, list=FALSE)
data_train <- datos[trainIndex,]
data_test <- datos[-trainIndex,]
null<-lm(varObjCont~1, data=data_train) #Modelo minimo
full<-readRDS("modeloFull")
modeloManual<-readRDS("modeloManual")
# Seleccion de variables "clásica"
modeloStepAIC<-step(null, scope=list(lower=null, upper=full), direction="both")
modeloBackAIC<-step(full, scope=list(lower=null, upper=full), direction="backward")
modeloStepBIC<-step(null, scope=list(lower=null, upper=full), direction="both",k=log(nrow(data_train)))
modeloBackBIC<-step(full, scope=list(lower=null, upper=full), direction="backward",k=log(nrow(data_train)))
## Modelos con interacciones ----
formInt<-formulaInteracciones(datos[,c(1:36,68)],37)#Set original la objetivo está en la columna 68
fullInt<-lm(formInt, data=data_train)
modeloStepAIC_int<-step(null, scope=list(lower=null, upper=fullInt), direction="both")
summary(modeloStepAIC_int) # Fallido
modeloStepBIC_int<-step(null, scope=list(lower=null, upper=fullInt), direction="both",k=log(nrow(data_train)))
## Modelos con transformadas ----
fullT<-lm(varObjCont~., data=data_train)
modeloStepAIC_trans<-step(null, scope=list(lower=null, upper=fullT), direction="both")
modeloStepBIC_trans<-step(null, scope=list(lower=null, upper=fullT), direction="both",k=log(nrow(data_train)))
## Modelos con todas ----
formIntT<-formulaInteracciones(datos,68)
fullIntT<-lm(formIntT, data=data_train)
modeloStepAIC_transInt<-step(null, scope=list(lower=null, upper=fullIntT), direction="both")
modeloStepBIC_transInt<-step(null, scope=list(lower=null, upper=fullIntT), direction="both", k=log(nrow(data_train)))
# # Seleccion aleatoria ----
# rep<-100
# prop<-0.7
# modelosGenerados<-c()
# for (i in 1:rep){
# set.seed(12345+i)
# subsample<-data_train[sample(1:nrow(data_train),prop*nrow(data_train),replace = T),]
# full<-lm(formIntT,data=subsample)
# null<-lm(varObjCont~1,data=subsample)
# modeloAux<-step(null,scope=list(lower=null,upper=full),direction="both",trace=0,k=log(nrow(subsample)))
# modelosGenerados<-c(modelosGenerados,paste(sort(unlist(strsplit(as.character(formula(modeloAux))[3]," [+] "))),
# collapse = "+"))
# }
# 2 únicos modelos que aparezcan más de una vez
modeloAleat1.frml<- as.formula("varObjCont ~ Age_0_4_Ptge+CCAA+CCAA:raiz4DifComAutonPtge+CodigoProvincia+ForeignersPtge+inmuebles+logxConstructionUnemploymentPtge+logxinmuebles+logxServicesUnemploymentPtge+raiz4DifComAutonPtge+sqrtxAge_19_65_pct+sqrtxAgricultureUnemploymentPtge+sqrxCodigoProvincia")
modeloAleat2.frml<- as.formula("varObjCont ~ ActividadPpal+ActividadPpal:AgricultureUnemploymentPtge+ActividadPpal:ForeignersPtge+Age_19_65_pct+Age_over65_pct+Age_under19_Ptge+AgricultureUnemploymentPtge+CCAA+CCAA:raiz4DifComAutonPtge+ForeignersPtge+inmuebles+logxinmuebles+raiz4DifComAutonPtge+sqrtxAgricultureUnemploymentPtge")
modeloAleat1<-lm(modeloAleat1.frml, data=data_train)
modeloAleat2<-lm(modeloAleat2.frml, data=data_train)
# LASSO ----
# Lo hacemos sin interacciones pues, de lo contrario, puede coger interacciones y no las variables que las forman
y<- as.double(as.matrix(data_train[, 68]))
x<- model.matrix(varObjCont~., data=data_train[,c(1:37,68)])[,-1]#no cambiar el -1
set.seed(1712)
cv.lasso <- cv.glmnet(x,y,nfolds=5)
plot(cv.lasso)
betas<-coef(cv.lasso, s=cv.lasso$lambda.1se)
Una vez definidos los modelos y realizada la criba de variables voy a usar ‘crossvalidation’ para compararlos de una forma justa.
## Validación cruzada ----
total<-c()
# Elimino el modelo que ha fallado
modelos<-sapply(list(modeloManual,modeloStepAIC,modeloStepBIC,modeloStepBIC_int,modeloStepAIC_trans,
modeloStepBIC_trans, modeloStepAIC_transInt, modeloStepBIC_transInt, modeloAleat1,
modeloAleat2), formula)
model.names = c("modeloManual", "modeloStepAIC","modeloStepBIC","modeloStepBIC_int","modeloStepAIC_trans",
"modeloStepBIC_trans", "modeloStepAIC_transInt", "modeloStepBIC_transInt", "modeloAleat1",
"modeloAleat2")
for (i in 1:length(modelos)){
set.seed(1712)
vcr<-train(modelos[[i]], data = data_train,
method = "lm",
trControl = trainControl(method="repeatedcv", number=5, repeats=20,
returnResamp="all")
)
total<-rbind(total,cbind(vcr$resample[,1:2],modelo=rep(model.names[i],
nrow(vcr$resample))))
}
set.seed(1712)
lassovcr <- train(varObjCont ~ ., data = data_train,
method = "glmnet",
tuneGrid=expand.grid(.alpha=1,.lambda=cv.lasso$lambda.1se),
trControl = trainControl(method="repeatedcv", number=5, repeats=20,
returnResamp="all")
)
total<-rbind(total,cbind(lassovcr$resample[,1:2],modelo=rep("Lasso",
nrow(vcr$resample))))
mean_R2 | std_R2 | variables | test_R2 | |
---|---|---|---|---|
modeloManual | 0,616 | 0,016 | 25 | 0,623 |
Lasso | 0,624 | 0,014 | 0 | 0,629 |
modeloStepBIC | 0,628 | 0,015 | 31 | 0,632 |
modeloStepAIC | 0,630 | 0,015 | 37 | 0,632 |
modeloStepBIC_trans | 0,637 | 0,015 | 32 | 0,640 |
modeloStepBIC_int | 0,642 | 0,015 | 54 | 0,641 |
modeloStepBIC_transInt | 0,649 | 0,015 | 50 | 0,642 |
modeloStepAIC_trans | 0,638 | 0,015 | 48 | 0,643 |
modeloAleat1 | 0,647 | 0,015 | 48 | 0,644 |
modeloAleat2 | 0,644 | 0,015 | 52 | 0,645 |
modeloStepAIC_transInt | 0,662 | 0,015 | 186 | 0,660 |
Por algún motivo el Lasso aparece como si usará 0 variables, lo bueno es que el gráfico podemos ver que el modelo óptimo según este método sería de entre 35 y 50 variables.
En el gráfico de cajas podemos ver como el mejor modelo es el que emplea tanto variables transformadas como interacciones y ha seleccionado las variables mediante el criterio Akaike. No obstante este modelo tiene 200 variables, como podemos ver en la tabla, luego ni se aproxima a ser el mejor modelo. Los demás modelos se mueven en el entorno de 30 - 60 variables, y en esencia existen dos opciones posibles:
Desde mi punto de vista la mejor opción de las dos es el modelo con menos variables, ya que la mejora no me parece suficientemente significativa, y menos mirando las desviaciones típicas de los modelos. Damos por ganador a: BICtrans.
Los modelos que involucraban las variables transformadas se dilataban excesivamente en el tiempo así que he prescindido de ellos. Esencialmente he repetido la parte manual del proceso realizado para la regresión lineal, centrándome en la compprensión de la selección del punto de corte, ya que este es el problema sobre el que vamos a trabajar en el módulo de Machine Learning.
# REGRESIÓN LOGÍSTICA ----
#Cargo los datos depurados (excluyo las variables transformadas)
todo<-readRDS("todo_bin")
todo<- todo[,c(1:36,68)]
#veo el reparto original. Compruebo que la variable objetivo tome valor 1 para el evento y 0 para el no evento
freq(todo$varObjBin) #ese ha de ser el error de referencia
## n % val%
## 0 3076 37.9 37.9
## 1 5043 62.1 62.1
#Hago la partici?n
set.seed(123456)
trainIndex <- createDataPartition(todo$varObjBin, p=0.8, list=FALSE)
data_train <- todo[trainIndex,]
data_test <- todo[-trainIndex,]
#pruebo un primer modelo sin las transformadas
modeloInicial<-glm(varObjBin~.,data=data_train[],family=binomial)
summary(modeloInicial)
##
## Call:
## glm(formula = varObjBin ~ ., family = binomial, data = data_train[])
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.8954 -0.2238 0.3553 0.5291 3.6565
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 4.457e+00 2.139e+00 2.083 0.037226 *
## CodigoProvincia 1.578e-03 3.165e-03 0.498 0.618153
## CCAAAragón 1.783e+00 1.734e-01 10.286 < 2e-16 ***
## CCAAAsturias 9.469e-01 2.891e-01 3.275 0.001057 **
## CCAABaleares 7.873e-01 3.292e-01 2.391 0.016785 *
## CCAACanarias 1.543e+00 3.007e-01 5.130 2.90e-07 ***
## CCAACantabria 3.787e+00 4.533e-01 8.356 < 2e-16 ***
## CCAACastillaLeón 3.386e+00 1.578e-01 21.451 < 2e-16 ***
## CCAACastillaMancha 2.188e+00 1.598e-01 13.694 < 2e-16 ***
## CCAACataluña -5.486e+00 7.249e-01 -7.568 3.80e-14 ***
## CCAACeuta 1.331e+01 3.247e+02 0.041 0.967311
## CCAAComValenciana 3.460e+00 2.238e-01 15.458 < 2e-16 ***
## CCAAExtremadura 9.240e-01 1.743e-01 5.300 1.16e-07 ***
## CCAAGalicia 4.090e+00 3.403e-01 12.016 < 2e-16 ***
## CCAAMadrid 2.789e+00 3.014e-01 9.255 < 2e-16 ***
## CCAAMelilla 1.266e+01 3.247e+02 0.039 0.968910
## CCAAMurcia 2.834e+00 5.573e-01 5.084 3.69e-07 ***
## CCAANavarra 2.602e-01 2.144e-01 1.214 0.224817
## CCAAPaísVasco -2.584e+00 4.388e-01 -5.890 3.86e-09 ***
## CCAARioja 2.867e+00 2.833e-01 10.120 < 2e-16 ***
## Population -2.244e-05 4.812e-05 -0.466 0.640965
## TotalCensus -5.790e-05 5.710e-05 -1.014 0.310607
## Age_0_4_Ptge 4.182e-02 3.689e-02 1.133 0.257063
## Age_under19_Ptge -2.777e-02 2.346e-02 -1.184 0.236505
## Age_19_65_pct -5.240e-02 2.003e-02 -2.616 0.008902 **
## Age_over65_pct -1.308e-02 1.928e-02 -0.679 0.497316
## WomanPopulationPtge -2.923e-03 1.067e-02 -0.274 0.784227
## ForeignersPtge 2.971e-02 8.903e-03 3.337 0.000846 ***
## SameComAutonPtge -1.088e-02 6.955e-03 -1.564 0.117765
## SameComAutonDiffProvPtge 2.376e-02 1.171e-02 2.030 0.042394 *
## DifComAutonPtge -2.846e-02 8.425e-03 -3.378 0.000729 ***
## UnemployLess25_Ptge -9.393e-03 5.272e-03 -1.782 0.074824 .
## Unemploy25_40_Ptge -4.014e-04 3.230e-03 -0.124 0.901118
## UnemployMore40_Ptge -1.696e-03 3.053e-03 -0.555 0.578578
## AgricultureUnemploymentPtge -1.003e-02 4.880e-03 -2.056 0.039758 *
## IndustryUnemploymentPtge -7.894e-04 4.635e-03 -0.170 0.864745
## ConstructionUnemploymentPtge -1.839e-03 4.118e-03 -0.447 0.655191
## ServicesUnemploymentPtge -9.645e-04 2.746e-03 -0.351 0.725413
## totalEmpresas 8.817e-04 7.091e-04 1.243 0.213728
## Industria 1.143e-03 4.806e-03 0.238 0.811964
## Construccion 2.620e-03 2.942e-03 0.891 0.373171
## Hosteleria -8.362e-04 1.430e-03 -0.585 0.558821
## Servicios 4.891e-04 1.941e-03 0.252 0.801076
## ActividadPpalHosteleria -8.774e-01 2.042e-01 -4.296 1.74e-05 ***
## ActividadPpalOtro -6.024e-01 2.412e-01 -2.497 0.012523 *
## inmuebles 3.036e-06 5.671e-05 0.054 0.957314
## Pob2010 7.704e-05 4.470e-05 1.724 0.084783 .
## SUPERFICIE -1.607e-05 7.799e-06 -2.060 0.039386 *
## DensidadBaja 1.105e-01 1.454e-01 0.760 0.447485
## PobChange_pct 4.671e-03 4.412e-03 1.059 0.289791
## PersonasInmueble 5.306e-02 1.184e-01 0.448 0.653998
## Explotaciones -2.784e-04 4.706e-04 -0.592 0.554102
## prop_missings 3.011e+00 7.347e-01 4.098 4.17e-05 ***
## aleatorio -5.543e-02 1.283e-01 -0.432 0.665633
## aleatorio2 -5.389e-02 1.268e-01 -0.425 0.670783
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8620.2 on 6495 degrees of freedom
## Residual deviance: 4792.0 on 6441 degrees of freedom
## AIC: 4902
##
## Number of Fisher Scoring iterations: 11
# Miro las variables más importantes y la curva ROC
par(mfrow=c(1,2), mar=c(4.1, 12, 4.1, 2.1))
impVariablesLog(modeloInicial,"varObjBin")
curvaRoc<- roc(data_test$varObjBin, predict(modeloInicial,data_test,type = "response"), direction="<")
plot(curvaRoc)
par(mfrow=c(1,1))
#Miro el gráfico V de Cramer para ver las variables más importantes
par(mar=c(12, 4.1, 4.1, 2.1))
graficoVcramer(todo, todo$varObjBin, "V de Cramer para Derecha")
cramer.bin<- c("Age_under19_Ptge", "Age_over65_pct","PersonasInmueble",
"Age_0_4_Ptge", "CodigoProvincia", "Age_19_65_pct",
"PobChange_pct", "UnemployMore40_Ptge", "CCAA", "ActividadPpal")
frml<- as.formula(paste("varObjBin", paste(cramer.bin, collapse="+"), sep="~"))
modelo2<-glm(frml,data=data_train,family=binomial)
summary(modelo2)
##
## Call:
## glm(formula = frml, family = binomial, data = data_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.7955 -0.2268 0.3808 0.5130 3.6225
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.613777 1.906565 1.371 0.170395
## Age_under19_Ptge -0.017619 0.022482 -0.784 0.433215
## Age_over65_pct -0.007085 0.018554 -0.382 0.702565
## PersonasInmueble 0.038885 0.106230 0.366 0.714331
## Age_0_4_Ptge 0.064170 0.036281 1.769 0.076947 .
## CodigoProvincia 0.001533 0.003111 0.493 0.622145
## Age_19_65_pct -0.040523 0.019303 -2.099 0.035796 *
## PobChange_pct 0.004555 0.004300 1.059 0.289425
## UnemployMore40_Ptge -0.002099 0.001603 -1.309 0.190381
## CCAAAragón 1.780339 0.157444 11.308 < 2e-16 ***
## CCAAAsturias 0.834891 0.272659 3.062 0.002198 **
## CCAABaleares 0.979563 0.311217 3.148 0.001647 **
## CCAACanarias 1.848876 0.283141 6.530 6.58e-11 ***
## CCAACantabria 3.542812 0.442040 8.015 1.10e-15 ***
## CCAACastillaLeón 3.364670 0.147962 22.740 < 2e-16 ***
## CCAACastillaMancha 2.005234 0.137232 14.612 < 2e-16 ***
## CCAACataluña -5.205583 0.719214 -7.238 4.56e-13 ***
## CCAACeuta 13.528740 324.743741 0.042 0.966770
## CCAAComValenciana 3.515049 0.210178 16.724 < 2e-16 ***
## CCAAExtremadura 0.529013 0.159449 3.318 0.000907 ***
## CCAAGalicia 4.101512 0.331430 12.375 < 2e-16 ***
## CCAAMadrid 2.841224 0.282652 10.052 < 2e-16 ***
## CCAAMelilla 13.378031 324.743752 0.041 0.967140
## CCAAMurcia 3.195654 0.540141 5.916 3.29e-09 ***
## CCAANavarra 0.056227 0.187237 0.300 0.763951
## CCAAPaísVasco -2.601900 0.429632 -6.056 1.39e-09 ***
## CCAARioja 2.765279 0.261701 10.567 < 2e-16 ***
## ActividadPpalHosteleria -1.101589 0.192982 -5.708 1.14e-08 ***
## ActividadPpalOtro -1.024593 0.210448 -4.869 1.12e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8620.2 on 6495 degrees of freedom
## Residual deviance: 4891.9 on 6467 degrees of freedom
## AIC: 4949.9
##
## Number of Fisher Scoring iterations: 11
par(mar=c(4.1, 12, 4.1, 2.1))
impVariablesLog(modelo2,"varObjBin")
# Selecciono las 10 variables más influyentes en el modelo Inicial
main.bin<- c("CCAA", "ActividadPpal", "prop_missings", "ForeignersPtge",
"DifComAutonPtge","PersonasInmueble", "Age_19_65_pct",
"Construccion", "Population", "SameComAutonDiffProvPtge")
frml<- as.formula(paste("varObjBin", paste(main.bin, collapse="+"), sep="~"))
modelo3<-glm(frml,data=data_train,family=binomial)
summary(modelo3)
##
## Call:
## glm(formula = frml, family = binomial, data = data_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -3.0040 -0.2206 0.3623 0.5270 3.6831
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.225e+00 4.557e-01 2.688 0.007187 **
## CCAAAragón 1.936e+00 1.512e-01 12.800 < 2e-16 ***
## CCAAAsturias 1.041e+00 2.748e-01 3.787 0.000152 ***
## CCAABaleares 8.948e-01 3.207e-01 2.790 0.005275 **
## CCAACanarias 1.770e+00 2.844e-01 6.224 4.85e-10 ***
## CCAACantabria 3.971e+00 4.459e-01 8.906 < 2e-16 ***
## CCAACastillaLeón 3.530e+00 1.449e-01 24.366 < 2e-16 ***
## CCAACastillaMancha 2.239e+00 1.546e-01 14.484 < 2e-16 ***
## CCAACataluña -5.292e+00 7.216e-01 -7.334 2.23e-13 ***
## CCAACeuta 1.367e+01 3.247e+02 0.042 0.966421
## CCAAComValenciana 3.581e+00 2.138e-01 16.754 < 2e-16 ***
## CCAAExtremadura 8.487e-01 1.661e-01 5.110 3.22e-07 ***
## CCAAGalicia 4.212e+00 3.283e-01 12.829 < 2e-16 ***
## CCAAMadrid 2.991e+00 2.941e-01 10.170 < 2e-16 ***
## CCAAMelilla 1.321e+01 3.247e+02 0.041 0.967545
## CCAAMurcia 2.894e+00 5.513e-01 5.249 1.53e-07 ***
## CCAANavarra 4.416e-01 2.004e-01 2.204 0.027509 *
## CCAAPaísVasco -2.355e+00 4.309e-01 -5.466 4.61e-08 ***
## CCAARioja 3.016e+00 2.717e-01 11.101 < 2e-16 ***
## ActividadPpalHosteleria -9.452e-01 1.982e-01 -4.769 1.85e-06 ***
## ActividadPpalOtro -5.942e-01 2.285e-01 -2.601 0.009305 **
## prop_missings 2.882e+00 6.343e-01 4.543 5.54e-06 ***
## ForeignersPtge 3.706e-02 6.547e-03 5.661 1.51e-08 ***
## DifComAutonPtge -1.563e-02 4.870e-03 -3.209 0.001330 **
## PersonasInmueble -6.074e-03 9.779e-02 -0.062 0.950469
## Age_19_65_pct -3.446e-02 6.603e-03 -5.219 1.80e-07 ***
## Construccion 5.414e-03 2.630e-03 2.058 0.039575 *
## Population 7.701e-06 3.112e-05 0.248 0.804508
## SameComAutonDiffProvPtge 2.248e-02 1.158e-02 1.940 0.052325 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8620.2 on 6495 degrees of freedom
## Residual deviance: 4826.4 on 6467 degrees of freedom
## AIC: 4884.4
##
## Number of Fisher Scoring iterations: 11
# Pruebo alguna interaccion sobre el 2
mod4.bin<- c("Age_under19_Ptge", "Age_over65_pct","PersonasInmueble",
"Age_0_4_Ptge", "CodigoProvincia", "Age_19_65_pct",
"PobChange_pct", "UnemployMore40_Ptge", "CCAA", "ActividadPpal",
"CCAA:ActividadPpal")
frml<- as.formula(paste("varObjBin", paste(mod4.bin, collapse="+"), sep="~"))
modelo4<-glm(frml,data=data_train,family=binomial)
summary(modelo4)
##
## Call:
## glm(formula = frml, family = binomial, data = data_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.6423 -0.1401 0.3557 0.5639 3.5359
##
## Coefficients: (4 not defined because of singularities)
## Estimate Std. Error z value
## (Intercept) 4.052e+00 1.934e+00 2.095
## Age_under19_Ptge -2.372e-02 2.246e-02 -1.056
## Age_over65_pct -7.871e-03 1.855e-02 -0.424
## PersonasInmueble 1.200e-02 1.083e-01 0.111
## Age_0_4_Ptge 6.237e-02 3.606e-02 1.730
## CodigoProvincia -1.501e-04 3.204e-03 -0.047
## Age_19_65_pct -4.279e-02 1.932e-02 -2.215
## PobChange_pct 3.818e-03 4.269e-03 0.894
## UnemployMore40_Ptge -2.212e-03 1.598e-03 -1.384
## CCAAAragón 1.275e+00 1.115e+00 1.144
## CCAAAsturias -1.685e+00 1.282e+00 -1.314
## CCAABaleares -9.586e-01 5.347e-01 -1.793
## CCAACanarias -3.118e-01 8.224e-01 -0.379
## CCAACantabria 5.878e-01 1.159e+00 0.507
## CCAACastillaLeón 1.659e+01 6.328e+02 0.026
## CCAACastillaMancha 2.078e+00 1.090e+00 1.907
## CCAACataluña -1.858e+01 2.980e+02 -0.062
## CCAACeuta 1.887e+01 3.956e+03 0.005
## CCAAComValenciana 1.655e+01 4.755e+02 0.035
## CCAAExtremadura 1.663e+01 3.956e+03 0.004
## CCAAGalicia 1.145e+00 8.362e-01 1.369
## CCAAMadrid 1.727e+00 6.374e-01 2.709
## CCAAMelilla 1.874e+01 3.956e+03 0.005
## CCAAMurcia 1.655e+01 2.797e+03 0.006
## CCAANavarra -1.469e+00 6.491e-01 -2.263
## CCAAPaísVasco -1.860e+01 9.320e+02 -0.020
## CCAARioja 1.652e+01 1.978e+03 0.008
## ActividadPpalHosteleria -2.379e+00 3.935e-01 -6.046
## ActividadPpalOtro -1.948e+00 4.198e-01 -4.640
## CCAAAragón:ActividadPpalHosteleria 7.644e-01 1.147e+00 0.667
## CCAAAsturias:ActividadPpalHosteleria 2.929e+00 1.317e+00 2.224
## CCAABaleares:ActividadPpalHosteleria 2.848e+00 7.042e-01 4.044
## CCAACanarias:ActividadPpalHosteleria 2.487e+00 8.740e-01 2.846
## CCAACantabria:ActividadPpalHosteleria 3.471e+00 1.308e+00 2.654
## CCAACastillaLeón:ActividadPpalHosteleria -1.361e+01 6.328e+02 -0.022
## CCAACastillaMancha:ActividadPpalHosteleria 6.897e-01 1.111e+00 0.621
## CCAACataluña:ActividadPpalHosteleria 1.466e+01 2.980e+02 0.049
## CCAACeuta:ActividadPpalHosteleria NA NA NA
## CCAAComValenciana:ActividadPpalHosteleria -1.240e+01 4.755e+02 -0.026
## CCAAExtremadura:ActividadPpalHosteleria -1.618e+01 3.956e+03 -0.004
## CCAAGalicia:ActividadPpalHosteleria 3.474e+00 9.268e-01 3.748
## CCAAMadrid:ActividadPpalHosteleria 1.393e+00 7.683e-01 1.813
## CCAAMelilla:ActividadPpalHosteleria NA NA NA
## CCAAMurcia:ActividadPpalHosteleria -1.321e+01 2.797e+03 -0.005
## CCAANavarra:ActividadPpalHosteleria 1.053e+00 7.636e-01 1.379
## CCAAPaísVasco:ActividadPpalHosteleria 1.524e+01 9.320e+02 0.016
## CCAARioja:ActividadPpalHosteleria -1.225e+01 1.978e+03 -0.006
## CCAAAragón:ActividadPpalOtro 2.898e-01 1.132e+00 0.256
## CCAAAsturias:ActividadPpalOtro 1.767e+00 1.405e+00 1.258
## CCAABaleares:ActividadPpalOtro 3.342e+00 1.254e+00 2.666
## CCAACanarias:ActividadPpalOtro 1.899e+01 3.956e+03 0.005
## CCAACantabria:ActividadPpalOtro 2.695e+00 1.385e+00 1.946
## CCAACastillaLeón:ActividadPpalOtro -1.337e+01 6.328e+02 -0.021
## CCAACastillaMancha:ActividadPpalOtro -5.475e-01 1.109e+00 -0.494
## CCAACataluña:ActividadPpalOtro 1.352e+01 2.980e+02 0.045
## CCAACeuta:ActividadPpalOtro NA NA NA
## CCAAComValenciana:ActividadPpalOtro -1.373e+01 4.755e+02 -0.029
## CCAAExtremadura:ActividadPpalOtro -1.617e+01 3.956e+03 -0.004
## CCAAGalicia:ActividadPpalOtro 1.740e+00 1.134e+00 1.535
## CCAAMadrid:ActividadPpalOtro 9.615e-01 8.004e-01 1.201
## CCAAMelilla:ActividadPpalOtro NA NA NA
## CCAAMurcia:ActividadPpalOtro 2.142e+00 3.953e+03 0.001
## CCAANavarra:ActividadPpalOtro 1.599e+00 6.937e-01 2.304
## CCAAPaísVasco:ActividadPpalOtro 1.675e+01 9.320e+02 0.018
## CCAARioja:ActividadPpalOtro -1.415e+01 1.978e+03 -0.007
## Pr(>|z|)
## (Intercept) 0.036196 *
## Age_under19_Ptge 0.290921
## Age_over65_pct 0.671383
## PersonasInmueble 0.911787
## Age_0_4_Ptge 0.083711 .
## CodigoProvincia 0.962628
## Age_19_65_pct 0.026748 *
## PobChange_pct 0.371209
## UnemployMore40_Ptge 0.166297
## CCAAAragón 0.252604
## CCAAAsturias 0.188804
## CCAABaleares 0.073041 .
## CCAACanarias 0.704561
## CCAACantabria 0.611947
## CCAACastillaLeón 0.979088
## CCAACastillaMancha 0.056506 .
## CCAACataluña 0.950281
## CCAACeuta 0.996195
## CCAAComValenciana 0.972232
## CCAAExtremadura 0.996646
## CCAAGalicia 0.171110
## CCAAMadrid 0.006742 **
## CCAAMelilla 0.996220
## CCAAMurcia 0.995280
## CCAANavarra 0.023608 *
## CCAAPaísVasco 0.984078
## CCAARioja 0.993336
## ActividadPpalHosteleria 1.48e-09 ***
## ActividadPpalOtro 3.48e-06 ***
## CCAAAragón:ActividadPpalHosteleria 0.505079
## CCAAAsturias:ActividadPpalHosteleria 0.026178 *
## CCAABaleares:ActividadPpalHosteleria 5.26e-05 ***
## CCAACanarias:ActividadPpalHosteleria 0.004434 **
## CCAACantabria:ActividadPpalHosteleria 0.007964 **
## CCAACastillaLeón:ActividadPpalHosteleria 0.982838
## CCAACastillaMancha:ActividadPpalHosteleria 0.534597
## CCAACataluña:ActividadPpalHosteleria 0.960781
## CCAACeuta:ActividadPpalHosteleria NA
## CCAAComValenciana:ActividadPpalHosteleria 0.979192
## CCAAExtremadura:ActividadPpalHosteleria 0.996737
## CCAAGalicia:ActividadPpalHosteleria 0.000178 ***
## CCAAMadrid:ActividadPpalHosteleria 0.069869 .
## CCAAMelilla:ActividadPpalHosteleria NA
## CCAAMurcia:ActividadPpalHosteleria 0.996232
## CCAANavarra:ActividadPpalHosteleria 0.167771
## CCAAPaísVasco:ActividadPpalHosteleria 0.986952
## CCAARioja:ActividadPpalHosteleria 0.995057
## CCAAAragón:ActividadPpalOtro 0.797978
## CCAAAsturias:ActividadPpalOtro 0.208353
## CCAABaleares:ActividadPpalOtro 0.007678 **
## CCAACanarias:ActividadPpalOtro 0.996169
## CCAACantabria:ActividadPpalOtro 0.051603 .
## CCAACastillaLeón:ActividadPpalOtro 0.983140
## CCAACastillaMancha:ActividadPpalOtro 0.621537
## CCAACataluña:ActividadPpalOtro 0.963814
## CCAACeuta:ActividadPpalOtro NA
## CCAAComValenciana:ActividadPpalOtro 0.976968
## CCAAExtremadura:ActividadPpalOtro 0.996740
## CCAAGalicia:ActividadPpalOtro 0.124847
## CCAAMadrid:ActividadPpalOtro 0.229649
## CCAAMelilla:ActividadPpalOtro NA
## CCAAMurcia:ActividadPpalOtro 0.999568
## CCAANavarra:ActividadPpalOtro 0.021197 *
## CCAAPaísVasco:ActividadPpalOtro 0.985658
## CCAARioja:ActividadPpalOtro 0.994293
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8620.2 on 6495 degrees of freedom
## Residual deviance: 4788.5 on 6435 degrees of freedom
## AIC: 4910.5
##
## Number of Fisher Scoring iterations: 16
# Pruebo uno con las variables más importantes del 3
impVariablesLog(modelo3,"varObjBin")
mod5.bin<- c("CCAA", "ActividadPpal", "prop_missings", "ForeignersPtge",
"DifComAutonPtge", "Age_19_65_pct")
frml<- as.formula(paste("varObjBin", paste(mod5.bin, collapse="+"), sep="~"))
modelo5<-glm(frml,data=data_train,family=binomial)
summary(modelo5)
##
## Call:
## glm(formula = frml, family = binomial, data = data_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.8812 -0.2221 0.3649 0.5249 3.6615
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 1.390873 0.443406 3.137 0.001708 **
## CCAAAragón 1.923127 0.149485 12.865 < 2e-16 ***
## CCAAAsturias 0.944902 0.268311 3.522 0.000429 ***
## CCAABaleares 0.816499 0.315013 2.592 0.009543 **
## CCAACanarias 1.670786 0.280761 5.951 2.67e-09 ***
## CCAACantabria 3.899332 0.441709 8.828 < 2e-16 ***
## CCAACastillaLeón 3.519518 0.142444 24.708 < 2e-16 ***
## CCAACastillaMancha 2.188758 0.149746 14.616 < 2e-16 ***
## CCAACataluña -5.219328 0.720768 -7.241 4.44e-13 ***
## CCAACeuta 13.493874 324.743736 0.042 0.966856
## CCAAComValenciana 3.539079 0.211308 16.748 < 2e-16 ***
## CCAAExtremadura 0.766186 0.160548 4.772 1.82e-06 ***
## CCAAGalicia 4.233436 0.327453 12.928 < 2e-16 ***
## CCAAMadrid 2.904824 0.287411 10.107 < 2e-16 ***
## CCAAMelilla 12.983947 324.743742 0.040 0.968107
## CCAAMurcia 2.795576 0.548465 5.097 3.45e-07 ***
## CCAANavarra 0.341248 0.188697 1.808 0.070538 .
## CCAAPaísVasco -2.362357 0.429324 -5.503 3.74e-08 ***
## CCAARioja 2.913225 0.264077 11.032 < 2e-16 ***
## ActividadPpalHosteleria -0.975342 0.197862 -4.929 8.25e-07 ***
## ActividadPpalOtro -0.788825 0.206962 -3.811 0.000138 ***
## prop_missings 2.840473 0.601012 4.726 2.29e-06 ***
## ForeignersPtge 0.037080 0.006531 5.678 1.36e-08 ***
## DifComAutonPtge -0.015741 0.004737 -3.323 0.000890 ***
## Age_19_65_pct -0.032207 0.006306 -5.107 3.27e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 8620.2 on 6495 degrees of freedom
## Residual deviance: 4836.0 on 6471 degrees of freedom
## AIC: 4886
##
## Number of Fisher Scoring iterations: 11
#Validacion cruzada repetida para elegir entre todos
auxVarObj<-todo$varObjBin
todo$varObjBin<-make.names(todo$varObjBin) #formateo la variable objetivo para que funcione el codigo
total<-c()
modelos<-sapply(list(modeloInicial,modelo2,modelo3,modelo4,modelo5),formula)
for (i in 1:length(modelos)){
set.seed(1712)
vcr<-train(as.formula(modelos[[i]]), data = todo,
method = "glm", family="binomial",metric = "ROC",
trControl = trainControl(method="repeatedcv", number=5, repeats=20,
summaryFunction=twoClassSummary,
classProbs=TRUE,returnResamp="all")
)
total<-rbind(total,data.frame(roc=vcr$resample[,1],modelo=rep(paste("Modelo",i),
nrow(vcr$resample))))
}
Vemos el valor del área bajo la curva ROC
mean_ROC | std_ROC | variables | test_pseudoR2 | |
---|---|---|---|---|
Modelo 4 | 0,895 | 0,008 | 65 | 0,426 |
Modelo 2 | 0,892 | 0,008 | 29 | 0,445 |
Modelo 5 | 0,897 | 0,007 | 25 | 0,454 |
Modelo 3 | 0,897 | 0,007 | 29 | 0,455 |
Modelo 1 | 0,895 | 0,007 | 55 | 0,459 |
Lo primero que debo hacer es celebrar los resultados ya que tanto el \(pseudoR^2\) como el área bajo la curva ROC dan valores considerablemente altos, lo que es una muy buena señal. Claramente los modelos que compiten pos ser el mejor son el modelo1 generado con todas las variables, el modelo3 generado con las variables que presentaban mayor significancia en el modelo1 y el modelo5 generado reduciendo aún más las variables, escogiendo las más importantes del modelo3. Aunque el tanto el modelo1 como el modelo3 presentan un \(pseudoR^2\) algo superior (muy ligeramente), el modelo5 tiene mayor área bajo la curva roc y el menor número de variables, así que va a ser nuestro elegido.
Para elegir el mejor punto de corte lo primero es mirar la distribución de las probabilidades sobre el set de datos test.
Ya vemos una región que parece interesante, podemos ver algunos valores de precisión, sensibilidad y especificidad de el modelo tomando esos valores:
Y viendo que los resultados son bastante buenos, podemos hacer ir probando los valores dentro de una región (un poco más conservadora) en la que creemos que se encuentra el punto óptimo.
## Mejor punto de corte ----
## generamos una rejilla de puntos de corte
posiblesCortes<-seq(0.25,0.75,0.005)
rejilla<-data.frame(t(rbind(posiblesCortes,sapply(posiblesCortes,function(x) sensEspCorte(modelo5,data_test,"varObjBin",x,"1")))))
rejilla$Youden<-rejilla$Sensitivity+rejilla$Specificity-1
rejilla$posiblesCortes[which.max(rejilla$Youden)]
## [1] 0.61
rejilla$posiblesCortes[which.max(rejilla$Accuracy)]
## [1] 0.43
rejilla$posiblesCortes[which.max(rejilla$Youden + rejilla$Accuracy)]
## [1] 0.435
Accuracy | Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | |
---|---|---|---|---|---|
0.43 | 0,845 | 0,923 | 0,719 | 0,843 | 0,850 |
0.435 | 0,845 | 0,922 | 0,720 | 0,844 | 0,849 |
0.61 | 0,837 | 0,882 | 0,763 | 0,859 | 0,798 |
Comparando los resultados para cada punto de corte podemos ver que el valor 0.61 baja demasiado la sensibilidad mientras que entre el 0.43 y el 0.435 las diferencias son poco sensibles. Como diría Aristóteles la virtud está en el centro así que creo que la mejor opción es 0.435, que además obedece al valor donde se maximiza la suma de la precisión con el coeficiente índice de Youden que es un criterio que me he inventado yo (la gráfica ha sido una fuerte sugestión).
Ahora con este valor vamos a ver los coeficientes y variables que participan del modelo ganador. Por supuesto aquí no nos vamos a llevar ninguna sorpresa. La Comunidad Autónoma sigue predominando con excesiva fuerza y el resto parecen prácticamente de apoyo.
Hubiera sido interesante hacer un modelo solo con la Comunidad Autónoma y usarlo como floor, posiblemente fuera un modelo bastante competitivo (y no es otra cosa que ese señor en un bar gritando: Los andaluces son unos rojos, los valencianos son unos fachas, …’ (a ver quién va ahora a decirle que no)).
# Vemos las variables m?s importantes del modelo ganador
par(mar=c(4.1, 12, 4.1, 2.1))
impVariablesLog(modelo5,"varObjBin")
# Vemos los coeficientes del modelo ganador
coef(modelo5)
## (Intercept) CCAAAragón CCAAAsturias
## 1.39087329 1.92312684 0.94490232
## CCAABaleares CCAACanarias CCAACantabria
## 0.81649928 1.67078613 3.89933178
## CCAACastillaLeón CCAACastillaMancha CCAACataluña
## 3.51951801 2.18875785 -5.21932772
## CCAACeuta CCAAComValenciana CCAAExtremadura
## 13.49387404 3.53907865 0.76618650
## CCAAGalicia CCAAMadrid CCAAMelilla
## 4.23343569 2.90482387 12.98394676
## CCAAMurcia CCAANavarra CCAAPaísVasco
## 2.79557607 0.34124772 -2.36235739
## CCAARioja ActividadPpalHosteleria ActividadPpalOtro
## 2.91322493 -0.97534186 -0.78882495
## prop_missings ForeignersPtge DifComAutonPtge
## 2.84047291 0.03708012 -0.01574055
## Age_19_65_pct
## -0.03220663
# Evaluamos la estabilidad del modelo a partir de las diferencias en train y test:
train.test<- as.data.frame(rbind(sensEspCorte(modelo5,data_train,"varObjBin",0.495,"1"),
sensEspCorte(modelo5,data_test,"varObjBin",0.495,"1")),
row.names=c("train", "test"))
train.test$auc<- c(roc(data_train$varObjBin, predict(modelo5,data_train,type = "response"),
direction="<")$auc,
roc(data_test$varObjBin, predict(modelo5,data_test,type = "response"),
direction="<")$auc)
train.test$pseudoR2<- c(pseudoR2(modelo5,data_train,"varObjBin"),
pseudoR2(modelo5,data_test,"varObjBin"))
kable(train.test , caption = "Comparación entre train y test",
row.names = TRUE,
digits = 3,
format.args = list(decimal.mark = ",")
)
Accuracy | Sensitivity | Specificity | Pos Pred Value | Neg Pred Value | auc | pseudoR2 | |
---|---|---|---|---|---|---|---|
train | 0,841 | 0,915 | 0,719 | 0,842 | 0,837 | 0,898 | 0,439 |
test | 0,842 | 0,910 | 0,732 | 0,848 | 0,832 | 0,903 | 0,454 |
Sorprendentemente la mayoría de valores mejoran para los datos test así que podemos concluir ampliamente satisfechos que nuestra regresión acierta más del 90% de las veces que región gobernará la derecha y al menos un 70% en cual lo hará la izquierda, lo cual es los tiempos que corren no es baladí.
Aún tengo muchos problemas con R y pierdo mucho tiempo con temas de librerías y errores varios, así que el trabajo no es todo lo bueno que debería. Además me relaje al saber que iba a profundizar en la regresión logística en el módulo de machine learning. Mis más sinceras disculpas por haber leído tan tarde lo del .pdf, y entregar en .html, siempre me salto la parte clave de los enunciados. En definitiva, muchas gracias por su tiempo, ha sido un trabajo muy estimulante.