Informe de Regresion Multiple

En el presente documento trataremos el caso particular de maría una empresaria que apertura su inmobiliaria y necesita realizar un estudio para determinar posibilidades con dos casos particulares para una casa y un apartamento.


Este documento está dividido en los siguientes puntos:


1.Contexto
2.Pasos requeridos
3.Desarrollo de pasos Requeridos Vivienda 1
4.Desarrollo de pasos Requeridos Vivienda 2
5.Conclusiones


Dentro de estos numerales desarrollaremos los pasos requeridos para la determinación de las mejores recomendaciones para el caso de la inmobiliaria C&A.

1. Contexto

Caso C&A

“cali”
“cali”

Enunciado

Maria comenzó como agente de bienes raíces en Cali hace 10 años. Después de laborar dos años para una empresa nacional, se traslado a Bogotá y trabajó para otra agencia de bienes raíces. Sus amigos y familiares la convencieron de que con su experiencia y conocimientos del negocio debía abrir su propia agencia. Terminó por adquirir la licencia de intermediario y al poco tiempo fundó su propia compañía, C&A (Casas y Apartamentos) en Cali. Santiago y Lina, dos vendedores de la empresa anterior aceptaron trabajar en la nueva compaña. En la actualidad ocho agentes de bienes raíces colaboran con ella en C&A.


Actualmente las ventas de bienes raíces en Cali se han visto disminuidas de manera significativa en lo corrido del año. Durante este periodo muchas instituciones bancarias de ahorro y vivienda están prestando grandes sumas de dinero para la industria y la construcción comercial y residencial. Cuando el efecto producto de las tensiones políticas y sociales disminuya, se espera que la actividad económica de este sector se reactive.


Hace dos días, María recibió una carta solicitando asesoría para la compra de dos viviendas por parte de una compañía internacional que desea ubicar a dos de sus empleados con sus familias en la ciudad. Las solicitudes incluyen las siguientes condiciones:


“casos de estudio”
“casos de estudio”

Ayude a María a responder la solicitud, mediante técnicas modelación que usted conoce. Ella requiere le envíe un informe ejecutivo donde analice los dos casos y sus recomendaciones (Informe). Como soporte del informe debe anexar las estimaciones, validaciones y comparación de modelos requeridos (Anexos) .


2. Pasos requeridos


  1. Realice un filtro a la base de datos e incluya solo las ofertas de : base1: casas, de la zona norte de la ciudad. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta. (Adicional un mapa con los puntos de las bases. Discutir si todos los puntos se ubican en la zona correspondiente o se presentan valores en otras zonas, por que?).


  1. Realice un análisis exploratorio de datos enfocado en la correlación entre la variable respuesta (precio de la casa) en función del área construida, estrato, numero de baños, numero de habitaciones y zona donde se ubica la vivienda. Use gráficos interactivos con el paquete plotly e interprete los resultados.


  1. Estime un modelo de regresión lineal múltiple con las variables del punto anterior (precio = f(área construida, estrato, número de cuartos, número de parqueaderos, número de baños ) ) e interprete los coeficientes si son estadísticamente significativos. Las interpretaciones deber están contextualizadas y discutir si los resultados son lógicos. Adicionalmente interprete el coeficiente R2 y discuta el ajuste del modelo e implicaciones (que podrían hacer para mejorarlo).


  1. Realice la validación de supuestos del modelo e interprete los resultados (no es necesario corregir en caso de presentar problemas, solo realizar sugerencias de que se podría hacer).


  1. Con el modelo identificado debe predecir el precio de la vivienda con las características de la solicitud.


  1. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda Tenga encuenta que la empresa tiene crédito pre-aprobado de máximo 350 millones de pesos para la primera vivienda. Realice un análisis y presente en un mapa al menos 5 ofertas potenciales que debe discutir.


  1. Realice los pasos del 1 al 6. Para la segunda solicitud que tiene un crédito pre-aprobado por valor de $850 millones.


Entregable


como entregable se debera realizar un informe ejecutivo con anexos soporte de las estimaciones publicado en RPubs - el enlace debe entregarse en la plataforma Bs

3. Desarrollo de pasos Requeridos Vivienda 1

3.1. Realice un filtro a la base de datos e incluya solo las ofertas

procedemos a cargar la base de datos

#install.packages("devtools") # solo la primera vez
#devtools::install_github("dgonxalex80/paqueteMODELOS", force =TRUE)
#cargamos paquete de datos y data
library(paqueteMODELOS)
## Loading required package: boot
## Loading required package: broom
## Loading required package: GGally
## Loading required package: ggplot2
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
## Loading required package: gridExtra
## Loading required package: knitr
## Loading required package: summarytools
data("vivienda")

#mostramos los primeros 10 registros de la data
head(vivienda,10)
## # A tibble: 10 × 13
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  1147 Zona … <NA>        3     250        70            1      3            6
##  2  1169 Zona … <NA>        3     320       120            1      2            3
##  3  1350 Zona … <NA>        3     350       220            2      2            4
##  4  5992 Zona … 02          4     400       280            3      5            3
##  5  1212 Zona … 01          5     260        90            1      2            3
##  6  1724 Zona … 01          5     240        87            1      3            3
##  7  2326 Zona … 01          4     220        52            2      2            3
##  8  4386 Zona … 01          5     310       137            2      3            4
##  9  1209 Zona … 02          5     320       150            2      4            6
## 10  1592 Zona … 02          5     780       380            2      3            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
dim(vivienda)
## [1] 8322   13
#generamos lo tipos de datos
str(vivienda)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ id          : num [1:8322] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : chr [1:8322] NA NA NA "02" ...
##  $ estrato     : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
##  - attr(*, "spec")=List of 3
##   ..$ cols   :List of 13
##   .. ..$ id          : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ zona        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ piso        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ estrato     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ preciom     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ areaconst   : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ parqueaderos: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ banios      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ habitaciones: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ tipo        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ barrio      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ longitud    : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ latitud     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   ..$ default: list()
##   .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
##   ..$ delim  : chr ";"
##   ..- attr(*, "class")= chr "col_spec"
##  - attr(*, "problems")=<externalptr>

como podemos darnos cuent contamos con un total de 13 atributos y 8322 registros, ahroa procederemos a realizar la seleccion de la base del primer caso es decir tomaremos casas con una rea contruida mayor a 200 con 1 parquedero , 4 habitaciones, en estratos 4 y 5 en la zona norte y con un precio maximo de 350 millones

