Marginación de municipios

Consideremos el índice de marginación que calcula CONAPO con datos de censos y conteos. Este índice un resumen de varios indicadores de carencias de las poblaciones de los municipios que nos rankear a los municipios por nivel de marginación. Se utiliza frecuentemente en análisis en donde queremos incluir el contexto donde viven las personas, y para guiar decisiones de política pública.

Por ejemplo, para 2010 tenemos los datos:

library(readr)
library(kableExtra)
library(ggplot2)
library(dplyr)
library(tidyr)
library(stargazer)
library(DT)

marginacion <- read_csv("./datos/imm-2010.csv")
descrip <- read_csv("./datos/imm-2010-descrip.csv", skip = 2)
descrip %>% knitr::kable()
Variable Descripción
CVE_ENT Clave de la entidad federativa
NOM_ENT Nombre de la entidad federativa
CVE_MUN Clave del municipio
NOM_MUN Nombre del municipio
POB_TOT Población total
ANALF Porcentaje de población de 15 años o más analfabeta
SPRIM Porcentaje de población de 15 años o más sin primaria completa
OVSDE Porcentaje de ocupantes en viviendas sin drenaje ni excusado
OVSEE Porcentaje de ocupantes en viviendas sin energía eléctrica
OVSAE Porcentaje de ocupantes en viviendas sin agua entubada
VHAC Porcentaje de viviendas con algún nivel de hacinamiento
OVPT Porcentaje de ocupantes en viviendas con piso de tierra
PL_5000 Porcentaje de población en localidades con menos de 5 000 habitantes
PO2SM Porcentaje de población ocupada con ingreso de hasta 2 salarios mínimos
IM Índice de marginación
GM Grado de marginación

El índice de marginación es una combinación de variables que indican distintos tipos de carencias para obtener un resumen o calificación general del grado de marginación de cada municipio.

ggplot(marginacion, aes(x = IM)) + geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Por ejemplo, si promediamos los índices de marginación de los municipios dentro de cada estado obtenemos:

marginacion %>% group_by(NOM_ENT) %>% summarise(marg = mean(IM), n = sum(POB_TOT)) %>% 
    arrange(desc(marg))
## # A tibble: 32 x 3
##    NOM_ENT                           marg       n
##    <chr>                            <dbl>   <dbl>
##  1 Guerrero                         1.12  3388768
##  2 Chiapas                          0.808 4796580
##  3 Oaxaca                           0.652 3801962
##  4 Puebla                           0.290 5779829
##  5 Veracruz de Ignacio de la Llave  0.216 7643194
##  6 Yucatan                          0.176 1955577
##  7 San Luis Potosi                  0.114 2585518
##  8 Campeche                        -0.163  822441
##  9 Michoacan de Ocampo             -0.203 4351037
## 10 Hidalgo                         -0.218 2665018
## # … with 22 more rows

¿Cómo se calcula el índice de marginación?

Veamos un resumen de las variables incluidas:

marg_tabla <- marginacion %>% select(ANALF:PO2SM)
marg_tabla %>% gather(variable, valor, ANALF:PO2SM) %>% group_by(variable) %>% 
    summarise(q10 = quantile(valor, 0.10),
              mediana = median(valor), 
              q90 = quantile(valor, 0.90)) %>% 
    arrange(desc(mediana))
## # A tibble: 9 x 4
##   variable    q10 mediana    q90
##   <chr>     <dbl>   <dbl>  <dbl>
## 1 PL_5000  14.8    100    100   
## 2 PO2SM    33.6     63.4   86.2 
## 3 VHAC     29.1     43.7   61.8 
## 4 SPRIM    16.0     34.5   50.9 
## 5 ANALF     3.82    11.9   27.9 
## 6 OVPT      1.91     8.68  29.4 
## 7 OVSAE     0.665    7.03  40.8 
## 8 OVSDE     0.62     3.46  17.9 
## 9 OVSEE     0.51     2.18   8.78

I.

Pregunta 1: usando la descomposición en valores singulares, encuentra una aproximación de rango 1 a la tabla de municipios x 9 variables mostradas arriba

