# install.packages("reticulate")
library(reticulate)
use_python("C:/Users/Cesar Corregidor/anaconda3/python.exe")

INSTRUCCIONES

Considere la base de datos housing.csv adjunta. La misma es descrita en detalle en Boston house prices dataset del repositorio que se encuentra artículo. A partir de la misma resuelva lo siguiente:

  1. Realice una corta presentación del conjunto de datos asegurándose de entender cada variable.

CONTENIDO

Cada registro de la base de datos describe un suburbio o una ciudad de Boston. Los datos se obtuvieron del Área Estadística Metropolitana Estándar de Boston (SMSA) en 1970. Los atributos se definen de la siguiente manera (tomados del Repositorio de Aprendizaje Automático de la UCI1):

Variable descripción
CRIM: tasa de criminalidad per cápita por ciudad.
ZN: proporción de terrenos residenciales con una superficie superior a 25.000 pies cuadrados.
INDUS: proporción de acres comerciales no minoristas por ciudad
CHAS: Variable ficticia de Charles River (= 1 si el tramo limita con el río; 0 en caso contrario)
NOX: concentración de óxidos nítricos (partes por 10 millones) 1https: //archive.ics.uci.edu/ml/datasets/Housing 20.2. Cargar el conjunto de datos 124
RM: número medio de habitaciones por vivienda
EDAD: proporción de unidades ocupadas por sus propietarios construidas antes de 1940
DIS: distancias ponderadas a cinco centros de empleo de Boston
RAD: índice de accesibilidad a carreteras radiales
TAX: tasa del impuesto sobre la propiedad por cada 10.000 dólares
PTRATIO: proporción alumno-maestro por ciudad
B: 1000 (Bk − 0,63) 2 donde Bk es la proporción de afrodescendientes por ciudad 13.
LSTAT: % de estatus inferior de la población
MEDV: Valor medio de las viviendas ocupadas por sus propietarios en miles de dólares.

Podemos ver que los atributos de entrada tienen una mezcla de unidades.

Cargamos la base de datos y validamos datos faltantes

data <- read.csv("D:/Cesar Corregidor/Documents/especializacion/ANALISIS_DE_REGRESION/Regresion-Aplicada-main/Talleres/Taller1/housing.csv", sep = "", header = F,
                 col.names = c("CRIM","ZN", "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD", "TAX", "PTRATIO",                                    "B","LSTAT", "MEDV"))
data_r <- read.csv("D:/Cesar Corregidor/Documents/especializacion/ANALISIS_DE_REGRESION/Regresion-Aplicada-main/Talleres/Taller1/housing.csv", sep = "", header = F,
                 col.names = c("CRIM","ZN", "INDUS", "CHAS", "NOX", "RM", "AGE", "DIS", "RAD", "TAX", "PTRATIO",                                    "B","LSTAT", "MEDV"))