BaseSeleccionada = subset(vivienda, vivienda$tipo=="Casa" &  vivienda$zona=="Zona Norte")
head(BaseSeleccionada, 3)
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1209 Zona N… 02          5     320       150            2      4            6
## 2  1592 Zona N… 02          5     780       380            2      3            3
## 3  4057 Zona N… 02          6     750       445           NA      7            6
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
library(sqldf)
## Loading required package: gsubfn
## Loading required package: proto
## Loading required package: RSQLite
agrupacionzona=sqldf("SELECT zona, COUNT(*) as Freq FROM BaseSeleccionada GROUP BY zona")
agrupacionzona
##         zona Freq
## 1 Zona Norte  722
agrupaciontipo=sqldf("SELECT tipo, COUNT(*) as Freq FROM BaseSeleccionada GROUP BY tipo")
agrupaciontipo
##   tipo Freq
## 1 Casa  722
# Creación de mapa 
library(leaflet)
library(ggplot2)

#creamos el mapa de la distribucion de los datos
mapa_base1<-leaflet(BaseSeleccionada) %>%
 addTiles() %>%
 addCircleMarkers(lng=~longitud,lat=~latitud,radius=3)

mapa_base1

como podemows darnos cuenta existen un total de 722 registros que corresponden a casas en la zona norte , pero al momento de graficar su posicion teniendo en cuenta su latitud y longitud vemos que hay ubicaciones que se encuetnran por fuera de la zona norte de la ciudad de cali, esto prodria deberse al hecho de errores al momento de la toma de informacion o digitacion.

teniendo en cuenta lo anterior seria un grave error el tomar estos datos por lo que debemos realizar una re zonificacion de la base original teniendo en cuenta una hubicacion donde inice la zona norte de cali, para lo cual dividimos todo lo que este por encima de la longitud 3.460961 como zona norte esto se saca teniendo en cuenta que la zona norte llega hasta el sepraraor vial de la calle 25 y calle 26 en cali, para el caso de la zona sur tendremops todo lo que sea menor a 3.403935 y lo que se encuentre en medio sera declarado zona centro, este tipo de division se hace por motivos de facilitar el proceso de estudio pero lo correcto seria aplciar un modelo no supervisado de clasificacion, ya sea un random forest, perceptorenes multipaca

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
#generamos las nuevas zonas 
vivienda_zona_new<- vivienda %>% 
    dplyr::filter(areaconst >=0) %>%
    mutate(Nueva_Zona= case_when(latitud<=3.403935~"New Zona Sur", latitud>=3.460961~"New Zona Norte", latitud>3.403935&latitud<3.460961~"New Zona Centro" )) %>% 
    arrange(areaconst)


#generamos la nueva base
BaseSeleccionada = subset(vivienda_zona_new, vivienda_zona_new$tipo=="Casa" &  vivienda_zona_new$Nueva_Zona=="New Zona Norte")
head(BaseSeleccionada, 3)
## # A tibble: 3 × 14
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1   502 Zona N… <NA>        3     190        30            1      2            3
## 2   519 Zona N… 02          5     125        45           NA      2            3
## 3   628 Zona O… <NA>        3     100        53           NA      1            3
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>
#validamos los nuevos valores
agrupaciontiponew=sqldf("SELECT Nueva_Zona, COUNT(*) as Freq FROM BaseSeleccionada GROUP BY Nueva_Zona")
agrupaciontiponew
##       Nueva_Zona Freq
## 1 New Zona Norte  546
#volvemos a generar el mapa de distribuciones
# Creación de mapa 
library(leaflet)
library(ggplot2)

#creamos el mapa de la distribucion de los datos
mapa_base1<-leaflet(BaseSeleccionada) %>%
 addTiles() %>%
 addCircleMarkers(lng=~longitud,lat=~latitud,radius=3)

mapa_base1

como podemos observar existe una mejor distribucion de los inmuebles y se agregaron nuevos datos al proceso para el analisis

3.2. Realice un análisis exploratorio de datos enfocado en la correlación

antes de empezar con el analisis de correlaciones entre las variables realizaremos una pequeña validacion de la data para encontrar outliers y nulos

library(naniar)
# devtools::install_github("dgonxalex80/paqueteMODELOS", force = TRUE)
Faltantes = gg_miss_var(BaseSeleccionada, show_pct=TRUE)
Faltantes

#faltantesporcen=n_miss(vivienda_faltantes$id)
faltantesVar = naniar::miss_var_summary(BaseSeleccionada)
faltantesVar
## # A tibble: 14 × 3
##    variable     n_miss pct_miss
##    <chr>         <int>    <dbl>
##  1 piso            235     43.0
##  2 parqueaderos    183     33.5
##  3 id                0      0  
##  4 zona              0      0  
##  5 estrato           0      0  
##  6 preciom           0      0  
##  7 areaconst         0      0  
##  8 banios            0      0  
##  9 habitaciones      0      0  
## 10 tipo              0      0  
## 11 barrio            0      0  
## 12 longitud          0      0  
## 13 latitud           0      0  
## 14 Nueva_Zona        0      0
#subset de datos sin data
tr = subset(BaseSeleccionada, is.na(BaseSeleccionada$id))
tr
## # A tibble: 0 × 14
## # ℹ 14 variables: id <dbl>, zona <chr>, piso <chr>, estrato <dbl>,
## #   preciom <dbl>, areaconst <dbl>, parqueaderos <dbl>, banios <dbl>,
## #   habitaciones <dbl>, tipo <chr>, barrio <chr>, longitud <dbl>,
## #   latitud <dbl>, Nueva_Zona <chr>
p> Como podemos darnos cuenta la data presenta datos faltantes en gran medida en los atributos de piso y parqueaderos, pero todos los dem??s presentan datos faltantes, realizando el analisis, podemos observar que un 33% de la data de parqueaderos esta nula y piso el 43% esta nulo .

p> teniendo en cuenta los resultados obtenidos en los campos de parqueaderos y pisos se toman las siguientes determinaciones:

  1. debido a que el atribut o de piso no se va a utilizar como variables independientes y tiene un alto grado de nulidad, se decide eliminar el atributo
  2. para el caso de los parqueaderos imputaremos el dato y colocaremos la moda de este , aunque esto representara un desbalanceo del atributo parqueadero

#calculamos la moda de los paqueaderos
frecuencia_parqueaderos = data.frame(table(BaseSeleccionada$parqueaderos))
modaparq = frecuencia_parqueaderos[which.max(frecuencia_parqueaderos$Freq),1]
modaparq
## [1] 2
## Levels: 1 2 3 4 5 6 7 8 9 10
#modificamos los valores nulos de parqueaderos , ojo cmabiar el valor de 1 por la moda
BaseSeleccionada$parqueaderos= case_when( is.na(BaseSeleccionada$parqueaderos)  ~1 , !is.na(BaseSeleccionada$parqueaderos) ~ BaseSeleccionada$parqueaderos)

