Importación de librerías y datos

Para iniciar la exploración de datos, se procede a importar las librerías que serán utilizadas en el análisis.

library(paqueteMODELOS)
library(dplyr)
library(gplots)
library(ggplot2)
library(NbClust)
library(cluster)
library(factoextra)
library(FactoMineR)
library(mice)
library(tidyverse)
library(ggmice)
library(plotly)
library(scales)
library(DescTools)
library(openxlsx)
library(stringi)
library(stargazer)
library(car)
library(caret)
library(fastDummies)

Ahora se procede a importar los datos para su análisis.

data(vivienda)

El análisis, y si es necesario, la limpieza de datos, es esencial para asegurar resultados coherentes y precisos. Para comenzar, se analizará la cantidad de observaciones y variables en la base de datos actual.

dim(vivienda)
## [1] 8322   13

La base de datos inicial consta de 8322 observaciones y 13 variables. A continuación, se presenta un resumen descriptivo de estas variables.

summarytools::descr(vivienda)
## Non-numerical variable(s) ignored: zona, piso, tipo, barrio
## Descriptive Statistics  
## vivienda  
## N: 8322  
## 
##                     areaconst    banios   estrato   habitaciones        id   latitud   longitud
## ----------------- ----------- --------- --------- -------------- --------- --------- ----------
##              Mean      174.93      3.11      4.63           3.61   4160.00      3.42     -76.53
##           Std.Dev      142.96      1.43      1.03           1.46   2401.63      0.04       0.02
##               Min       30.00      0.00      3.00           0.00      1.00      3.33     -76.59
##                Q1       80.00      2.00      4.00           3.00   2080.00      3.38     -76.54
##            Median      123.00      3.00      5.00           3.00   4160.00      3.42     -76.53
##                Q3      229.00      4.00      5.00           4.00   6240.00      3.45     -76.52
##               Max     1745.00     10.00      6.00          10.00   8319.00      3.50     -76.46
##               MAD       84.51      1.48      1.48           1.48   3083.81      0.05       0.02
##               IQR      149.00      2.00      1.00           1.00   4159.00      0.07       0.02
##                CV        0.82      0.46      0.22           0.40      0.58      0.01       0.00
##          Skewness        2.69      0.93     -0.18           1.63      0.00      0.03       0.65
##       SE.Skewness        0.03      0.03      0.03           0.03      0.03      0.03       0.03
##          Kurtosis       12.91      1.13     -1.11           3.98     -1.20     -1.15       0.58
##           N.Valid     8319.00   8319.00   8319.00        8319.00   8319.00   8319.00    8319.00
##         Pct.Valid       99.96     99.96     99.96          99.96     99.96     99.96      99.96
## 
## Table: Table continues below
## 
##  
## 
##                     parqueaderos   preciom
## ----------------- -------------- ---------
##              Mean           1.84    433.89
##           Std.Dev           1.12    328.65
##               Min           1.00     58.00
##                Q1           1.00    220.00
##            Median           2.00    330.00
##                Q3           2.00    540.00
##               Max          10.00   1999.00
##               MAD           1.48    207.56
##               IQR           1.00    320.00
##                CV           0.61      0.76
##          Skewness           2.33      1.85
##       SE.Skewness           0.03      0.03
##          Kurtosis           8.31      3.67
##           N.Valid        6717.00   8320.00
##         Pct.Valid          80.71     99.98

Ahora se procede a la limpieza de los datos.

Limpieza de datos

Se revisa la presencia de datos nulos:

plot_pattern(vivienda, rotate = TRUE)

Se identificó que existen 2 registros o viviendas con información completamente vacía, así como 1 registro con solo la variable “preciom”. Para mejorar la calidad de la base de datos, se procede a eliminar estos 3 registros.

En primer lugar, se removerán las dos filas que no contienen ninguna información, es decir, están completamente vacías.

vivienda_limpia <- vivienda[rowSums(is.na(vivienda)) != ncol(vivienda),]

Posteriormente, se procede a eliminar la tercera fila que contiene únicamente la variable “preciom”.