#En primer lugar descomponemos la tabla de marginación en valores singulares con sus respectivos vectores asociados
valores<-svd(marg_tabla)
sigma <- valores$d
v <- valores$v
rownames(v) <- colnames(marg_tabla)
u <- valores$u
rownames(u) <- rownames(marg_tabla)

#En segundo lugar, multiplicamos el primer valor singular con el primer vector renglón y vector columna.
aprox_r_1<-(sigma[1]*tcrossprod(valores$u[,1], valores$v[,1])) 
rownames(aprox_r_1) <- rownames(marg_tabla)
colnames(aprox_r_1) <- colnames(marg_tabla)

#Aproximación de órden 1
datatable(aprox_r_1, rownames = TRUE, options = list(pageLength = 5, scrollX=T) )

II.

Pregunta 2: Calcula una medida de calidad de la aproximación de rango 1. ¿Qué tan buena es?

# Puedo evaluarlo con la norma de Frombenius
#La calculamos de distintas maneras
#A)
sum(marg_tabla^2)-sum(sigma[1:1]^2)
## [1] 2785216
#B)
sum((as.matrix(marg_tabla) - aprox_r_1)^2)
## [1] 2785216
#Puedo expresarlo en cociente
sum(sigma[1:1]^2)/sum(marg_tabla^2)
## [1] 0.9262932
#La matriz original y la de orden 1 son similares en valores en un 92%.

#Graficamente
R <- as.matrix(marg_tabla) - aprox_r_1
qplot(x=as.numeric(aprox_r_1), y=as.numeric(as.matrix(marg_tabla)), geom=c("smooth"), main="Similitud", xlab="Aproximación de órden 1",
   ylab="Datos originales") + geom_abline(colour='red')
## `geom_smooth()` using method = 'gam' and formula 'y ~ s(x, bs = "cs")'

En resumen, la aproximación de órden 1 parece que es una muy buena aproximación pues genera el 92% de la composición de los valores de las entradas en los datos originales.

III.

Pregunta 3: En la descomposición que hiciste, ¿Qué usaría cómo medición de marginación por municipio, los scores de los municipios o los pesos de las variables?

Usaría los scores de los municipios pues son una buena aproximación de la marginación por municipio porque te brindan información sobre la estructura inicial de la marginacion (y como se pueden comparar entre ellos mismos) antes de corregir por los pesos de las variables.

IV.

Pregunta 4: Explica cómo se construye tu medición de marginación en términos de la descomposición en valores singulares que obtuviste? ¿Cómo se ponderan las variables originales para construir tu medición de marginación?

La medición se contruye multiplicando al primer valor singular con la primera columna de mi tabla de scores y la primera columna de pesos de variables transpuesta. Es decir, el socre de cada municipio se va a multiplicar por el valor singular lo que expande de manera monotónica a cada score, (dandole cuerpo a la tabla). Esto produce algo así como un nucleo de valor que comparte el municipio a través de cada variable. Luego se multiplica cada score por cada peso de las variables creando ahora asi información de cada municipio para cada variable. La ponderación que toma cada variable simplemente es reflejo del tamaño de las unidades de cada variable. En teoría podríamos reconstruir el indice de marginación si sumamos ahora cada variable para cada municipio, sin embargo es muy probable que para construir el indice hayan centrado o estandarizado las variables, por lo que por lo pronto no lograríamos una reconstrucción perfecta.

V.

Pregunta 5: Observa que variables que tienen unidades más grandes (como PL_5000, porcentaje de población que vive en localidades de menos de 5000 habitantes) tienen más peso que otras como OVSAE (porcentaje de habitantes sin agua entubada). Argumenta por qué sería buena idea escalar las variables antes de hacer la descomposición en valores singulares.

Los pesos de las variables y los valores singulares nos brindan información de la varianza y su dirección. Si no escalamos o estandarizamos, los pesos y los valores propios estarán cargados de información de la dimensión de las unidades más que de la estructura real de la varianza que queremos descubrir. Si bien, hay veces en que la dimensión de las variables importa en estos análisis, en general no nos brinda mucha información útil.