head(BaseSeleccionada)
## # A tibble: 6 × 14
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1   502 Zona N… <NA>        3     190        30            1      2            3
## 2   519 Zona N… 02          5     125        45            1      2            3
## 3   628 Zona O… <NA>        3     100        53            1      1            3
## 4   487 Zona N… 03          3     198        55            1      2            4
## 5   720 Zona N… 04          3     120        60            1      1            3
## 6   773 Zona N… <NA>        3     125        60            1      2            2
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>

Como siguiente paso eliminamos los datos duplicados de la siguiente forma

#prcedemos a dejar la base sin registros duplicados
#devtools::install_github("edzer/sp")
library(dplyr)
BaseSeleccionada = distinct(BaseSeleccionada)
BaseSeleccionada
## # A tibble: 546 × 14
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   502 Zona … <NA>        3     190        30            1      2            3
##  2   519 Zona … 02          5     125        45            1      2            3
##  3   628 Zona … <NA>        3     100        53            1      1            3
##  4   487 Zona … 03          3     198        55            1      2            4
##  5   720 Zona … 04          3     120        60            1      1            3
##  6   773 Zona … <NA>        3     125        60            1      2            2
##  7   573 Zona … 02          3     295        60            1      1            2
##  8   886 Zona … 10          4     165        60            1      2            2
##  9   313 Zona … <NA>        3     210        60            1      2            3
## 10   173 Zona … 02          3     150        60            1      2            3
## # ℹ 536 more rows
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>
#validamos los nuevos valores
agrupacion=sqldf("SELECT tipo, COUNT(*) as Freq FROM BaseSeleccionada GROUP BY tipo")
agrupacion
##   tipo Freq
## 1 Casa  546

luego de realizar el analisis de nulos procedemos a realizar el analisis de correlaciones entre las variables debido a que hay mucha diferencia entre las variables de precio y area construida creamos otras variables con el logaritmo, de esta forma aumentamos la confiabilidad de la matriz

#grafico normal de matriz de correlaciones
library(GGally)
library(ggcorrplot)
library(dplyr)
BaseSeleccionada$preciomlog=log(BaseSeleccionada$preciom)
BaseSeleccionada$areaconstlog=log(BaseSeleccionada$areaconst)

BaseSeleccionada
## # A tibble: 546 × 16
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   502 Zona … <NA>        3     190        30            1      2            3
##  2   519 Zona … 02          5     125        45            1      2            3
##  3   628 Zona … <NA>        3     100        53            1      1            3
##  4   487 Zona … 03          3     198        55            1      2            4
##  5   720 Zona … 04          3     120        60            1      1            3
##  6   773 Zona … <NA>        3     125        60            1      2            2
##  7   573 Zona … 02          3     295        60            1      1            2
##  8   886 Zona … 10          4     165        60            1      2            2
##  9   313 Zona … <NA>        3     210        60            1      2            3
## 10   173 Zona … 02          3     150        60            1      2            3
## # ℹ 536 more rows
## # ℹ 7 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>, preciomlog <dbl>, areaconstlog <dbl>
df2 = BaseSeleccionada %>%
   select( preciomlog, areaconstlog, estrato, parqueaderos,banios,habitaciones)


#graficamos la tabla de correlaciones
GGally::ggpairs(df2, title="Matriz de Correlaciones de Variables")

# install.packages("plotly")
# install.packages("ggcorrplot")
#correlaciones con gploty
dfn<-select(df2, estrato, preciomlog, areaconstlog, parqueaderos, banios, habitaciones)

r<-cor(dfn)

p<-ggcorrplot(r,type="lower",
           title="Correlaciones",
           colors=c("red","yellow","blue"),
           outline.color="black", ggtheme = theme_test() + theme(text = element_text(size = 7)))


plotly::ggplotly(p)

De los anteriores resultados obtenidos podemos inferir lo siguiente:

  1. el precio de mercado tiene una correlacion alta con el area contruida debido a que cuenta con un valor de 82.8%
  2. el precio de mercado tiene una correlacion alta con la cantidad de baños debido a que cuenta con un valor de 63.6%
  3. el precio de mercado tiene una correlacion baja con los atributos de parquederos y habitaciones.
  4. no se analiza la zona debido a que todos los inmuebles se encuentran en la zona Norte

3.3. Estime un modelo de regresión lineal múltiple con las variables

Ahora procederemos a calcular el modelo lineal multiple y generaremos los coeficientes del modelo, para lo cual crearemos unas variabbles dummy que permiten trabajar con el modelo

BaseSeleccionada$estrato4<-as.numeric(BaseSeleccionada$estrato==4)  
BaseSeleccionada$estrato5<-as.numeric(BaseSeleccionada$estrato==5)  
BaseSeleccionada$estrato6<-as.numeric(BaseSeleccionada$estrato==6)

#calculamos el modelo sin separar los estratos
modelobase <- lm(preciomlog ~ areaconstlog+ habitaciones+ parqueaderos + banios+ estrato , data = BaseSeleccionada)
summary(modelobase)
## 
## Call:
## lm(formula = preciomlog ~ areaconstlog + habitaciones + parqueaderos + 
##     banios + estrato, data = BaseSeleccionada)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.68578 -0.16295 -0.02156  0.13947  1.21121 
## 
## Coefficients:
##                Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   2.3315494  0.1033589  22.558  < 2e-16 ***
## areaconstlog  0.4775141  0.0258218  18.493  < 2e-16 ***
## habitaciones -0.0006772  0.0088085  -0.077  0.93875    
## parqueaderos  0.0373387  0.0096861   3.855  0.00013 ***
## banios        0.0623635  0.0118634   5.257 2.11e-07 ***
## estrato       0.1716794  0.0156646  10.960  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2599 on 540 degrees of freedom
## Multiple R-squared:  0.787,  Adjusted R-squared:  0.785 
## F-statistic: 399.1 on 5 and 540 DF,  p-value: < 2.2e-16
#modelo completo
modelobase <- lm(preciomlog ~ areaconstlog+ habitaciones+ parqueaderos + banios+ estrato4+ estrato5+ estrato6 , data = BaseSeleccionada)
summary(modelobase)
## 
## Call:
## lm(formula = preciomlog ~ areaconstlog + habitaciones + parqueaderos + 
##     banios + estrato4 + estrato5 + estrato6, data = BaseSeleccionada)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.68201 -0.15530 -0.02235  0.14936  1.21673 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  2.850983   0.112661  25.306  < 2e-16 ***
## areaconstlog 0.475899   0.025735  18.492  < 2e-16 ***
## habitaciones 0.002351   0.008810   0.267  0.78967    
## parqueaderos 0.036585   0.009623   3.802  0.00016 ***
## banios       0.055875   0.011963   4.671 3.80e-06 ***
## estrato4     0.235686   0.034060   6.920 1.29e-11 ***
## estrato5     0.332559   0.033107  10.045  < 2e-16 ***
## estrato6     0.624307   0.063886   9.772  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2581 on 538 degrees of freedom
## Multiple R-squared:  0.7908, Adjusted R-squared:  0.7881 
## F-statistic: 290.6 on 7 and 538 DF,  p-value: < 2.2e-16
#creamos un modelos con los valores originales para ser usado en las prediciones
modeloPrediccion <- lm(preciom ~ areaconst+ habitaciones+ parqueaderos + banios+ estrato4+ estrato5+ estrato6 , data = BaseSeleccionada)