vivienda_limpia <- vivienda[complete.cases(vivienda$id),]

Después de eliminar los registros con información faltante, se procede a realizar un nuevo análisis de la matriz de valores nulos para asegurar que no queden registros con datos incompletos:

plot_pattern(vivienda_limpia, rotate = TRUE)

Tras la eliminación de los registros con datos vacíos, se observa una mejora significativa en la calidad de la base de datos. Sin embargo, aún persisten valores nulos en las variables “parqueadero” y “piso”. Estas dos columnas conservan un número considerable de casos vacíos, con 1602 y 2635 registros vacíos respectivamente. Aunque se ha reducido el ruido en la base de datos, es importante tener en cuenta estos valores nulos al realizar análisis posteriores.

Tras analizar nuestro conjunto de datos, hemos identificado que las variables ‘piso’ y ‘parqueadero’ son las únicas afectadas por valores nulos. Para abordar esta situación y garantizar la integridad de nuestros análisis, proponemos considerar las siguientes alternativas para la imputación de estos datos faltantes:

  • Cero
  • Media
  • Mediana
  • Valor de un registro completo similar al del dato faltante

Antes de optar por alguna de estas opciones, es necesario comprender el contexto y plantearnos por qué estos datos podrían estar vacíos. ¿Cuál podría haber sido la razón?

Algunas posibles razones podrían incluir:

  • Información no proporcionada por el cliente: En algunos casos, los clientes pueden optar por no proporcionar detalles sobre el piso o el número de espacios de estacionamiento disponibles en la propiedad.

  • Errores de ingreso de datos: Durante la entrada de datos, es posible que se hayan omitido los detalles del piso o del parqueadero debido a errores humanos o problemas técnicos.

  • Características de la propiedad: En ciertos tipos de propiedades, como terrenos o locales comerciales, la información sobre el piso o el parqueadero puede no ser relevante o aplicable.

  • Información incompleta de la fuente de datos: Dependiendo de la fuente de los datos, es posible que la información sobre el piso o el parqueadero no esté disponible o no se haya recopilado adecuadamente.

La presencia de datos nulos en la base sugiere que la información sobre piso o parqueadero puede no ser relevante para ciertas viviendas. Es probable que algunas casas no tengan parqueadero, y en el caso de apartamentos, pueden no haber asignaciones previas de parqueadero. Por lo tanto, se opta por imputar todos los valores nulos con 0.

Para el proceso de reemplazo de los valores nulos por 0 en la variable parqueadero se realiza de la siguiente manera.

vivienda_limpia$parqueaderos[is.na(vivienda_limpia$parqueaderos)] <- 0

Para la variable “piso”, dado que no puede tener un valor de 0 y es una variable cualitativa ordinal, se opta por reemplazar los datos faltantes por la moda. En este caso, la moda sería el piso 2, ya que es el que tiene la mayor frecuencia.

moda_piso <- Mode(vivienda_limpia$piso, na.rm = TRUE)
vivienda_limpia$piso[is.na(vivienda_limpia$piso)] <- moda_piso

Ahora si finalmente observamos la base de datos:

colSums(is.na(vivienda_limpia)) %>%
                 as.data.frame() 
##              .
## id           0
## zona         0
## piso         0
## estrato      0
## preciom      0
## areaconst    0
## parqueaderos 0
## banios       0
## habitaciones 0
## tipo         0
## barrio       0
## longitud     0
## latitud      0
plot_pattern(vivienda_limpia, rotate = TRUE)
##  /\     /\
## {  `---'  }
## {  O   O  }
## ==>  V <==  No need for mice. This data set is completely observed.
##  \  \|/  /
##   `-----'

Ahora corroboramos el tipo de datos de las variables:

str(vivienda_limpia)
## tibble [8,319 × 13] (S3: tbl_df/tbl/data.frame)
##  $ id          : num [1:8319] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8319] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : chr [1:8319] "02" "02" "02" "02" ...
##  $ estrato     : num [1:8319] 3 3 3 4 5 5 4 5 5 5 ...
##  $ preciom     : num [1:8319] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8319] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8319] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8319] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8319] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8319] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8319] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8319] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8319] 3.43 3.43 3.44 3.44 3.46 ...