Por ejemplo, los pesos y los valores tendrían más información de las variables con las unidades más grandes que de las variables con unidades más pequeñas. Si escalamos, podríamos ver la estructura de los datos de manera más pareja, en específico, si estandarizamos compararíamos las varianzas en las mismas unidades.

VI.

Pregunta 6: Escala todas las variables para que tomen valores aproximadamente entre 0 y 1 y repite el análisis de descomposición en valores singulares. Compara tu nuevo índice con la variable IM (que es el índice de marginación oficial). ¿Qué tan similares son? (recuerda que puedes multiplicar por menos tu índice si es necesario) Muestra los nuevos pesos de las variables para este nuevo índice que acabas de crear ¿cómo intepretas tu índice en términos de estos pesos?. Puedes usar este código para reescalar:

#reescalamos
max_c <- apply(marg_tabla, 2, function(x){ quantile(x, 0.95) })
min_c <- apply(marg_tabla, 2, min)
marg_tabla_norm <- scale(marg_tabla, center = min_c, scale = (max_c - min_c))

#Repetimos
valores_norm<-svd(marg_tabla_norm)
sigma_norm <- valores_norm$d
v_norm <- valores_norm$v
rownames(v_norm) <- colnames(marg_tabla)
u_norm <- valores_norm$u
rownames(u_norm) <- rownames(marg_tabla)

#En segundo lugar, multiplicamos el primer valor singular con el primer vector renglon y vector columna.
aprox_r_1_norm<-(sigma_norm[1]*tcrossprod(valores_norm$u[,1], valores_norm$v[,1])) %>% round(1)
rownames(aprox_r_1_norm) <- rownames(marg_tabla)
colnames(aprox_r_1_norm) <- colnames(marg_tabla)

#Agrego el indice:
aprox_r_1_norm<-as.data.frame(aprox_r_1_norm) %>%mutate(IM_aprox=rowSums(.))
aprox_r_1_norm<-cbind(aprox_r_1_norm,marginacion$IM)

En cuanto a la similitud, en la siguiente regresión evaluamos al IM ~ nuestro IM. Notamos que la relación es estadísticamente significativa a más del 99% sin embargo también notamos que el coeficiente es de .571, lo que quiere decir que a pesar de que tengan el mismo signo (osea que van en la misma dirección) la mayoría de las veces, nuestro IM en general es casi del doble del tamaño que el IM real. Además la constante es negativa y estadísticamente significativa, lo que quiere decir que en promedio,además de ser del doble de tamaño, nuestro IM está 2.434 puntos por debajo del valor del IM real.

#similitud entre indice
reg1<-lm(`marginacion$IM`~ IM_aprox,aprox_r_1_norm)
stargazer(reg1,type="text")
## 
## =================================================
##                          Dependent variable:     
##                     -----------------------------
##                                  IM`             
## -------------------------------------------------
## IM_aprox                      0.571***           
##                                (0.002)           
##                                                  
## Constant                      -2.434***          
##                                (0.007)           
##                                                  
## -------------------------------------------------
## Observations                    2,456            
## R2                              0.981            
## Adjusted R2                     0.981            
## Residual Std. Error       0.138 (df = 2454)      
## F Statistic         126,084.100*** (df = 1; 2454)
## =================================================
## Note:                 *p<0.1; **p<0.05; ***p<0.01

En cuanto a los pesos, ahora se reponderaron un poco corrigiendo por el desbalance de las unidades. Aunque siguen siendo reflejo de la varianza de los datos. Debido a que no hemos controlado por ello, que nuestra estimación del IM esté “capturando” varianza extra y por ello nos sale casi del doble de tamaño y con un ligero sesgo negativo. Esto es una ventaja si queremos aprovechar con más detalle la varianza de los datos pero es una desventaja si lo que queremos es tener una estimación exacta del IM.

#pesos de las variables
datatable(v_norm, rownames = TRUE, options = list(pageLength = 5, scrollX=T) )

VII.

Pregunta 7 Verifica que puedes reconstruir el índice oficial usando el siguiente escalamiento:

media <- apply(marg_tabla, 2, mean)
desvest <- apply(marg_tabla, 2, sd)
marg_tabla_norm <- scale(marg_tabla, center = media, scale = desvest)