Ahora procederemos a realizar una estimacion paso a paso mediante el metodo Steppwise

modelo_b0<- lm(preciom ~ 1, data=BaseSeleccionada) # modelo y= b0
modelo_all <- lm(preciomlog ~ areaconstlog+ habitaciones+ parqueaderos + banios+  estrato4+ estrato5+ estrato6 , data=BaseSeleccionada) # modelo con todas las variables independientes
forward <- step(modelo_b0, direction='forward', scope=formula(modelo_all), trace=0)

# Visualización de los resultados 
forward$anova
##             Step Df   Deviance Resid. Df Resid. Dev      AIC
## 1                NA         NA       545   33949422 6028.619
## 2 + areaconstlog -1 18754732.1       544   15194690 5591.675
## 3     + estrato6 -1  2572070.0       543   12622620 5492.417
## 4 + parqueaderos -1   782436.2       542   11840184 5459.477
## 5     + estrato5 -1   302413.2       541   11537771 5447.351
## 6       + banios -1   240708.9       540   11297062 5437.839
## 7     + estrato4 -1    98793.6       539   11198268 5435.043
summary(forward)
## 
## Call:
## lm(formula = preciom ~ areaconstlog + estrato6 + parqueaderos + 
##     estrato5 + banios + estrato4, data = BaseSeleccionada)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -458.55  -76.76  -17.56   50.85  990.68 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -813.217     62.307 -13.052  < 2e-16 ***
## areaconstlog  200.165     13.738  14.570  < 2e-16 ***
## estrato6      359.895     34.024  10.578  < 2e-16 ***
## parqueaderos   24.483      5.372   4.558 6.41e-06 ***
## estrato5       74.955     17.383   4.312 1.92e-05 ***
## banios         17.445      5.661   3.081  0.00217 ** 
## estrato4       40.030     18.357   2.181  0.02964 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 144.1 on 539 degrees of freedom
## Multiple R-squared:  0.6701, Adjusted R-squared:  0.6665 
## F-statistic: 182.5 on 6 and 539 DF,  p-value: < 2.2e-16

los dos modelos tienen una buena explicacion por medio de los modelos en el caso del primer modelo para casas tiene un R que es capaz de explicarlo en un 79% separando los estratos y para el caso de la estimacion paso a paso mediante el metodo Steppwise este nos indica que el modelo deberia realizarce con casi todas las variables sin tener en cuenta las habitaciones, para el mejoramiento de estos resultados podriamos ver la opcion de normalizar los datos de areacontruida y precio para que tenga un mejor manejo de los outliers, este proceso se realizo y se coloco en las columnas de preciomlog y areaconslog

3.4. Realice la validación de supuestos del modelo e interprete los resultados

Ahora realizaremos la validacion de supuestos del modelo

#validamos los suspuestos del modelo
par(mfrow = c(2, 2))
plot(modelobase)

de las anteriores graficas podemos determinar lo siguiente:

  1. teniendo en cuenta la grafica de residualVsfitted y scale-location permiten apreciar que la varianza es poco normal, esto debido a los proceso de limpieza que se realizaron a la data antes del proceso de modelado.

  2. la grafica de normalidad muestra que los residuales tienen un buen ajuste

3.5. Con el modelo identificado debe predecir el precio de la vivienda con las características de la solicitud

ahora procederemos a predecir el precio de la vivienda para las caracterisitcas deseadas

predict(modeloPrediccion, data.frame(areaconst=200, estrato4=1, estrato5=0, estrato6=0, parqueaderos=1, banios=2, habitaciones=4 ),interval = "confidence")
##        fit      lwr      upr
## 1 322.0662 290.5816 353.5509
predict(modeloPrediccion, data.frame(areaconst=200, estrato4=0, estrato5=1, estrato6=0, parqueaderos=1, banios=2, habitaciones=4 ),interval = "confidence")
##        fit      lwr      upr
## 1 360.4805 332.1304 388.8307

teniendo en cuenta lo anterior podemos apreciar que el precio para una casa en la zona norte, teniendo en cuenta las especificaciones del primer caso, oscila aproximadamente entre 290.5 y 353.5 millones de pesos, para el estrato 4 y para el estrato 5 el precio oscila entre 332.1 y 388 millones de pesos

3.6. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda

teniendo en cuenta que para nuestra primera solicitud se tiene un prestamos aprobado de 350 millones y se brindara 5 posibles casas, pero primero generamos todas las posibilidades.

library(dplyr)
casa = filter(BaseSeleccionada, areaconst <= 200, parqueaderos <= 1, banios <= 2, habitaciones <= 4, Nueva_Zona == "New Zona Norte", estrato %in% c(4, 5), preciom <= 350)
casa
## # A tibble: 14 × 19
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   519 Zona … 02          5     125       45             1      2            3
##  2   886 Zona … 10          4     165       60             1      2            2
##  3   346 Zona … <NA>        4     170       77             1      2            2
##  4   493 Zona … <NA>        4     190       86             1      2            3
##  5  1183 Zona … 03          5     300      100             1      2            3
##  6  1073 Zona … <NA>        4     280      104.            1      2            3
##  7  1666 Zona … 02          4     275      120             1      2            4
##  8   406 Zona … 03          4     170      120             1      2            3
##  9   364 Zona … 03          4     160      120             1      2            3
## 10   410 Zona … 03          4     160      120             1      2            3
## 11   411 Zona … 03          4     170      120             1      2            3
## 12   420 Zona … 03          4     160      120             1      2            3
## 13  1008 Zona … <NA>        4     215      144.            1      2            4
## 14    93 Zona … 03          4     265      162             1      2            4
## # ℹ 10 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>, preciomlog <dbl>, areaconstlog <dbl>, estrato4 <dbl>,
## #   estrato5 <dbl>, estrato6 <dbl>

como podemos darnos cuenta contamos con un total de 14 posibilidades que cubren las necescidades especificas, ademas se aclara que para las necesidades especificas no existen registros, pero trabajaremos con rangos cercanos a las necesidades sin pasarnos de los estipulado por la empresa cliente

las casa seleccionadas para este proceso son las de codigos 93(se selecciona por que es la mas grande), 1008 (se selecciona por que es la seguna mas grande), 1183 (se selecciona para tener posibilidades en otro estrato), 519 (se selecciona para tener posibilidades en otro estrato) y 1666 (es una de las que mas se acerca a las necesidades estipuladas por la empresa)