La variable estrato se transformará a categórica, mientras que la variable piso a númerica:

vivienda_limpia$estrato <- as.character(vivienda_limpia$estrato)
vivienda_limpia$piso <- as.numeric(vivienda_limpia$piso)

Se corrobora nuevamente:

str(vivienda_limpia)
## tibble [8,319 × 13] (S3: tbl_df/tbl/data.frame)
##  $ id          : num [1:8319] 1147 1169 1350 5992 1212 ...
##  $ zona        : chr [1:8319] "Zona Oriente" "Zona Oriente" "Zona Oriente" "Zona Sur" ...
##  $ piso        : num [1:8319] 2 2 2 2 1 1 1 1 2 2 ...
##  $ estrato     : chr [1:8319] "3" "3" "3" "4" ...
##  $ preciom     : num [1:8319] 250 320 350 400 260 240 220 310 320 780 ...
##  $ areaconst   : num [1:8319] 70 120 220 280 90 87 52 137 150 380 ...
##  $ parqueaderos: num [1:8319] 1 1 2 3 1 1 2 2 2 2 ...
##  $ banios      : num [1:8319] 3 2 2 5 2 3 2 3 4 3 ...
##  $ habitaciones: num [1:8319] 6 3 4 3 3 3 3 4 6 3 ...
##  $ tipo        : chr [1:8319] "Casa" "Casa" "Casa" "Casa" ...
##  $ barrio      : chr [1:8319] "20 de julio" "20 de julio" "20 de julio" "3 de julio" ...
##  $ longitud    : num [1:8319] -76.5 -76.5 -76.5 -76.5 -76.5 ...
##  $ latitud     : num [1:8319] 3.43 3.43 3.44 3.44 3.46 ...

1.Realice un filtro a la base de datos

Realice un filtro a la base de datos e incluya sólo las ofertas de apartamentos. Presente los primeros 3 registros de las bases y algunas tablas que comprueben la consulta.

Después de la limpieza de datos se procede a filtrar la información según lo requerido:

vivienda_apto <- filter(vivienda_limpia, tipo == "Apartamento")
head(vivienda_apto, 3)
## # A tibble: 3 × 13
##      id zona     piso estrato preciom areaconst parqueaderos banios habitaciones
##   <dbl> <chr>   <dbl> <chr>     <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
## 1  1212 Zona N…     1 5           260        90            1      2            3
## 2  1724 Zona N…     1 5           240        87            1      3            3
## 3  2326 Zona N…     1 4           220        52            2      2            3
## # ℹ 4 more variables: tipo <chr>, barrio <chr>, longitud <dbl>, latitud <dbl>

Ahora se eliminan las variables que no se usarán en el análisis:

vivienda_apto <- subset(vivienda_apto, select = -c(id,tipo,barrio,latitud,longitud))

2.Realice un análisis exploratorio de datos

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.

Area construida vs Preciom

plot_area <- plot_ly(data = vivienda_apto, 
                     x = ~areaconst, 
                     y = ~preciom, 
                     type = 'scatter', 
                     mode = 'markers',
                     marker = list(color = 'blue', size = 8)) %>%  # Cambiar color y tamaño de los puntos
  layout(title = "Precio vs Área Construida",
         xaxis = list(title = "Área Construida"),
         yaxis = list(title = "Precio"))

# Mostrar el gráfico
plot_area
cor(vivienda_apto$areaconst,vivienda_apto$preciom)
## [1] 0.8287437

La gráfica muestra una relación positiva entre el precio y el área construida: a mayor área, el precio tiende a aumentar. La mayoría de las propiedades se concentran en áreas menores a 300 m2 y precios inferiores a 1000 millones de pesos, aunque hay algunos outliers con áreas más grandes. Además, a medida que aumenta el área construida, la dispersión en los precios crece, lo que sugiere que otros factores también pueden influir en los precios de propiedades más grandes.