#Repetimos
valores_scaled<-svd(marg_tabla_norm)
sigma_scaled <- valores_scaled$d
v_scaled <- valores_scaled$v
rownames(v_scaled) <- colnames(marg_tabla)
u_scaled <- valores_scaled$u
rownames(u_scaled) <- rownames(marg_tabla)

#dejé el loop solo porque experimenté qué pasa si hago la aproximación de otro órden
my.sum <- 0
for(i in 1:1){
    current <- (sigma_scaled[i]*tcrossprod(valores_scaled$u[,i], valores_scaled$v[,i])) 
    my.sum <- my.sum + current
}

aprox_r_1_scaled<- my.sum
rownames(aprox_r_1_scaled) <- rownames(marg_tabla)
colnames(aprox_r_1_scaled) <- colnames(marg_tabla)

#Agrego el indice:

aprox_r_1_scaled<-as.data.frame(aprox_r_1_scaled) %>%mutate(IM_aprox=rowSums(.))
aprox_r_1_scaled<-cbind(aprox_r_1_scaled,marginacion$IM)
aprox_r_1_scaled$IM_aprox<-scale(aprox_r_1_scaled$IM_aprox, center=mean(aprox_r_1_scaled$IM_aprox, scale=sd(aprox_r_1_scaled$IM_aprox)))

En este caso, con una aproximación de rango 1 y estandarizando las variables pudimos recrear casi perfectamente el IM original. La constante es cero mostrando que nuestra estimación de IM es insesgada y el coeficiente es 1, lo que quiere decir que es virtualmente identico y en la misma dirección.

#similitud entre indice
reg2<-lm(`marginacion$IM`~ IM_aprox,aprox_r_1_scaled)
stargazer(reg2,type="text")
## 
## =====================================================
##                            Dependent variable:       
##                     ---------------------------------
##                                    IM`               
## -----------------------------------------------------
## IM_aprox                        1.000***             
##                                 (0.0001)             
##                                                      
## Constant                        -0.00003             
##                                 (0.0001)             
##                                                      
## -----------------------------------------------------
## Observations                      2,456              
## R2                                1.000              
## Adjusted R2                       1.000              
## Residual Std. Error         0.003 (df = 2454)        
## F Statistic         288,754,373.000*** (df = 1; 2454)
## =====================================================
## Note:                     *p<0.1; **p<0.05; ***p<0.01

VIII.

Pregunta 8 Compara tus resultados de la pregunta 6 y pregunta 7. Brevemente explica las ventajas que le ves al análisis escalado a 0-1 de la pregunta 6 con el análisis de componentes principales de la pregunta 7.

Al estandarizar pudimos hacer que las variables tengan el mismo peso a la hora de obtener los valores singulares y vectores asociados. De esta manera, la estimación del IM es ahora idéntica.

Las ventajas del análisis escalado 0-1 esque podemos aprovcechar más la varianza pues no la estamos “encerrando”(la escala de distancia es más amplia), esto sirve si queremos explorar con más detalle los efectos de las distribuciones de cada variable sobre el IM; las ventajas del análisis estandarizado esque nos brinda una descompocisión pareja para cada variable y en consecuencia podemos aproximar exactamente al IM.

stargazer(reg1,reg2,type="text")
## 
## =================================================================
##                                        Dependent variable:       
##                                 ---------------------------------
##                                                IM`               
##                                      (1)              (2)        
## -----------------------------------------------------------------
## IM_aprox                           0.571***         1.000***     
##                                    (0.002)          (0.0001)     
##                                                                  
## Constant                          -2.434***         -0.00003     
##                                    (0.007)          (0.0001)     
##                                                                  
## -----------------------------------------------------------------
## Observations                        2,456            2,456       
## R2                                  0.981            1.000       
## Adjusted R2                         0.981            1.000       
## Residual Std. Error (df = 2454)     0.138            0.003       
## F Statistic (df = 1; 2454)      126,084.100*** 288,754,373.000***
## =================================================================
## Note:                                 *p<0.1; **p<0.05; ***p<0.01