viviendas_propuestas_base<- BaseSeleccionada %>% 
    dplyr::filter(id %in% c(93,1008,1183,519,1666)) %>% 
    mutate(diferencia_cupo=350-preciom, precio_m2=preciom/areaconst) %>% 
    arrange(precio_m2)

viviendas_propuestas_base
## # A tibble: 5 × 21
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1008 Zona N… <NA>        4     215      144.            1      2            4
## 2    93 Zona O… 03          4     265      162             1      2            4
## 3  1666 Zona N… 02          4     275      120             1      2            4
## 4   519 Zona N… 02          5     125       45             1      2            3
## 5  1183 Zona O… 03          5     300      100             1      2            3
## # ℹ 12 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>, preciomlog <dbl>, areaconstlog <dbl>, estrato4 <dbl>,
## #   estrato5 <dbl>, estrato6 <dbl>, diferencia_cupo <dbl>, precio_m2 <dbl>

por ultimo procedemos a visualizar donde se encuentran ubicadas cada una de las opciones de casas en la zona norte

# Creación de mapa con flecha de norte y barra de escala
library(leaflet)
library(sf)
## Linking to GEOS 3.11.2, GDAL 3.7.2, PROJ 9.3.0; sf_use_s2() is TRUE
library(ggplot2)
mapa_opciones<-leaflet(viviendas_propuestas_base) %>%
 addTiles() %>%
 addCircleMarkers(lng=~longitud,lat=~latitud,radius=7)

mapa_opciones

4. Desarrollo de pasos Requeridos Vivienda 2

4.1. Realice un filtro a la base de datos e incluya solo las ofertas

procedemos a cargar la base de datos y validar los tipos de datos

#generamos lo tipos de datos
str(vivienda)
## spc_tbl_ [8,322 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ id          : num [1:8322] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8322] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : chr [1:8322] NA NA NA "02" ...
##  $ estrato     : num [1:8322] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8322] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8322] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8322] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8322] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8322] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8322] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8322] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8322] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8322] 3.43 3.43 3.44 3.44 3.46 ...
##  - attr(*, "spec")=List of 3
##   ..$ cols   :List of 13
##   .. ..$ id          : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ zona        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ piso        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ estrato     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ preciom     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ areaconst   : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ parqueaderos: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ banios      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ habitaciones: list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ tipo        : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ barrio      : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_character" "collector"
##   .. ..$ longitud    : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   .. ..$ latitud     : list()
##   .. .. ..- attr(*, "class")= chr [1:2] "collector_double" "collector"
##   ..$ default: list()
##   .. ..- attr(*, "class")= chr [1:2] "collector_guess" "collector"
##   ..$ delim  : chr ";"
##   ..- attr(*, "class")= chr "col_spec"
##  - attr(*, "problems")=<externalptr>

como podemos darnos cuent contamos con un total de 13 atributos y 8322 registros, ahroa procederemos a realizar la seleccion de la base del primer caso es decir tomaremos casas con una rea contruida mayor a 200 con 1 parquedero , 4 habitaciones, en estratos 4 y 5 en la zona norte y con un precio maximo de 350 millones

BaseSeleccionadaAPT = subset(vivienda, vivienda$tipo=="Apartamento" &  vivienda$zona=="Zona Sur")
head(BaseSeleccionadaAPT, 3)
## # A tibble: 3 × 13
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  5098 Zona S… 05          4     290        96            1      2            3
## 2   698 Zona S… 02          3      78        40            1      1            2
## 3  8199 Zona S… <NA>        6     875       194            2      5            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>
library(sqldf)
agrupacionzona=sqldf("SELECT zona, COUNT(*) as Freq FROM BaseSeleccionadaAPT GROUP BY zona")
agrupacionzona
##       zona Freq
## 1 Zona Sur 2787
agrupaciontipo=sqldf("SELECT tipo, COUNT(*) as Freq FROM BaseSeleccionadaAPT GROUP BY tipo")
agrupaciontipo
##          tipo Freq
## 1 Apartamento 2787
# Creación de mapa 
library(leaflet)
library(ggplot2)

#creamos el mapa de la distribucion de los datos
mapa_base1<-leaflet(BaseSeleccionadaAPT) %>%
 addTiles() %>%
 addCircleMarkers(lng=~longitud,lat=~latitud,radius=3)

mapa_base1

como podemows darnos cuenta existen un total de 2787 registros que corresponden a Apartamentos en la zona sur , pero al momento de graficar su posicion teniendo en cuenta su latitud y longitud vemos que hay ubicaciones que se encuentran por fuera de la zona sur de la ciudad de cali, esto prodria deberse al hecho de errores al momento de la toma de informacion o digitacion.

teniendo en cuenta lo anterior seria un grave error el tomar estos datos por lo que debemos realizar una re zonificacion de la base original teniendo en cuenta una hubicacion donde inice la zona norte de cali, para lo cual dividimos todo lo que este por encima de la longitud 3.460961 como zona norte esto se saca teniendo en cuenta que la zona norte llega hasta el sepraraor vial de la calle 25 y calle 26 en cali, para el caso de la zona sur tendremops todo lo que sea menor a 3.403935 y lo que se encuentre en medio sera declarado zona centro, este tipo de division se hace por motivos de facilitar el proceso de estudio pero lo correcto seria aplciar un modelo no supervisado de clasificacion, ya sea un random forest, perceptorenes multipaca

library(dplyr)

#generamos las nuevas zonas 
vivienda_zona_new<- vivienda %>% 
    dplyr::filter(areaconst >=0) %>%
    mutate(Nueva_Zona= case_when(latitud<=3.403935~"New Zona Sur", latitud>=3.460961~"New Zona Norte", latitud>3.403935&latitud<3.460961~"New Zona Centro" )) %>% 
    arrange(areaconst)


#generamos la nueva base
BaseSeleccionadaAPT = subset(vivienda_zona_new, vivienda_zona_new$tipo=="Apartamento" &  vivienda_zona_new$Nueva_Zona=="New Zona Sur")
head(BaseSeleccionadaAPT, 3)
## # A tibble: 3 × 14
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1   698 Zona S… 02          3      78        40            1      1            2
## 2  6007 Zona S… <NA>        4     108        40           NA      1            1
## 3  7656 Zona S… <NA>        3     110        44           NA      2            2
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>
#validamos los nuevos valores
agrupaciontiponew=sqldf("SELECT Nueva_Zona, COUNT(*) as Freq FROM BaseSeleccionadaAPT GROUP BY Nueva_Zona")
agrupaciontiponew
##     Nueva_Zona Freq
## 1 New Zona Sur 2145
#volvemos a generar el mapa de distribuciones
# Creación de mapa 
library(leaflet)
library(ggplot2)