Estrato vs Preciom

# Crear el gráfico de caja con color personalizado
plot_estrato <- plot_ly(data = vivienda_apto, 
                        x = ~factor(estrato), 
                        y = ~preciom, 
                        type = 'box', 
                        fillcolor = 'lightblue',  # Cambiar el color de las cajas,
                        boxpoints = 'outliers',    # Mostrar los puntos atípicos
                        marker = list(color = 'blue')) %>%  # Cambiar el color de los puntos atípicos si existen
  layout(title = "Precio vs Estrato",
         xaxis = list(title = "Estrato"),
         yaxis = list(title = "Precio"))

# Mostrar el gráfico
plot_estrato

La gráfica muestra que a medida que el estrato aumenta de 3 a 6, los precios de los inmuebles también tienden a subir, lo que indica una relación directa entre el estrato socioeconómico y el precio. Además, los estratos 5 y 6 presentan una mayor variabilidad en los precios, lo que sugiere que dentro de estos estratos hay una mayor diversidad de precios. También se observan varios outliers, especialmente en los estratos 4, 5 y 6, lo que indica la presencia de propiedades con precios significativamente más altos que el promedio en esos grupos.

Número de baños vs Preciom

plot_banios <- plot_ly(data = vivienda_apto, 
                       x = ~banios, 
                       y = ~preciom, 
                       type = 'box', 
                       fillcolor = 'lightblue',  # Cambiar el color de las cajas,
                       boxpoints = 'outliers',    # Mostrar los puntos atípicos
                       marker = list(color = 'blue', size = 6)) %>%  # Cambiar color y tamaño de los puntos atípicos
  layout(title = "Precio vs Número de Baños",
         xaxis = list(title = "Número de Baños"),
         yaxis = list(title = "Precio"))

# Mostrar el gráfico
plot_banios

La gráfica muestra que a medida que aumenta el número de baños en una propiedad, los precios tienden a incrementarse, lo que indica una relación positiva entre el número de baños y el precio. Los inmuebles con 5 o más baños presentan una mayor dispersión en los precios, lo que sugiere que, a partir de este número, hay más variabilidad en los valores de las propiedades. También se observan varios outliers, especialmente en los grupos de 2, 4 y 5 baños, lo que indica la presencia de propiedades con precios mucho más altos que el promedio en esas categorías.

Usando la correlacion de spearman debido a que es una variable discreta:

cor(vivienda_apto$banios,vivienda_apto$preciom, method = "spearman")
## [1] 0.771612

La correlación de Spearman entre el número de baños y el precio es de 0.7716, lo que indica una fuerte relación positiva entre estas dos variables. Esto significa que, en general, a medida que aumenta el número de baños, el precio también tiende a aumentar de manera consistente. Al utilizar Spearman, que es más adecuado para variables discretas como el número de baños, se confirma que la relación no solo es lineal, sino que sigue una tendencia monótona: más baños están asociados con precios más altos.

Número de habitaciones vs Preciom

plot_habitaciones <- plot_ly(data = vivienda_apto, 
                             x = ~habitaciones, 
                             y = ~preciom, 
                             type = 'box', 
                             fillcolor = 'lightblue',  # Cambiar el color de las cajas
                             boxpoints = 'outliers',    # Mostrar los puntos atípicos
                             marker = list(color = 'blue', size = 6)) %>%  # Cambiar color y tamaño de los puntos atípicos
  layout(title = "Precio vs Número de Habitaciones",
         xaxis = list(title = "Número de Habitaciones"),
         yaxis = list(title = "Precio"))

# Mostrar el gráfico
plot_habitaciones

La gráfica muestra que a medida que aumenta el número de habitaciones en una propiedad, el precio tiende a incrementarse, lo que indica una relación positiva entre el número de habitaciones y el precio. Sin embargo, esta relación no es tan clara como en otros gráficos, ya que hay más variabilidad en los precios, especialmente a partir de 4 habitaciones, donde la dispersión aumenta. Los outliers se concentran en los inmuebles con 2, 4 y 6 habitaciones, lo que indica que hay propiedades con precios significativamente más altos en esas categorías. Además, a partir de 6 habitaciones, aunque hay pocos datos, los precios parecen mantenerse altos.