library(DT)
DT::datatable(data_r)
str(data_r)
## 'data.frame':    506 obs. of  14 variables:
##  $ CRIM   : num  0.00632 0.02731 0.02729 0.03237 0.06905 ...
##  $ ZN     : num  18 0 0 0 0 0 12.5 12.5 12.5 12.5 ...
##  $ INDUS  : num  2.31 7.07 7.07 2.18 2.18 2.18 7.87 7.87 7.87 7.87 ...
##  $ CHAS   : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ NOX    : num  0.538 0.469 0.469 0.458 0.458 0.458 0.524 0.524 0.524 0.524 ...
##  $ RM     : num  6.58 6.42 7.18 7 7.15 ...
##  $ AGE    : num  65.2 78.9 61.1 45.8 54.2 58.7 66.6 96.1 100 85.9 ...
##  $ DIS    : num  4.09 4.97 4.97 6.06 6.06 ...
##  $ RAD    : int  1 2 2 3 3 3 5 5 5 5 ...
##  $ TAX    : num  296 242 242 222 222 222 311 311 311 311 ...
##  $ PTRATIO: num  15.3 17.8 17.8 18.7 18.7 18.7 15.2 15.2 15.2 15.2 ...
##  $ B      : num  397 397 393 395 397 ...
##  $ LSTAT  : num  4.98 9.14 4.03 2.94 5.33 ...
##  $ MEDV   : num  24 21.6 34.7 33.4 36.2 28.7 22.9 27.1 16.5 18.9 ...
data_py = r_to_py(data_r)
data_py$head()
##       CRIM    ZN  INDUS  CHAS    NOX  ...    TAX  PTRATIO       B  LSTAT  MEDV
## 0  0.00632  18.0   2.31     0  0.538  ...  296.0     15.3  396.90   4.98  24.0
## 1  0.02731   0.0   7.07     0  0.469  ...  242.0     17.8  396.90   9.14  21.6
## 2  0.02729   0.0   7.07     0  0.469  ...  242.0     17.8  392.83   4.03  34.7
## 3  0.03237   0.0   2.18     0  0.458  ...  222.0     18.7  394.63   2.94  33.4
## 4  0.06905   0.0   2.18     0  0.458  ...  222.0     18.7  396.90   5.33  36.2
## 
## [5 rows x 14 columns]
data_py$isnull()$sum()
## CRIM       0
## ZN         0
## INDUS      0
## CHAS       0
## NOX        0
## RM         0
## AGE        0
## DIS        0
## RAD        0
## TAX        0
## PTRATIO    0
## B          0
## LSTAT      0
## MEDV       0
## dtype: int64
data_r = py_to_r(data_py)

Puesto que no hay datos faltantes omitimos el paso de agregar datos. Cuando revisamos la estructura con str() de r. Observamos que CHAS y RAD toma valores enteros. CHAS representa por números variables categóricas siendo 1: limita con el río y 0: en caso contrario y RAD: índice de accesibilidad a carreteras radiales también sería una variable categórica pero ordinal. Veamos los niveles de categória de estas variables.

data_r$CHAS <- factor(data_r$CHAS)
data_r$RAD <- factor(data_r$RAD)
levels(data_r$CHAS)
## [1] "0" "1"
levels(data_r$RAD)
## [1] "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "24"
  1. Presente los principales resultados de un Análisis Descriptivo y Exploratorio de los datos. Haga énfasis en la relación que pueda existir entre las variables

Como tenemos una categoría de “24” en la variable RAD que me hace dudar que pueda ser un dato atípico entonces realizo un diagrama de barras

library(ggplot2)
RAD_cont = as.data.frame(table(data_r$RAD))
colnames(RAD_cont) = c("RAD","Frecuencia")
#Gráfico
ggplot(data=RAD_cont, aes(x=RAD, y=Frecuencia))+
geom_bar(stat = "identity", fill="steelblue", position = position_dodge())+
geom_text(aes(label=Frecuencia), vjust=1.6, color="white", size=4.5)+
ggtitle ("Diagrama de barras para la \nvariable RAD")+
theme (plot.title = element_text(#family="Comic Sans MS",
                                  size=rel(2), 
                                  vjust=2,
                                  hjust = 0.5,
                                  face="bold",
                                  color="#8B3626", 
                                  lineheight=1.5)) + 
theme(axis.title.x = element_text(face="bold", vjust=-1.5, colour="black", size=rel(1.5)))+
theme(axis.title.y = element_text(face="bold", vjust=1.5, colour="black", size=rel(1.5))) 

No es un dato atípico, es más, es la categoría con mayor frecuencia.

Revisemos el diagrama de barra para la variable CHAS

library(ggplot2)
CHAS_cont = as.data.frame(table(data_r$CHAS))
colnames(CHAS_cont) = c("Chas","Frecuencia")
#Gráfico
ggplot(data=CHAS_cont, aes(x=Chas, y=Frecuencia))+
geom_bar(stat = "identity", fill="steelblue")+
geom_text(aes(label=Frecuencia), vjust=1.6, color="white", size=4.5)+
ggtitle ("Diagrama de barras para la \nvariable CHAS")+
theme (plot.title = element_text(#family="Comic Sans MS",
                                  size=rel(2), 
                                  vjust=2,
                                  hjust = 0.5,
                                  face="bold",
                                  color="#8B3626", 
                                  lineheight=1.5)) + 