#creamos el mapa de la distribucion de los datos
mapa_base1<-leaflet(BaseSeleccionadaAPT) %>%
 addTiles() %>%
 addCircleMarkers(lng=~longitud,lat=~latitud,radius=3)

mapa_base1

como podemos observar existe una mejor distribucion de los inmuebles y se agregaron nuevos datos al proceso para el analisis

4.2. Realice un análisis exploratorio de datos enfocado en la correlación

antes de empezar con el analisis de correlaciones entre las variables realizaremos una pequeña validacion de la data para encontrar outliers y nulos

library(naniar)
# devtools::install_github("dgonxalex80/paqueteMODELOS", force = TRUE)
Faltantes = gg_miss_var(BaseSeleccionadaAPT, show_pct=TRUE)
Faltantes

#faltantesporcen=n_miss(vivienda_faltantes$id)
faltantesVar = naniar::miss_var_summary(BaseSeleccionadaAPT)
faltantesVar
## # A tibble: 14 × 3
##    variable     n_miss pct_miss
##    <chr>         <int>    <dbl>
##  1 piso            528     24.6
##  2 parqueaderos    339     15.8
##  3 id                0      0  
##  4 zona              0      0  
##  5 estrato           0      0  
##  6 preciom           0      0  
##  7 areaconst         0      0  
##  8 banios            0      0  
##  9 habitaciones      0      0  
## 10 tipo              0      0  
## 11 barrio            0      0  
## 12 longitud          0      0  
## 13 latitud           0      0  
## 14 Nueva_Zona        0      0
#subset de datos sin data
tr = subset(BaseSeleccionadaAPT, is.na(BaseSeleccionadaAPT$id))
tr
## # A tibble: 0 × 14
## # ℹ 14 variables: id <dbl>, zona <chr>, piso <chr>, estrato <dbl>,
## #   preciom <dbl>, areaconst <dbl>, parqueaderos <dbl>, banios <dbl>,
## #   habitaciones <dbl>, tipo <chr>, barrio <chr>, longitud <dbl>,
## #   latitud <dbl>, Nueva_Zona <chr>
p> Como podemos darnos cuenta la data presenta datos faltantes en gran medida en los atributos de piso y parqueaderos, pero todos los demas no presentan datos faltantes, realizando el analisis, podemos observar que un 15% de la data de parqueaderos esta nula y piso el 24% esta nulo .

p> teniendo en cuenta los resultados obtenidos en los campos de parqueaderos y pisos se toman las siguientes determinaciones:

  1. debido a que el atributo de piso no se va a utilizar como variables independientes y tiene un alto grado de nulidad, se decide eliminar el atributo
  2. para el caso de los parqueaderos imputaremos el dato y colocaremos la moda de este , aunque esto representara un desbalanceo del atributo parqueadero

#calculamos la moda de los paqueaderos
frecuencia_parqueaderos = data.frame(table(BaseSeleccionadaAPT$parqueaderos))
modaparq = frecuencia_parqueaderos[which.max(frecuencia_parqueaderos$Freq),1]
modaparq
## [1] 1
## Levels: 1 2 3 4 10
#modificamos los valores nulos de parqueaderos , ojo cmabiar el valor de 1 por la moda
BaseSeleccionadaAPT$parqueaderos= case_when( is.na(BaseSeleccionadaAPT$parqueaderos)  ~2 , !is.na(BaseSeleccionadaAPT$parqueaderos) ~ BaseSeleccionadaAPT$parqueaderos)

head(BaseSeleccionadaAPT)
## # A tibble: 6 × 14
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1   698 Zona S… 02          3      78        40            1      1            2
## 2  6007 Zona S… <NA>        4     108        40            2      1            1
## 3  7656 Zona S… <NA>        3     110        44            2      2            2
## 4  5873 Zona O… <NA>        5      89        44            1      1            2
## 5  1998 Zona S… 03          5     130        45            1      2            2
## 6  1485 Zona S… 07          4     145        45            2      2            2
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>

Como siguiente paso eliminamos los datos duplicados de la siguiente forma

#prcedemos a dejar la base sin registros duplicados
#devtools::install_github("edzer/sp")
library(dplyr)
BaseSeleccionadaAPT = distinct(BaseSeleccionadaAPT)
BaseSeleccionadaAPT
## # A tibble: 2,145 × 14
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   698 Zona … 02          3      78        40            1      1            2
##  2  6007 Zona … <NA>        4     108        40            2      1            1
##  3  7656 Zona … <NA>        3     110        44            2      2            2
##  4  5873 Zona … <NA>        5      89        44            1      1            2
##  5  1998 Zona … 03          5     130        45            1      2            2
##  6  1485 Zona … 07          4     145        45            2      2            2
##  7  1990 Zona … 06          4     140        45            1      1            2
##  8  8027 Zona … <NA>        4      78        46            1      1            2
##  9   793 Zona … 05          4     121        47            2      1            2
## 10  8219 Zona … <NA>        3      87        47            2      1            3
## # ℹ 2,135 more rows
## # ℹ 5 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>
#validamos los nuevos valores
agrupacion=sqldf("SELECT tipo, COUNT(*) as Freq FROM BaseSeleccionadaAPT GROUP BY tipo")
agrupacion
##          tipo Freq
## 1 Apartamento 2145

luego de realizar el analisis de nulos procedemos a realizar el analisis de correlaciones entre las variables

BaseSeleccionadaAPT$preciomlog=log(BaseSeleccionadaAPT$preciom)
BaseSeleccionadaAPT$areaconstlog=log(BaseSeleccionadaAPT$areaconst)

BaseSeleccionadaAPT
## # A tibble: 2,145 × 16
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1   698 Zona … 02          3      78        40            1      1            2
##  2  6007 Zona … <NA>        4     108        40            2      1            1
##  3  7656 Zona … <NA>        3     110        44            2      2            2
##  4  5873 Zona … <NA>        5      89        44            1      1            2
##  5  1998 Zona … 03          5     130        45            1      2            2
##  6  1485 Zona … 07          4     145        45            2      2            2
##  7  1990 Zona … 06          4     140        45            1      1            2
##  8  8027 Zona … <NA>        4      78        46            1      1            2
##  9   793 Zona … 05          4     121        47            2      1            2
## 10  8219 Zona … <NA>        3      87        47            2      1            3
## # ℹ 2,135 more rows
## # ℹ 7 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>, preciomlog <dbl>, areaconstlog <dbl>
df2 = BaseSeleccionadaAPT %>%
   select( preciomlog, areaconstlog, estrato, parqueaderos,banios,habitaciones)
#grafico normal de matriz de correlaciones
library(GGally)
library(ggcorrplot)
GGally::ggpairs(df2, title="Matriz de correlaciones Apartementos")