Usando la correlacion de spearman debido a que es una variable discreta:

cor(vivienda_apto$habitaciones,vivienda_apto$preciom, method = "spearman")
## [1] 0.3258252

La correlación de Spearman entre el número de habitaciones y el precio es de 0.3258, lo que indica una relación positiva moderada entre estas dos variables. Aunque la correlación es menor en comparación con otras variables como el número de baños, sigue habiendo una tendencia a que, a medida que aumenta el número de habitaciones, el precio también tiende a aumentar. Sin embargo, la magnitud de esta correlación sugiere que el número de habitaciones no tiene un impacto tan fuerte en el precio como otras características, lo que podría explicarse por la mayor variabilidad observada en la gráfica.

Zona vs Preciom

# Crear el gráfico de caja con color personalizado para las zonas
plot_zona <- plot_ly(data = vivienda_apto, 
                     x = ~zona, 
                     y = ~preciom, 
                     type = 'box', 
                     fillcolor = 'lightblue',  # Cambiar el color de las cajas
                     boxpoints = 'outliers',   # Mostrar los puntos atípicos
                     marker = list(color = 'blue', size = 6)) %>%  # Cambiar color y tamaño de los puntos atípicos
  layout(title = "Precio vs Zona",
         xaxis = list(title = "Zona"),
         yaxis = list(title = "Precio"))

# Mostrar el gráfico
plot_zona

La gráfica muestra que el precio de las propiedades varía significativamente según la zona. La Zona Oeste tiene los precios más altos, con una mayor dispersión, lo que indica que en esta zona los precios varían considerablemente. La Zona Norte y la Zona Sur tienen precios más moderados, aunque también presentan una mayor cantidad de outliers, lo que sugiere que en estas zonas hay algunas propiedades con precios significativamente más altos que el promedio. Por otro lado, la Zona Centro y la Zona Oriente tienen los precios más bajos, con menor dispersión y menos outliers, lo que indica una mayor homogeneidad en los precios dentro de esas zonas. En resumen, la zona en la que se encuentra la propiedad influye de manera notable en el precio, siendo la Zona Oeste la más costosa y variable en términos de precio.

3.Estime un modelo de regresión lineal

Primero convertiremos la variable estrato que es categórica a una variable tipo dummy en donde se asignen internamente otras variables dicotómicas de acuerdo con el número de categorías.

vivienda_apto_dummies <- dummy_cols(vivienda_apto, select_columns = "estrato")
print(vivienda_apto_dummies)
## # A tibble: 5,100 × 12
##    zona        piso estrato preciom areaconst parqueaderos banios habitaciones
##    <chr>      <dbl> <chr>     <dbl>     <dbl>        <dbl>  <dbl>        <dbl>
##  1 Zona Norte     1 5           260        90            1      2            3
##  2 Zona Norte     1 5           240        87            1      3            3
##  3 Zona Norte     1 4           220        52            2      2            3
##  4 Zona Norte     1 5           310       137            2      3            4
##  5 Zona Norte     2 6           520        98            2      2            2
##  6 Zona Norte     3 4           320       108            2      3            3
##  7 Zona Norte     3 5           385       103            2      2            3
##  8 Zona Norte     3 3           100        49            0      1            2
##  9 Zona Norte     4 3           175        80            1      2            3
## 10 Zona Norte     5 6           820       377            1      4            4
## # ℹ 5,090 more rows
## # ℹ 4 more variables: estrato_3 <int>, estrato_4 <int>, estrato_5 <int>,
## #   estrato_6 <int>

Aunque se hizo la conversion de la variable estrato que es categórica en variables dummy, la función lm automáticamente maneja variables categóricas, convirtiéndolas en dummies y omitiendo una categoría como referencia.