theme(axis.title.x = element_text(face="bold", vjust=-1.5, colour="black", size=rel(1.5)))+
theme(axis.title.y = element_text(face="bold", vjust=1.5, colour="black", size=rel(1.5))) 

CHAS_cont
##   Chas Frecuencia
## 1    0        471
## 2    1         35

Hay muchas casas más que no limitan con el río

Veamos el comportamiento del pago en función de estas variables categóricas usando box plots y diagramas de violin

library(gridExtra)
options(repr.plot.width=8, repr.plot.height=8)
fig1 <- ggplot(data_r, aes(x=RAD, y=MEDV))+geom_boxplot()
fig2 <- ggplot(data_r, aes(x=CHAS, y=MEDV))+geom_boxplot()
grid.arrange(fig1,fig2, ncol=2, nrow=2)

library(ggplot2)
library(gridExtra)
options(repr.plot.width=8, repr.plot.height=8)
violin1 <- ggplot(data_r, aes(x = RAD, y = MEDV, fill = RAD)) +
  geom_violin(trim = FALSE) + 
  geom_boxplot(width = 0.02) +
  theme(legend.position = "none")
  
violin2 <- ggplot(data_r, aes(x = CHAS, y = MEDV, fill = CHAS)) +
  geom_violin(trim = FALSE) + 
  geom_boxplot(width = 0.02) +
  theme(legend.position = "none")

grid.arrange(violin1,violin2, ncol=1, nrow=2)

De acuerdo al análisis del precio promedio en función de la variable CHAS las casas que limitan con el río tienen mayor precio que las que no lo hacen. Además estas que no limitan con el río tienen una fuerte concentración en la media de modo que el rango intercuartílico es menor, esto quire decir que tienden a tener un promedio de precio similar, pero a simple vista se ve que hay demasiados valores atípicos con precio muy similares los de CHAS = 1. Para las casas que limitan con el río tienen un fuerte sesgo y valores muy concentrados por encima del 75% pero que no llegan a ser datos atípicos.

Para la variable RAD lo que podemos observar es muchas diferencias en las medias para cada categoría. Algo muy interesante es el cambio de la categoría 8 a 24. Para 8 de índice de accesibilidad a carreteras radiales se encuentran los valores más altos y para 24 se encuentran los valores más bajos.

Revisamos los diagramas de frecuencia para todas las variables cuantitativas

library(dplyr)
library(gridExtra)
library(tidyverse) # metapackage of all tidyverse packages
options(repr.plot.width=12, repr.plot.height=12)
f1 <- ggplot(data_r, aes(x=CRIM)) + geom_histogram()
f2 <- ggplot(data_r, aes(x=ZN)) + geom_histogram()
f3 <- ggplot(data_r, aes(x=INDUS)) + geom_histogram()
f4 <- ggplot(data_r, aes(x=NOX)) + geom_histogram()
f5 <- ggplot(data_r, aes(x=RM)) + geom_histogram()
f6 <- ggplot(data_r, aes(x=AGE)) + geom_histogram()
f7 <- ggplot(data_r, aes(x=DIS)) + geom_histogram()
f8 <- ggplot(data_r, aes(x=TAX)) + geom_histogram()
f9 <- ggplot(data_r, aes(x=PTRATIO)) + geom_histogram()
f10 <- ggplot(data_r, aes(x=B)) + geom_histogram()
f11 <- ggplot(data_r, aes(x=LSTAT)) + geom_histogram()
f12 <- ggplot(data_r, aes(x=MEDV)) + geom_histogram()
grid.arrange(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12, ncol=3, nrow=4)