# install.packages("plotly")
# install.packages("ggcorrplot")
#correlaciones con gploty
dfn<-select(df2, estrato, preciomlog, areaconstlog, parqueaderos, banios, habitaciones)

r<-cor(dfn)

p<-ggcorrplot(r,type="lower",
           title="Correlaciones",
           colors=c("red","yellow","blue"),
           outline.color="black", ggtheme = theme_test() + theme(text = element_text(size = 7)))


plotly::ggplotly(p)

De los anteriores resultados obtenidos podemos inferir lo siguiente:

  1. el precio de mercado tiene una correlacion alta con el area contruida debido a que cuenta con un valor de 87.3%
  2. el precio de mercado tiene una correlacion alta con la cantidad de baños debido a que cuenta con un valor de 76.6%
  3. el precio de mercado tiene una correlacion baja con el atributos de parquederos debido a que cuenta con un valor de 48%
  4. el precio de mercado tiene una correlacion baja con el atributos de habitaciones.
  5. no se analiza la zona debido a que todos los inmuebles se encuentran en la zona Norte

4.3. Estime un modelo de regresión lineal múltiple con las variables

Ahora procederemos a calcular el modelo lineal multiple y generaremos los coeficientes del modelo

BaseSeleccionadaAPT$estrato4<-as.numeric(BaseSeleccionadaAPT$estrato==4)  
BaseSeleccionadaAPT$estrato5<-as.numeric(BaseSeleccionadaAPT$estrato==5)  
BaseSeleccionadaAPT$estrato6<-as.numeric(BaseSeleccionadaAPT$estrato==6)

#calculamos el modelo sin separar los estratos
modelobase <- lm(preciomlog ~ areaconstlog+ habitaciones+ parqueaderos + banios+ estrato , data = BaseSeleccionadaAPT)
summary(modelobase)
## 
## Call:
## lm(formula = preciomlog ~ areaconstlog + habitaciones + parqueaderos + 
##     banios + estrato, data = BaseSeleccionadaAPT)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.83249 -0.11398  0.00466  0.12977  0.74281 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   1.226757   0.064654  18.974  < 2e-16 ***
## areaconstlog  0.707711   0.019353  36.569  < 2e-16 ***
## habitaciones -0.031204   0.008559  -3.646 0.000273 ***
## parqueaderos  0.038603   0.007879   4.900 1.03e-06 ***
## banios        0.080300   0.007827  10.259  < 2e-16 ***
## estrato       0.214336   0.007027  30.501  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.203 on 2139 degrees of freedom
## Multiple R-squared:  0.8544, Adjusted R-squared:  0.8541 
## F-statistic:  2511 on 5 and 2139 DF,  p-value: < 2.2e-16
modelobase <- lm(preciomlog ~ areaconstlog+ habitaciones+ parqueaderos + banios+ estrato4+ estrato5+ estrato6 , data = BaseSeleccionadaAPT)
summary(modelobase)
## 
## Call:
## lm(formula = preciomlog ~ areaconstlog + habitaciones + parqueaderos + 
##     banios + estrato4 + estrato5 + estrato6, data = BaseSeleccionadaAPT)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1.82404 -0.11739  0.01046  0.13240  0.79915 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   1.764514   0.071420  24.706  < 2e-16 ***
## areaconstlog  0.720356   0.019225  37.470  < 2e-16 ***
## habitaciones -0.023175   0.008519  -2.721  0.00657 ** 
## parqueaderos  0.033235   0.008031   4.138 3.64e-05 ***
## banios        0.068539   0.007886   8.692  < 2e-16 ***
## estrato4      0.305962   0.019799  15.453  < 2e-16 ***
## estrato5      0.457312   0.020597  22.203  < 2e-16 ***
## estrato6      0.735758   0.024753  29.724  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2004 on 2137 degrees of freedom
## Multiple R-squared:  0.8582, Adjusted R-squared:  0.8578 
## F-statistic:  1848 on 7 and 2137 DF,  p-value: < 2.2e-16
modeloprediccion2 <- lm(preciom ~ areaconst+ habitaciones+ parqueaderos + banios+ estrato4+ estrato5+ estrato6 , data = BaseSeleccionadaAPT)

Ahora procederemos a realizar una estimacion paso a paso mediante el metodo Steppwise

modelo_b0<- lm(preciom ~ 1, data=BaseSeleccionadaAPT) # modelo y= b0
modelo_all <- lm(preciomlog ~ areaconstlog+ habitaciones+ parqueaderos + banios+ estrato4+ estrato5+ estrato6, data=BaseSeleccionadaAPT) # modelo con todas las variables independientes
forward <- step(modelo_b0, direction='forward', scope=formula(modelo_all), trace=0)

# Visualización de los resultados 
forward$anova
##             Step Df    Deviance Resid. Df Resid. Dev      AIC
## 1                NA          NA      2144   94976213 22949.73
## 2 + areaconstlog -1 65870237.97      2143   29105975 20414.87
## 3     + estrato6 -1  6767960.93      2142   22338014 19849.19
## 4 + parqueaderos -1  1514673.42      2141   20823341 19700.58
## 5       + banios -1   728051.91      2140   20095289 19626.24
## 6 + habitaciones -1   349583.97      2139   19745705 19590.60
## 7     + estrato5 -1    25136.20      2138   19720569 19589.87
## 8     + estrato4 -1    56664.96      2137   19663904 19585.69
summary(forward)
## 
## Call:
## lm(formula = preciom ~ areaconstlog + estrato6 + parqueaderos + 
##     banios + habitaciones + estrato5 + estrato4, data = BaseSeleccionadaAPT)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -616.85  -40.94    3.99   37.00  893.72 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)  -1042.962     34.185 -30.510  < 2e-16 ***
## areaconstlog   270.302      9.202  29.375  < 2e-16 ***
## estrato6       160.336     11.848  13.533  < 2e-16 ***
## parqueaderos    44.602      3.844  11.603  < 2e-16 ***
## banios          35.816      3.774   9.489  < 2e-16 ***
## habitaciones   -23.581      4.077  -5.784 8.39e-09 ***
## estrato5        29.365      9.858   2.979  0.00293 ** 
## estrato4        23.517      9.477   2.482  0.01316 *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 95.93 on 2137 degrees of freedom
## Multiple R-squared:  0.793,  Adjusted R-squared:  0.7923 
## F-statistic:  1169 on 7 and 2137 DF,  p-value: < 2.2e-16

los dos modelos tienen una buena explicacion por medio de los modelos en el caso del segundo modelo para apartamentoses es aun mejor que el primer modelo d por lo que alcanza a tener un R de 85% , para el mejoramiento de estos resultados podriamos ver la opcion de normalizar los datos de areacontruida y precio para que tenga un mejor manejo de los outliers, esto fue realizado y se tuvo un muy bien R cuadrado, y teniendo en cuenta el metodo Steppwise deberieamos realizar e lmodelo con todfas las variables