mod <- lm(preciom ~ areaconst + estrato +  habitaciones + parqueaderos  + banios, data = vivienda_apto)
# Resumen del modelo
summary(mod)
## 
## Call:
## lm(formula = preciom ~ areaconst + estrato + habitaciones + parqueaderos + 
##     banios, data = vivienda_apto)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1739.07   -50.35    -0.29    43.38  1001.91 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   -9.10043    9.45620  -0.962 0.335906    
## areaconst      2.07473    0.04076  50.902  < 2e-16 ***
## estrato4       7.58085    6.36427   1.191 0.233647    
## estrato5      24.85416    6.59027   3.771 0.000164 ***
## estrato6     171.62149    8.30318  20.669  < 2e-16 ***
## habitaciones -36.18187    3.18877 -11.347  < 2e-16 ***
## parqueaderos  54.61526    2.84773  19.179  < 2e-16 ***
## banios        47.53130    2.93497  16.195  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 128.9 on 5092 degrees of freedom
## Multiple R-squared:  0.8016, Adjusted R-squared:  0.8013 
## F-statistic:  2939 on 7 and 5092 DF,  p-value: < 2.2e-16

Intercepto (Intercept): El valor de -9.10043 indica que cuando todas las variables independientes son 0, el valor esperado de preciom es -9.1 (lo cual puede no tener sentido práctico y se interpreta con cuidado).

Área Construida (areaconst): Coeficiente de 2.07473, altamente significativo (p < 2e-16). Cada metro cuadrado adicional de área construida aumenta el precio en aproximadamente 2.07 unidades.

Estrato (estrato4, estrato5, estrato6):

estrato4: No significativo (p = 0.233467), por lo que su impacto no es concluyente.

estrato5: Coeficiente de 24.85416, significativo (p < 0.0001), lo que sugiere que estar en estrato 5 aumenta el precio en aproximadamente 24.85 unidades en comparación con el estrato de referencia.

estrato6: Coeficiente de 171.62149, altamente significativo (p < 2e-16), lo que indica un gran aumento en el precio de aproximadamente 171.62 unidades comparado con el estrato de referencia.

Habitaciones: Coeficiente de -36.18187, altamente significativo (p < 2e-16). Tener más habitaciones está asociado con una disminución en el precio, lo que podría indicar un efecto compensatorio relacionado con el área u otras variables.

Parqueaderos: Coeficiente de 54.61526, altamente significativo (p < 2e-16). Cada parqueadero adicional incrementa el precio en aproximadamente 54.62 unidades.

Baños: Coeficiente de 47.53130, altamente significativo (p < 2e-16). Cada baño adicional aumenta el precio en aproximadamente 47.53 unidades.

R-squared: 0.8016 indica que el 80.16% de la variabilidad en el precio es explicada por este modelo. Es un buen ajuste.

Se puede concluir que el modelo presenta un buen ajuste, dado que el coeficiente de determinación es relativamente alto y los coeficientes de las variables predictoras son en su mayoría estadísticamente significativos. No obstante, para mejorar el modelo, se debería considerar la inclusión de otras variables que se consideren relevantes, así como explorar la posibilidad de realizar transformaciones de variables para capturar relaciones no lineales y verificar si el modelo cumple con los supuestos de la regresión lineal.

4.Realice la validación de supuestos del modelo

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)

par(mfrow=c(2,2))
plot(mod)

Pruebas de hipótesis

Se establece el nivel de significancia que se acepta como evidencia suficiente para aceptar o rechazar la hipótesis nula, en este caso un valor de alfa de 0.05(5%)

Normalidad

ks.test(resid(mod), "pnorm", mean=mean(resid(mod)), sd=sd(resid(mod)))
## 
##  Asymptotic one-sample Kolmogorov-Smirnov test
## 
## data:  resid(mod)
## D = 0.14872, p-value < 2.2e-16
## alternative hypothesis: two-sided

Dado que el p-valor es extremadamente bajo (mucho menor que 0.05), se tiene evidencia estadística significativa para rechazar la hipótesis nula. Esto indica que los residuos del modelo no siguen una distribución normal.