A grandes rasgos podemos observar cada una del comportamiento de las variables numéricas. Veamos las gráficas de dispersión

options(repr.plot.width=12, repr.plot.height=12)
dis1 <- ggplot(data_r, aes(x=CRIM, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis2 <- ggplot(data_r, aes(x=ZN, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis3 <- ggplot(data_r, aes(x=INDUS, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis4 <- ggplot(data_r, aes(x=NOX, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis5 <- ggplot(data_r, aes(x=RM, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis6 <- ggplot(data_r, aes(x=AGE, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis7 <- ggplot(data_r, aes(x=DIS, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis8 <- ggplot(data_r, aes(x=TAX, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis9 <- ggplot(data_r, aes(x=PTRATIO, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis10 <- ggplot(data_r, aes(x=B, y=MEDV)) + geom_point()+ geom_smooth(method=lm)
dis11 <- ggplot(data_r, aes(x=LSTAT, y=MEDV)) + geom_point()+ geom_smooth(method=lm)

#grid.arrange(dis1,dis2,dis3,dis4,dis5,dis6,dis7,dis8,dis9,dis10,dis11, ncol=3, nrow=4)
grid.arrange(dis1,dis2,dis3,dis4, ncol=2, nrow=2)

grid.arrange(dis5,dis6,dis7,dis8, ncol=2, nrow=2)

grid.arrange(dis9,dis10,dis11,ncol=2, nrow=2)

library(corrplot)
## Warning: package 'corrplot' was built under R version 4.1.2
correlacion<-round(cor(data), 2)

corrplot(correlacion, method="number", type="upper")

Observando estas gráficas de dispersión y la tabla que muestra la correlación de Pearson. Existen dos variables numéricas que tienen una correlación de 0.7 y 0.74 que son RM Y LSTAT respectivamente.

El RM indica que el precio promedio de las casas son directamente proporcional al número de baños. Y LSTAT, con pendiente negativa indica que entre más grande es el porcentaje de estatus inferior de la población el precio es menor, en otras palabras el estatus es a simple vista un fuerte indicador lineal para valorar el precio de una casa.

Estas son las relaciones más fuertes en contraste con la variable de interés “MEDV” sin embargo en el gráfico vemos que DIS parece tener una fuerte relación lineal con INDUS, NOX y AGE con pendiente negativa.

  1. Proponga el mejor modelo de regresión lineal múltiple para la última columna de la base de datos (valor medio comercial de casas de uso residencial en miles de dólares).

Usando el método forward con RM como la variable independiente principal y haciendo varias combinaciones llegamos al siguiente modelo:

\(MEDV -> RM + B +PTRATIO\)

  1. Estime el modelo propuesto en el ítem anterior. Verifique sea estadísticamente significativo. Reporte los valores \(R^2\) , AIC, BIC de forma explícita.

Revisemos varios modelos:

modelo1 = lm(data = data, formula = MEDV~RM+B)
summary(modelo1)   
## 
## Call:
## lm(formula = MEDV ~ RM + B, data = data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -22.253  -2.718  -0.329   2.475  38.414 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -40.981101   2.608112 -15.713  < 2e-16 ***
## RM            8.685555   0.397283  21.862  < 2e-16 ***
## B             0.025032   0.003058   8.187 2.22e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 6.221 on 503 degrees of freedom
## Multiple R-squared:  0.5443, Adjusted R-squared:  0.5424 
## F-statistic: 300.3 on 2 and 503 DF,  p-value: < 2.2e-16
AIC(modelo1)       
## [1] 3290.853
BIC(modelo1)
## [1] 3307.759
modelo2 = lm(data = data, formula = MEDV~LSTAT+PTRATIO)
summary(modelo2)
## 
## Call:
## lm(formula = MEDV ~ LSTAT + PTRATIO, data = data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -12.2428  -3.6398  -0.8622   1.8790  26.9036 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept) 54.04682    2.24217  24.105   <2e-16 ***
## LSTAT       -0.82018    0.03883 -21.120   <2e-16 ***
## PTRATIO     -1.14525    0.12810  -8.941   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.78 on 503 degrees of freedom
## Multiple R-squared:  0.6067, Adjusted R-squared:  0.6051 
## F-statistic: 387.9 on 2 and 503 DF,  p-value: < 2.2e-16
AIC(modelo2)       
## [1] 3216.348
BIC(modelo2)       
## [1] 3233.254
ajuste = lm(data = data, formula = MEDV~RM+B+PTRATIO)
summary(ajuste)    
## 
## Call:
## lm(formula = MEDV ~ RM + B + PTRATIO, data = data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -17.347  -2.841  -0.279   2.174  38.904 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -11.422951   4.153203  -2.750  0.00617 ** 
## RM            7.506790   0.393880  19.059  < 2e-16 ***
## B             0.021438   0.002879   7.446 4.21e-13 ***
## PTRATIO      -1.130717   0.128821  -8.777  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5.798 on 502 degrees of freedom
## Multiple R-squared:  0.6049, Adjusted R-squared:  0.6025 
## F-statistic: 256.2 on 3 and 502 DF,  p-value: < 2.2e-16
AIC(ajuste)        
## [1] 3220.608
BIC(ajuste)        
## [1] 3241.74

Realizando un contraste de nuestro modelo (modelo3) se puede verificar por medio de los valores reportados \(R^2\), \(AIC\) y \(BIC\) que es mejor que el modelo 1 pero no del modelo 2. Sin embargo el criterio para su elección fueron los resultados obtenidos en las hipótesis para los supuestos.

Rechazamos la hipótesis nula y aceptamos que estos parámetros generan una tendencia. El \(R^2\) = 0.6025. De modo este modelo es capaz de explicar el 60.25% de la variabilidad en el precio de viviendas. El RSE = 5.798 indica que en promedio cualquier predicción se aleja 5.798 unidades del valor real. Así que si promediamos el MEDV tenemos 22.53281, RSE/mean(data_r$MEDV):

5.798/mean(data$MEDV)
## [1] 0.2573137

Se observa incrementos de entorno a un 25.73% del error debido al uso de este modelo

  1. Verifique los supuestos del modelo. Implemente análisis de Residuos (figuras), calcule y dibuje los residuos estudentizados.

  2. Reporte los p-valores de las pruebas de hipótesis que fueron usadas, además del planteamiento de tales pruebas.

options(repr.plot.width=5, repr.plot.height=5)
par(mfrow=c(2,2))
plot(ajuste)

- Valor esperado de los residuos

residuales <- residuals(ajuste)
mean(residuales)
## [1] 2.404289e-16

El valor esperado de los residuos es 0.

#install.packages("lmtest")
library(lmtest) 
## Warning: package 'lmtest' was built under R version 4.1.2
dwtest(ajuste)
## 
##  Durbin-Watson test
## 
## data:  ajuste
## DW = 0.79253, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

Como p_value es < 0.05 rechazamos H0 y validamos que la autocorrelación en los errores es mayor a 0.

library(lmtest) 
bptest(ajuste) 
## 
##  studentized Breusch-Pagan test
## 
## data:  ajuste
## BP = 4.5379, df = 3, p-value = 0.2089

Como p_value > 0.05 no tenemos evidencia suficiente para rechazar la hipótesis nula, así que el modelo cumple con multicolinealidad.

library(tseries)
## Warning: package 'tseries' was built under R version 4.1.2
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
jarque.bera.test(residuales)  #H0: Hay normalidad
## 
##  Jarque Bera Test
## 
## data:  residuales
## X-squared = 2138.4, df = 2, p-value < 2.2e-16
hist(residuales)

El p_value < 0.05. reachazamos la hipótesis nula, O sea que la distribución de los errores para cada punto de nuestro modelo no tiende a una distribución normal. Sin embargo al hacer el histograma de estos residuales vemos el comportamiento “normal”.

  1. ¿Existen datos atípicos, influyentes o que llamen su atención?

Cuánto están cambiando los valores ajustados cuando saco un punto de la base de datos

plot(dffits(ajuste), pch=23, bg='orange', cex=0.5, ylab="DFFITS")

umbral = 2*sqrt(4/dim(data)[1])
umbral
## [1] 0.1778217
data_at = data[which(dffits(ajuste) > umbral),]
DT::datatable(data_at)
dim(data[which(dffits(ajuste) > umbral),] %>% filter(MEDV == 50))[1]
## [1] 13

Hay 24 registros que si se sacan de la base de datos modifica significativamente los valores ajustados, sin embargo 13 registros tienen un MEDV = 50. siendo este el valor máximo que toma MEDV en todo el dataset, esto interesante puesto que en la toda base de datos sólo hay 16 registros que cumplen con este valor. Nos hace pensar que el tope máximo que los encuestadores tomaron para MEDV fue de 50 000 dólares y nos da curiosidad el contexto en ese momento para saber si hubo un criterio para elegir ese valor máximo.

Qué tanto cambia la función de regresión cuando se elimina un punto de la base de datos

plot(cooks.distance(ajuste), pch=23, bg='orange', cex=0.5, ylab="Cook's distance")

Para esta prueba se tienen 5 registros que impactan de manera significativa en la función del modelo.

Que tanto está cambiando cada parámetro cuando se elimina un punto de la base de datos

data_at =data[which(dfbetas(ajuste) > umbral),]
DT::datatable(data_at)
par(mfrow = c(2,2))
plot(dfbetas(ajuste)[,'RM'], pch=23, bg='orange', cex=0.5, ylab="DFBETA (RM)")
plot(dfbetas(ajuste)[,'B'], pch=23, bg='orange', cex=0.5, ylab="DFBETA (B)")
plot(dfbetas(ajuste)[,'PTRATIO'], pch=23, bg='orange', cex=0.5, ylab="DFBETA (PTRATIO)")
umbral = 2/sqrt(dim(data)[1])
umbral 
## [1] 0.08891084

La variable PTRATIO es más suceptible al cambio. Los registros presentan una variabilidad significativa para el intervalo de registros [350, 450].

  1. Interprete su modelo en términos de la variable que incluye

\[MEDV = \beta_0 + \beta_1 RM + \beta_2 B +\beta_3 PTRATIO\] \[-> MEDV = (-11.42 + 7.5 RM + 0.021 B - 1.131 PTRATIO)*1000 dolares\], interpretamos así:

  1. A partir del modelo, suponga algún valor para la variable respuesta y reporte un Intervalo de Confianza del 95% para el pronóstico de la variable respuesta
confint(ajuste)[1,]
##      2.5 %     97.5 % 
## -19.582754  -3.263149
confint(ajuste)[2,]
##    2.5 %   97.5 % 
## 6.732935 8.280646
confint(ajuste)[3,]
##      2.5 %     97.5 % 
## 0.01578150 0.02709418
confint(ajuste)[4,]
##      2.5 %     97.5 % 
## -1.3838121 -0.8776229

Nuestro modelo de regresión lineal estaría dado \[MEDV=([-19.582754, -3.263149 ]+[6.732935, 8.280646] * RM +[0.01578150, 0.02709418] * B \] \[+[-1.3838121, -0.8776229 ] * PTRATIO)* 1000\]$ Supongamos los RM = 5, B = 10, PTRATIO = 2

RM = 5
B = 10
PTRATIO = 2
c((-19.6+ 6.7 * RM + 0.016 * B -1.4 * PTRATIO)* 1000, (-3.26 + 8.28 * RM + 0.027*B -0.88)* 1000)
## [1] 11260 37530

Para una vivienda con 5 habitaciones, una proporción de afrodescendientes de 10 y una proporción alumno-maestro de 2 el valor promedio de la vivienda estará dentro del rango [11260, 37530] dólares