Ahora realizaremos la validacion de supuestos del modelo

#validamos los suspuestos del modelo
par(mfrow = c(2, 2))
plot(modelobase)

de las anteriores graficas podemos determinar lo siguiente:

  1. teniendo en cuenta la grafica de residual Vs fitted y scale-location permiten apreciar que la varianza es normal, esto debido a los proceso de limpieza que se realizaron a la data antes del proceso de modelado.

  2. la grafica de normalidad muestra que los residuales tienen un buen ajuste

4.5. Con el modelo identificado debe predecir el precio de la vivienda con las características de la solicitud

ahora procederemos a predecir el precio de la vivienda para las caracterisitcas deseadas

predict(modeloprediccion2, data.frame(areaconst=300, estrato4=0, estrato5=1, estrato6=0, parqueaderos=3, banios=3, habitaciones=5 ),interval = "confidence")
##        fit      lwr      upr
## 1 670.8884 645.5841 696.1927
predict(modeloprediccion2, data.frame(areaconst=300, estrato4=0, estrato5=0, estrato6=1, parqueaderos=3, banios=3, habitaciones=5 ),interval = "confidence")
##        fit      lwr      upr
## 1 816.4451 791.2794 841.6107

teniendo en cuenta lo anterior podemos apreciar que el precio para un apartamento en la zona norte, teniendo en cuenta las especificaciones del primer caso, oscila aproximadamente entre 645.58 y 696.19 millones de pesos para el estrato 5 y para el estrato 6 el precio oscila entre 791.27 y 841.61 millones de pesos

4.6. Con las predicciones del modelo sugiera potenciales ofertas que responda a la solicitud de la vivienda

teniendo en cuenta que para nuestra primera solicitud se tiene un prestamos aprobado de 350 millones y se brindara 5 posibles Apartamentos, pero primero generamos todas las posibilidades.

library(dplyr)
Apartamento = filter(BaseSeleccionadaAPT, areaconst <= 300, parqueaderos <= 3, banios <= 3, habitaciones <= 5, Nueva_Zona == "New Zona Sur", estrato %in% c(5,6), preciom <= 850)
Apartamento
## # A tibble: 943 × 19
##       id zona   piso  estrato preciom areaconst parqueaderos banios habitaciones
##    <dbl> <chr>  <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1  5873 Zona … <NA>        5      89      44              1      1            2
##  2  1998 Zona … 03          5     130      45              1      2            2
##  3  3551 Zona … <NA>        5     245      50              1      1            1
##  4  1639 Zona … 06          5     155      50              1      1            2
##  5  3621 Zona … 05          6     245      50.3            2      1            1
##  6  1635 Zona … <NA>        5     147      51              1      2            3
##  7  1619 Zona … 02          5     155      52              2      2            2
##  8  1875 Zona … 02          6     128      55              2      2            2
##  9  7694 Zona … 06          5     219      55              2      2            3
## 10  3622 Zona … 03          6     260      55              2      1            1
## # ℹ 933 more rows
## # ℹ 10 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>, preciomlog <dbl>, areaconstlog <dbl>, estrato4 <dbl>,
## #   estrato5 <dbl>, estrato6 <dbl>

como podemos darnos cuenta contamos con un total de 943 posibilidades que cubren las necescidades especificas, ademas se aclara que para las necesidades especificas no existen registros, pero trabajaremos con rangos cercanos a las necesidades sin pasarnos de los estipulado por la empresa cliente

las casa seleccionadas para este proceso son las de codigos 6175 (se selecciona por que es la mas grande y tiene un numero de habitaicones cercano), 5880 (se selecciona por lo que contiene un buen numero de habitaciones y parquederos), 6361 (se selecciona para tener posibilidades en otro estrato), 4008 (se selecciona para tener posibilidades en otro estrato) y 5701 (es una de las que mas se acerca a las necesidades estipuladas por la empresa)

viviendas_propuestas_base<- BaseSeleccionadaAPT %>% 
    dplyr::filter(id %in% c(6175,5880,6361,4008,5701)) %>% 
    mutate(diferencia_cupo=850-preciom, precio_m2=preciom/areaconst) %>% 
    arrange(precio_m2)

viviendas_propuestas_base
## # A tibble: 5 × 21
##      id zona    piso  estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <chr>   <dbl>   <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  6175 Zona S… 05          5     350       270            3      3            4
## 2  6361 Zona S… <NA>        6     655       241            2      3            3
## 3  4008 Zona S… 07          6     410       142            2      3            4
## 4  5701 Zona S… <NA>        6     570       160            3      3            3
## 5  5880 Zona S… <NA>        6     670       168            2      3            4
## # ℹ 12 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>,
## #   Nueva_Zona <chr>, preciomlog <dbl>, areaconstlog <dbl>, estrato4 <dbl>,
## #   estrato5 <dbl>, estrato6 <dbl>, diferencia_cupo <dbl>, precio_m2 <dbl>

por ultimo procedemos a visualizar donde se encuentran ubicadas cada una de las opciones de casas en la zona sur

# Creación de mapa con flecha de norte y barra de escala
library(leaflet)
library(sf)
library(ggplot2)
mapa_opciones<-leaflet(viviendas_propuestas_base) %>%
 addTiles() %>%
 addCircleMarkers(lng=~longitud,lat=~latitud,radius=7)

mapa_opciones

5.Conclusiones

por ultimo podemos obtener las siguientes conclusiones:

  1. la base de datos de la inmobliria presenta inconsistencias en sus datos , esto debido a temas de digitacion o errores en la toma de datos. lo anterior obliga a realizar una reclasificacion teniendo en cuenta la latitud y longitud
  2. los dos modelos tienen una buena explicacion por medio de los modelos en el caso del primer modelo para casas tiene un R que es capaz de explicarlo en un 69% separando los estratos y para el modelo de apartamentos es aun mejor por lo que alcanza a tener un R de 78% , para el mejoramiento de estos resultados podriamos ver la opcion de normalizar los datos de areacontruida y precio para que tenga un mejor manejo de los outliers.
  3. las variables en los dos casos que presentan una mayor correlacion con el precio son el area contruida y la cantidad de baños, pero tambien el estrato tiene una correlacion postivia con un 67% para los apartamentos y un 61% para las casa
  4. las opciones brindadas para los dos modelos fueron tomadas teniendo en cuenta que cumplan con los atributos que tiene mas correlacion con el precio es decir las de mayor area contruida y cantidad de baños
  5. pienso que la seleccion de la opciones es la mas optima y podria gustar al potencial comprador.