Homoscedasticidad

lmtest::bptest(mod)
## 
##  studentized Breusch-Pagan test
## 
## data:  mod
## BP = 1443.5, df = 7, p-value < 2.2e-16

Dado que el p-valor es extremadamente bajo (mucho menor que 0.05), se tiene evidencia estadística significativa para rechazar la hipótesis nula de homocedasticidad. Esto indica que hay heterocedasticidad en los residuos del modelo.

No autocorrelación

lmtest::dwtest(mod)
## 
##  Durbin-Watson test
## 
## data:  mod
## DW = 1.7173, p-value < 2.2e-16
## alternative hypothesis: true autocorrelation is greater than 0

Aunque el valor del estadístico DW (1.7173) está relativamente cerca de 2, lo que podría sugerir una ligera autocorrelación, el valor p extremadamente bajo indica que hay evidencia estadística significativa para rechazar la hipótesis nula de no autocorrelación. Esto significa que existe autocorrelación positiva en los residuos del modelo.

No Multicolinealidad

vif_values <- vif(mod)
print(vif_values)
##                  GVIF Df GVIF^(1/(2*Df))
## areaconst    2.452065  1        1.565907
## estrato      2.102309  3        1.131834
## habitaciones 1.425482  1        1.193936
## parqueaderos 2.002715  1        1.415173
## banios       3.018264  1        1.737315

Todos los valores de GVIF ajustados (GVIF^(1/(2*Df))) están por debajo de 2, lo cual sugiere que no hay una multicolinealidad significativa en tu modelo. Aunque el valor más alto es para “baños” (1.737315), sigue estando por debajo del umbral comúnmente aceptado (5 o 10), lo que indica que no hay presencia de multicolinealidad en las variables independientes.

5.Realice una partición en los datos

Realice una partición en los datos de forma aleatoria donde 70% sea un set para entrenar el modelo y 30% para prueba. Estime el modelo con la muestra del 70%. Muestre los resultados.

# Se realiza la partición del dataset usando la librería caret.
entrenamiento <- createDataPartition(vivienda_apto$preciom, p = 0.7, 
                                  list = FALSE, 
                                  times = 1)

# Crear los datasets de entrenamiento y prueba
data_train <- vivienda_apto[entrenamiento, ]
data_test <- vivienda_apto[-entrenamiento, ]

#Se entrena el modelo
modelo_entrenado <- train(preciom ~ .,  # 'preciom' es la variable dependiente
                          data = data_train,  # Conjunto de entrenamiento
                          method = "lm",      # Método de regresión lineal
                          tuneLenght = 3000)  

Se muestra ahora el resumen obtenido del modelo:

# Mostrar el resumen del modelo
summary(modelo_entrenado)
## 
## Call:
## lm(formula = .outcome ~ ., data = dat, tuneLenght = 3000)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -1552.56   -51.31     0.29    42.70   984.70 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)        -33.82169   30.81664  -1.098 0.272491    
## `zonaZona Norte`    23.69635   29.45774   0.804 0.421209    
## `zonaZona Oeste`    83.67326   29.91287   2.797 0.005182 ** 
## `zonaZona Oriente` -17.11390   34.63558  -0.494 0.621257    
## `zonaZona Sur`       6.54647   29.43636   0.222 0.824020    
## piso                 2.63268    0.79882   3.296 0.000991 ***
## estrato4            12.67681    8.09054   1.567 0.117235    
## estrato5            27.55885    8.18320   3.368 0.000766 ***
## estrato6           162.07933   10.33246  15.686  < 2e-16 ***
## areaconst            1.85662    0.04924  37.707  < 2e-16 ***
## parqueaderos        52.01916    3.29514  15.787  < 2e-16 ***
## banios              47.26890    3.43020  13.780  < 2e-16 ***
## habitaciones       -30.44940    3.73128  -8.161 4.58e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 126.5 on 3559 degrees of freedom
## Multiple R-squared:  0.7996, Adjusted R-squared:  0.7989 
## F-statistic:  1183 on 12 and 3559 DF,  p-value: < 2.2e-16

R² ajustado: El valor de 0.8036 indica que el modelo explica aproximadamente el 80.5% de la variabilidad en los precios, lo cual es un buen ajuste.

Significancia de variables: Variables como estrato5, estrato6, areaconst, parqueaderos, y banios tienen un valor p muy bajo (p < 0.001), lo que indica que son altamente significativas para predecir el precio.

Coeficientes positivos importantes: estrato6, areaconst, parqueaderos, y banios tienen coeficientes positivos, lo que sugiere que aumentan el precio a medida que aumentan.

Coeficiente negativo: El número de habitaciones tiene un coeficiente negativo (-24.93), lo que indica que, sorprendentemente, un mayor número de habitaciones podría estar asociado con una disminución del precio en este modelo.

Variables no significativas: Zonas como Zona Norte, Zona Oriente y Zona Sur no son estadísticamente significativas (p > 0.05), lo que sugiere que no afectan de manera importante el precio en este modelo.

6.Realice predicciones con el modelo anterior

Realice predicciones con el modelo anterior usando los datos de prueba (30%).

# Realizar las predicciones usando el conjunto de prueba (30%)
predictions <- predict(modelo_entrenado, newdata = data_test)

# Crear un dataframe para comparar las predicciones con los valores reales
results <- data.frame(Real = data_test$preciom, Predicted = predictions)

# Ver los primeros resultados
head(results, 5)
##   Real Predicted
## 1  520  476.8458
## 2  320  365.4617
## 3  420  467.3343
## 4  430  268.1029
## 5  320  526.2835

Los resultados muestran que el modelo tiene un rendimiento mixto, con algunas predicciones cercanas a los valores reales, como en el segundo caso, donde la predicción es de 373.51 frente a un valor real de 320. Sin embargo, en otros casos, como en el primero y el cuarto, las predicciones están más alejadas, con el modelo sobreestimando o subestimando el precio real. Esto indica que el modelo no es consistentemente preciso en todas las predicciones.

En general, aunque el modelo parece capturar ciertas tendencias en los datos, las variaciones entre las predicciones y los valores reales sugieren que podría mejorarse, ya sea ajustando el modelo o reconsiderando las variables utilizadas para predecir los precios.

7.Calcule el error cuadrático medio

Calcule el error cuadrático medio, el error absoluto medio y el R2, interprete.

# Calcular el Error Cuadrático Medio (MSE)
mse <- mean((results$Real - results$Predicted)^2)

# Calcular el Error Absoluto Medio (MAE)
mae <- mean(abs(results$Real - results$Predicted))

# Calcular el Coeficiente de Determinación (R²)
rss <- sum((results$Real - results$Predicted)^2)  # Residual Sum of Squares
tss <- sum((results$Real - mean(results$Real))^2)  # Total Sum of Squares
r_squared <- 1 - (rss/tss)

# Mostrar los resultados
cat("MSE:", mse, "\n")
## MSE: 16342.85
cat("MAE:", mae, "\n")
## MAE: 78.51095
cat("R²:", r_squared, "\n")
## R²: 0.8243296

A partir de los resultados mostrados, el Error Cuadrático Medio (MSE) es de 15,966.37, lo que indica que, en promedio, el cuadrado de las diferencias entre los valores reales y predichos es considerable, sugiriendo que el modelo tiene cierto nivel de error.

El Error Absoluto Medio (MAE), que es de 77.57, proporciona una medida más intuitiva del error promedio en las predicciones, indicando que, en promedio, las predicciones están desviadas unos 77.57 unidades del valor real.

El R² de 0.8149 indica que el modelo es capaz de explicar aproximadamente el 81.5% de la variabilidad en los datos, lo que sugiere un buen ajuste general. Sin embargo, el nivel de error reflejado por el MSE y MAE sugiere que aún hay margen para mejorar la precisión del modelo, posiblemente a través de un ajuste adicional o la inclusión de más variables relevantes.