1 Introducción

1.1 Alcance de la actividad

La presente actividad desarrolla el caso de C&A (Casas y Apartamentos), una agencia inmobiliaria que debe atender la solicitud de una compañía interesada en adquirir dos viviendas en la ciudad de Cali para sus empleados y sus familias. Cada solicitud presenta condiciones particulares relacionadas con el tipo de inmueble, área construida, número de parqueaderos, baños y habitaciones, estrato socioeconómico, zona de ubicación y presupuesto disponible.

Para apoyar la toma de decisiones se plantea el uso de técnicas de regresión lineal múltiple, a partir de la información disponible sobre ofertas de vivienda. El análisis comprende la selección de los datos correspondientes a cada solicitud, la exploración de las principales variables relacionadas con el precio, la estimación e interpretación de los modelos, la validación de sus supuestos y la predicción del precio esperado para las características requeridas.

Finalmente, los resultados obtenidos servirán como referencia para identificar y analizar ofertas potenciales que se ajusten a las condiciones y restricciones presupuestales de cada solicitud, con el propósito de formular recomendaciones para C&A.

1.2 Datos utilizados

Para el desarrollo de la actividad se utiliza la base de datos vivienda, suministrada a través del paquete paqueteMODELOS. De acuerdo con el enunciado, la información corresponde a ofertas de vivienda y contiene variables relacionadas con el precio, las características físicas y la localización de los inmuebles.

A continuación, se presenta una primera vista de la base utilizada.

# Revisar el número de filas y columnas de la base
dim(vivienda)
## [1] 8322   13
# Explorar la estructura general de la base:
# nombres de variables, tipo de dato y algunos valores de ejemplo
glimpse(vivienda)
## Rows: 8,322
## Columns: 13
## $ id           <dbl> 1147, 1169, 1350, 5992, 1212, 1724, 2326, 4386, 1209, 159…
## $ zona         <chr> "Zona Oriente", "Zona Oriente", "Zona Oriente", "Zona Sur…
## $ piso         <chr> NA, NA, NA, "02", "01", "01", "01", "01", "02", "02", "02…
## $ estrato      <dbl> 3, 3, 3, 4, 5, 5, 4, 5, 5, 5, 6, 4, 5, 6, 4, 5, 5, 4, 5, …
## $ preciom      <dbl> 250, 320, 350, 400, 260, 240, 220, 310, 320, 780, 750, 62…
## $ areaconst    <dbl> 70, 120, 220, 280, 90, 87, 52, 137, 150, 380, 445, 355, 2…
## $ parqueaderos <dbl> 1, 1, 2, 3, 1, 1, 2, 2, 2, 2, NA, 3, 2, 2, 1, 4, 2, 2, 2,…
## $ banios       <dbl> 3, 2, 2, 5, 2, 3, 2, 3, 4, 3, 7, 5, 6, 2, 4, 4, 4, 3, 2, …
## $ habitaciones <dbl> 6, 3, 4, 3, 3, 3, 3, 4, 6, 3, 6, 5, 6, 2, 5, 5, 4, 3, 3, …
## $ tipo         <chr> "Casa", "Casa", "Casa", "Casa", "Apartamento", "Apartamen…
## $ barrio       <chr> "20 de julio", "20 de julio", "20 de julio", "3 de julio"…
## $ longitud     <dbl> -76.51, -76.51, -76.52, -76.54, -76.51, -76.52, -76.52, -…
## $ latitud      <dbl> 3.434, 3.434, 3.436, 3.435, 3.459, 3.370, 3.426, 3.383, 3…
# Mostrar los primeros 5 registros para tener una vista inicial
# del contenido de la base
head(vivienda, 5)

Interpretación:
La base vivienda contiene 8.322 registros y 13 variables. La información reúne características físicas de los inmuebles, variables asociadas con su ubicación, el precio de las ofertas y las coordenadas geográficas de cada registro.

2 Preparación y análisis exploratorio de los datos

2.1 Exploración inicial de la base

Como punto de partida, se realiza una exploración de las variables contenidas en la base con el fin de reconocer su naturaleza y las categorías presentes.

# Identificar el tipo de dato con el que R reconoce cada variable
sapply(vivienda, class)
##           id         zona         piso      estrato      preciom    areaconst 
##    "numeric"  "character"  "character"    "numeric"    "numeric"    "numeric" 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##    "numeric"    "numeric"    "numeric"  "character"  "character"    "numeric" 
##      latitud 
##    "numeric"

Interpretación:
La base presenta variables almacenadas en R como numéricas y de tipo carácter. Entre las numéricas se encuentran id, estrato, preciom, areaconst, parqueaderos, banios, habitaciones, longitud y latitud, mientras que zona, piso, tipo y barrio se encuentran registradas como variables de tipo carácter.

Esta clasificación corresponde al tipo de dato con el que cada variable está almacenada en R. Por tanto, su naturaleza estadística debe analizarse de forma independiente, ya que una variable numérica puede representar categorías ordenadas y no necesariamente una medida cuantitativa.

# Obtener un resumen general de las variables de la base
summary(vivienda)
##        id           zona               piso              estrato    
##  Min.   :   1   Length:8322        Length:8322        Min.   :3.00  
##  1st Qu.:2080   Class :character   Class :character   1st Qu.:4.00  
##  Median :4160   Mode  :character   Mode  :character   Median :5.00  
##  Mean   :4160                                         Mean   :4.63  
##  3rd Qu.:6240                                         3rd Qu.:5.00  
##  Max.   :8319                                         Max.   :6.00  
##  NA's   :3                                            NA's   :3     
##     preciom       areaconst     parqueaderos      banios       habitaciones 
##  Min.   :  58   Min.   :  30   Min.   : 1.0   Min.   : 0.00   Min.   : 0.0  
##  1st Qu.: 220   1st Qu.:  80   1st Qu.: 1.0   1st Qu.: 2.00   1st Qu.: 3.0  
##  Median : 330   Median : 123   Median : 2.0   Median : 3.00   Median : 3.0  
##  Mean   : 434   Mean   : 175   Mean   : 1.8   Mean   : 3.11   Mean   : 3.6  
##  3rd Qu.: 540   3rd Qu.: 229   3rd Qu.: 2.0   3rd Qu.: 4.00   3rd Qu.: 4.0  
##  Max.   :1999   Max.   :1745   Max.   :10.0   Max.   :10.00   Max.   :10.0  
##  NA's   :2      NA's   :3      NA's   :1605   NA's   :3       NA's   :3     
##      tipo              barrio             longitud        latitud    
##  Length:8322        Length:8322        Min.   :-76.6   Min.   :3.33  
##  Class :character   Class :character   1st Qu.:-76.5   1st Qu.:3.38  
##  Mode  :character   Mode  :character   Median :-76.5   Median :3.42  
##                                        Mean   :-76.5   Mean   :3.42  
##                                        3rd Qu.:-76.5   3rd Qu.:3.45  
##                                        Max.   :-76.5   Max.   :3.50  
##                                        NA's   :3       NA's   :3

Interpretación:

A partir del resumen general de la base se realizan las siguientes observaciones:

  • id: presenta valores entre 1 y 8.319 y registra 3 valores faltantes. Esta variable corresponde al identificador de cada registro, por lo que sus medidas de tendencia central no tienen una interpretación estadística relevante para el análisis de las viviendas.

  • zona: se encuentra almacenada como una variable de tipo carácter y contiene 8.322 registros. A partir de este resumen no es posible determinar todavía las categorías existentes, su frecuencia ni la presencia de valores faltantes, por lo que estos aspectos deberán revisarse posteriormente.

  • piso: se encuentra almacenada como una variable de tipo carácter. Debido a que representa el piso en el que se encuentra una vivienda, será necesario revisar posteriormente sus categorías y valores faltantes para establecer si su registro es consistente.

  • estrato: presenta valores entre 3 y 6, correspondientes a niveles socioeconómicos que resultan razonables para las viviendas contenidas en la base. La mediana corresponde al estrato 5. Aunque R calcula una media de 4,63 debido a que la variable está almacenada numéricamente, su interpretación debe considerar que se trata de categorías ordenadas y no de una medida cuantitativa continua.

  • preciom: el precio de las viviendas se encuentra entre 58 y 1.999 millones de pesos, con una mediana de 330 millones y una media de 434 millones. Aunque existe una diferencia importante entre los precios más bajos y los más altos, el rango observado no resulta, por sí mismo, extraño para un mercado inmobiliario en el que pueden coexistir viviendas de características, tamaños, estratos y ubicaciones muy diferentes. El valor máximo se encuentra considerablemente por encima del tercer cuartil de 540 millones, por lo que podría corresponder a una vivienda de alta gama, sin que esto implique necesariamente un dato erróneo. La mayor media frente a la mediana sugiere la influencia de estas viviendas de mayor valor sobre el promedio.

  • areaconst: el área construida varía entre 30 y 1.745 m², con una mediana de 123 m² y una media de 175 m². Un área de 30 m² puede resultar razonable para una vivienda pequeña, mientras que superficies superiores a 1.000 m² son poco frecuentes, pero posibles en propiedades de gran tamaño. Por tanto, el máximo de 1.745 m² merece ser examinado posteriormente, aunque no puede considerarse inconsistente únicamente por su magnitud.

  • parqueaderos: registra entre 1 y 10 parqueaderos y la mayor parte de las observaciones se concentra entre uno y dos. Los valores de uno o dos espacios resultan coherentes con viviendas residenciales habituales. Un inmueble con 10 parqueaderos es claramente menos frecuente, pero podría corresponder a una propiedad de gran área o características particulares, por lo que debe revisarse antes de considerarlo un valor anómalo. La principal situación que se observa en esta variable es la presencia de 1.605 valores faltantes, aspecto que puede tener mayor impacto sobre el análisis que su valor máximo.

  • banios: presenta valores entre 0 y 10, con una mediana de 3. La existencia de viviendas con varios baños es razonable, especialmente en inmuebles de mayor área, por lo que un máximo de 10 no constituye necesariamente una inconsistencia. En cambio, el valor mínimo de cero sí requiere una revisión particular, debido a que una vivienda registrada para oferta inmobiliaria normalmente debería disponer de al menos un baño.

  • habitaciones: presenta valores entre 0 y 10 y una mediana de 3. Los valores altos pueden resultar razonables en viviendas grandes y no constituyen por sí mismos una señal de error. El valor de cero habitaciones requiere mayor análisis: podría ser válido en determinados apartamentos tipo estudio, pero resultaría menos coherente si se presenta en viviendas registradas como casas. Su validez deberá contrastarse posteriormente con el tipo de inmueble.

  • tipo: se encuentra almacenada como una variable de tipo carácter. El resumen no permite todavía conocer sus categorías ni la cantidad de observaciones correspondiente a cada una, por lo que su distribución deberá revisarse posteriormente.

  • barrio: se encuentra almacenada como una variable de tipo carácter. Debido a la diversidad esperada de barrios en una base inmobiliaria de la ciudad, será necesario examinar posteriormente sus categorías y frecuencias.

  • longitud y latitud: presentan valores aproximados entre -76,6 y -76,5 para la longitud y entre 3,33 y 3,50 para la latitud. Los rangos observados son geográficamente razonables para registros concentrados en Cali y no muestran, en esta primera revisión, coordenadas evidentemente incompatibles con la ciudad. Posteriormente, su representación cartográfica permitirá verificar con mayor precisión la correspondencia entre las coordenadas y las zonas asignadas a cada inmueble.

En general, las estadísticas descriptivas no muestran valores claramente imposibles en variables como precio, área, número máximo de habitaciones, baños o parqueaderos. No obstante, se identifican algunos registros que requieren mayor revisión, principalmente las viviendas con cero baños o cero habitaciones y la cantidad considerable de valores faltantes en parqueaderos. Los valores máximos observados pueden considerarse poco frecuentes, pero deberán analizarse junto con las demás características de cada inmueble antes de clasificarlos como atípicos o inconsistentes.

# Identificar las zonas registradas en la base de datos
unique(vivienda$zona)
## [1] "Zona Oriente" "Zona Sur"     "Zona Norte"   "Zona Oeste"   "Zona Centro" 
## [6] NA

Interpretación:
La variable zona contiene cinco categorías de ubicación: Oriente, Sur, Norte, Oeste y Centro. Estas categorías corresponden a las divisiones utilizadas en la base para identificar la localización general de las viviendas.

También se observa la presencia de valores faltantes (NA), por lo que posteriormente será necesario establecer cuántos registros presentan esta ausencia y evaluar su efecto sobre la construcción de las bases correspondientes a cada solicitud.

# Identificar los tipos de vivienda registrados en la base
unique(vivienda$tipo)
## [1] "Casa"        "Apartamento" NA

Interpretación:
La variable estrato presenta cuatro niveles: 3, 4, 5 y 6, sin evidenciar valores faltantes en la revisión realizada. Aunque se encuentra almacenada en R como una variable numérica, sus valores representan categorías socioeconómicas ordenadas, por lo que estadísticamente corresponde a una variable cualitativa ordinal.

Esta característica deberá tenerse en cuenta posteriormente al definir la forma en que será incorporada al modelo de regresión.

# Identificar los niveles de estrato registrados en la base
unique(vivienda$estrato)
## [1]  3  4  5  6 NA

Interpretación:
La variable estrato presenta cuatro niveles: 3, 4, 5 y 6, además de valores faltantes (NA). Aunque se encuentra almacenada en R como una variable numérica, sus valores representan categorías socioeconómicas ordenadas, por lo que estadísticamente corresponde a una variable cualitativa ordinal.

La presencia de valores faltantes deberá revisarse posteriormente, especialmente porque el estrato forma parte de las características consideradas en las solicitudes y en la modelación.

# Identificar los valores registrados en la variable piso
unique(vivienda$piso)
##  [1] NA   "02" "01" "03" "04" "05" "06" "07" "08" "09" "10" "11" "12"

Interpretación:
La variable piso presenta valores desde "01" hasta "12", además de registros faltantes (NA). Aunque actualmente está almacenada en R como una variable de tipo carácter, sus categorías representan niveles ordenados, por lo que conceptualmente corresponde a una variable cualitativa ordinal.

El uso de valores como "01", "02" o "03" permite conservar el formato de dos dígitos, pero no modifica el orden natural asociado al piso de ubicación de la vivienda. La presencia de valores faltantes deberá revisarse posteriormente, ya que puede estar relacionada con inmuebles para los cuales esta característica no fue registrada o no resulta aplicable, como podría ocurrir en algunas casas.

# Identificar los valores registrados en la variable barrio
unique(vivienda$barrio)
##   [1] "20 de julio"                   "3 de julio"                   
##   [3] "acopi"                         "agua blanca"                  
##   [5] "aguablanca"                    "aguacatal"                    
##   [7] "alameda"                       "alameda del río"              
##   [9] "alameda del rio"               "alamos"                       
##  [11] "alborada"                      "alcazares"                    
##  [13] "alférez real"                 "alferez real"                 
##  [15] "alfonso lópez"                 "alfonso lópez i"              
##  [17] "alfonso lopez"                 "alto jordán"                  
##  [19] "altos de guadalupe"            "altos de menga"               
##  [21] "altos de santa"                "antonio nariño"               
##  [23] "aranjuez"                      "arboleda"                     
##  [25] "arboleda campestre candelaria" "arboledas"                    
##  [27] "atanasio girardot"             "autopista sur"                
##  [29] "bajo aguacatal"                "barranquilla"                 
##  [31] "barrio 7de agosto"             "barrio el recuerdo"           
##  [33] "barrio eucarístico"            "barrio obrero"                
##  [35] "barrio tranquilo y"            "base aérea"                  
##  [37] "belalcazar"                    "Belalcazar"                   
##  [39] "belisario caicedo"             "bella suiza"                  
##  [41] "bella suiza alta"              "bellavista"                   
##  [43] "benjamín herrera"              "berlin"                       
##  [45] "bloques del limonar"           "bochalema"                    
##  [47] "bolivariano"                   "bosques de alboleda"          
##  [49] "bosques del limonar"           "boyacá"                       
##  [51] "bretaña"                       "brisas de guadalupe"          
##  [53] "brisas de los"                 "Brisas De Los"                
##  [55] "brisas del guabito"            "brisas del limonar"           
##  [57] "Bueno Madrid"                  "buenos aires"                 
##  [59] "cañasgordas"                   "cañaveralejo"                 
##  [61] "cañaverales"                   "cañaverales los samanes"      
##  [63] "caldas"                        "Cali"                         
##  [65] "cali bella"                    "cali canto"                   
##  [67] "calibella"                     "calicanto"                    
##  [69] "calicanto viii"                "calima"                       
##  [71] "calimio norte"                 "calipso"                      
##  [73] "cambulos"                      "camino real"                  
##  [75] "Camino Real"                   "campestre"                    
##  [77] "caney"                         "caney especial"               
##  [79] "capri"                         "cascajal"                     
##  [81] "cataya real"                   "ceibas"                       
##  [83] "centelsa"                      "centenario"                   
##  [85] "Centenario"                    "centro"                       
##  [87] "cerro cristales"               "cerros de guadalupe"          
##  [89] "champagnat"                    "chapinero"                    
##  [91] "chiminangos"                   "Chiminangos"                  
##  [93] "chiminangos 1 etapa"           "chiminangos 2 etapa"          
##  [95] "chipichape"                    "ciudad 2000"                  
##  [97] "Ciudad 2000"                   "ciudad antejardin"            
##  [99] "ciudad bochalema"              "ciudad córdoba"               
## [101] "ciudad córdoba reservado"      "ciudad capri"                 
## [103] "ciudad cordoba"                "ciudad country"               
## [105] "ciudad del campo"              "ciudad jardín"                
## [107] "Ciudad Jardín"                 "ciudad jardin"                
## [109] "ciudad jardin pance"           "ciudad los álamos"            
## [111] "ciudad los alamos"             "ciudad meléndez"             
## [113] "ciudad melendez"               "ciudad modelo"                
## [115] "ciudad pacifica"               "Ciudad Pacifica"              
## [117] "ciudad real"                   "ciudad talanga"               
## [119] "ciudad universitaria"          "ciudadela comfandi"           
## [121] "ciudadela del río"             "ciudadela melendez"           
## [123] "ciudadela paso ancho"          "ciudadela pasoancho"          
## [125] "colinas de menga"              "colinas del bosque"           
## [127] "colinas del sur"               "colon"                        
## [129] "colseguros"                    "colseguros andes"             
## [131] "Colseguros Andes"              "comfenalco"                   
## [133] "compartir"                     "conjunto gibraltar"           
## [135] "cristóbal colón"               "cristales"                    
## [137] "cristobal colón"               "cuarto de legua"              
## [139] "departamental"                 "ed benjamin herrera"          
## [141] "el bosque"                     "El Bosque"                    
## [143] "el caney"                      "El Caney"                     
## [145] "el castillo"                   "el cedro"                     
## [147] "el diamante"                   "el dorado"                    
## [149] "el gran limonar"               "el guabal"                    
## [151] "el guabito"                    "el ingenio"                   
## [153] "El Ingenio"                    "el ingenio 3"                 
## [155] "el ingenio i"                  "el ingenio ii"                
## [157] "el ingenio iii"                "el jardín"                    
## [159] "el jordán"                     "el lido"                      
## [161] "el limonar"                    "el nacional"                  
## [163] "el paraíso"                    "el peñon"                     
## [165] "el prado"                      "el refugio"                   
## [167] "el rodeo"                      "el sena"                      
## [169] "el trébol"                    "el troncal"                   
## [171] "el vallado"                    "eucarístico"                  
## [173] "evaristo garcía"               "farrallones de pance"         
## [175] "fenalco kennedy"               "fepicol"                      
## [177] "flora"                         "flora industrial"             
## [179] "floralia"                      "fonaviemcali"                 
## [181] "francisco eladio ramirez"      "fuentes de la"                
## [183] "gaitan"                        "gran limonar"                 
## [185] "granada"                       "guadalupe"                    
## [187] "guadalupe alto"                "guaduales"                    
## [189] "guayaquil"                     "hacienda alferez real"        
## [191] "ingenio"                       "ingenio i"                    
## [193] "ingenio ii"                    "jamundi"                      
## [195] "jamundi alfaguara"             "jorge eliecer gaitán"         
## [197] "jorge isaacs"                  "jose manuel marroquín"        
## [199] "juanamb√∫"                     "juanambu"                     
## [201] "junín"                         "junin"                        
## [203] "la alborada"                   "la alianza"                   
## [205] "la arboleda"                   "la base"                      
## [207] "la buitrera"                   "la campiña"                   
## [209] "la cascada"                    "la ceibas"                    
## [211] "la esmeralda"                  "la flora"                     
## [213] "La Flora"                      "la floresta"                  
## [215] "la fortaleza"                  "la gran colombia"             
## [217] "la hacienda"                   "La Hacienda"                  
## [219] "la independencia"              "la libertad"                  
## [221] "la luisa"                      "la merced"                    
## [223] "la morada"                     "la nueva base"                
## [225] "la playa"                      "la portada al"                
## [227] "la primavera"                  "la reforma"                   
## [229] "la rivera"                     "la rivera i"                  
## [231] "la rivera ii"                  "la riverita"                  
## [233] "la riviera"                    "la selva"                     
## [235] "la villa del"                  "laflora"                      
## [237] "lares de comfenalco"           "las acacias"                  
## [239] "las américas"                 "las camelias"                 
## [241] "las ceibas"                    "las delicias"                 
## [243] "las granjas"                   "las quintas de"               
## [245] "las vegas"                     "las vegas de"                 
## [247] "libertadores"                  "los alamos"                   
## [249] "los alcázares"                 "los alcazares"                
## [251] "los andes"                     "los cámbulos"                 
## [253] "los cambulos"                  "los cristales"                
## [255] "los cristales club"            "los farallones"               
## [257] "los guaduales"                 "Los Guaduales"                
## [259] "los guayacanes"                "los jockeys"                  
## [261] "los libertadores"              "los parques barranquilla"     
## [263] "los robles"                    "lourdes"                      
## [265] "mamellan"                      "manzanares"                   
## [267] "mariano ramos"                 "marroquín iii"                
## [269] "mayapan las vegas"             "meléndez"                    
## [271] "melendez"                      "menga"                        
## [273] "metropolitano del norte"       "miradol del aguacatal"        
## [275] "miraflores"                    "Miraflores"                   
## [277] "morichal de comfandi"          "multicentro"                  
## [279] "municipal"                     "nápoles"                      
## [281] "napoles"                       "normandía"                    
## [283] "normandía west point"          "normandia"                    
## [285] "norte"                         "norte la flora"               
## [287] "nueva base"                    "nueva floresta"               
## [289] "nueva tequendama"              "oasis de comfandi"            
## [291] "oasis de pasoancho"            "occidente"                    
## [293] "pacará"                        "pacara"                       
## [295] "palmas del ingenio"            "pampa linda"                  
## [297] "pampalinda"                    "panamericano"                 
## [299] "pance"                         "Pance"                        
## [301] "parcelaciones pance"           "parque residencial el"        
## [303] "paseo de los"                  "paso del comercio"            
## [305] "pasoancho"                     "poblado campestre"            
## [307] "ponce"                         "popular"                      
## [309] "portada de comfandi"           "portales de comfandi"         
## [311] "porvenir"                      "prados de oriente"            
## [313] "prados del limonar"            "Prados Del Limonar"           
## [315] "prados del norte"              "Prados Del Norte"             
## [317] "prados del sur"                "primavera"                    
## [319] "primero de mayo"               "primitivo crespo"             
## [321] "puente del comercio"           "puente palma"                 
## [323] "quintas de don"                "Quintas De Don"               
## [325] "quintas de salomia"            "rafael uribe uribe"           
## [327] "refugio"                       "rep√∫blica de israel"         
## [329] "rincón de salomia"             "rincon de la"                 
## [331] "riveras del valle"             "rozo la torre"                
## [333] "saavedra galindo"              "salomia"                      
## [335] "samanes"                       "samanes de guadalupe"         
## [337] "sameco"                        "san antonio"                  
## [339] "san bosco"                     "san carlos"                   
## [341] "san cayetano"                  "san fernando"                 
## [343] "San Fernando"                  "san fernando nuevo"           
## [345] "san fernando viejo"            "san joaquín"                  
## [347] "san joaquin"                   "san juan bosco"               
## [349] "san judas"                     "san judas tadeo"              
## [351] "san luís"                      "san luis"                     
## [353] "san nicolás"                   "san nicolas"                  
## [355] "san pedro"                     "san vicente"                  
## [357] "santa"                         "santa anita"                  
## [359] "Santa Anita"                   "santa anita sur"              
## [361] "santa bárbara"                 "santa elena"                  
## [363] "santa fe"                      "santa helena de"              
## [365] "santa isabel"                  "Santa Isabel"                 
## [367] "santa mónica"                  "santa mónica alta"            
## [369] "santa mónica popular"          "santa mónica residencial"     
## [371] "santa monica"                  "Santa Monica"                 
## [373] "santa monica norte"            "santa monica popular"         
## [375] "santa monica residencial"      "santa rita"                   
## [377] "santa rosa"                    "santa teresita"               
## [379] "Santa Teresita"                "Santafe"                      
## [381] "santander"                     "santo domingo"                
## [383] "Santo Domingo"                 "sector aguacatal"             
## [385] "sector cañaveralejo guadalupe" "seminario"                    
## [387] "sierras de normandía"          "siete de agosto"              
## [389] "simón bolivar"                 "tejares cristales"            
## [391] "tejares de san"                "templete"                     
## [393] "tequendama"                    "tequendema"                   
## [395] "terrón colorado"               "torres de comfandi"           
## [397] "unión de vivienda"             "unicentro cali"               
## [399] "urbanización barranquilla"     "urbanización boyacá"          
## [401] "urbanización colseguros"       "urbanización la flora"        
## [403] "urbanización la merced"        "urbanización la nueva"        
## [405] "urbanización las cascadas"     "urbanización nueva granada"   
## [407] "urbanización pacara"           "urbanización río lili"        
## [409] "urbanización san joaquin"      "urbanización tequendama"      
## [411] "urbanizacion el saman"         "urbanizacion gratamira"       
## [413] "urbanizacion lili"             "valle de lili"                
## [415] "valle del lili"                "Valle Del Lili"               
## [417] "valle grande"                  "versalles"                    
## [419] "villa colombia"                "villa de veracruz"            
## [421] "villa del lago"                "villa del parque"             
## [423] "villa del prado"               "Villa Del Prado"              
## [425] "villa del sol"                 "villa del sur"                
## [427] "Villas De Veracruz"            "villas de veracruz"           
## [429] "vipasa"                        "zona centro"                  
## [431] "zona norte"                    "zona norte los"               
## [433] "zona oeste"                    "zona oriente"                 
## [435] "zona residencial"              "zona sur"                     
## [437] NA

Interpretación:
La variable barrio presenta una elevada diversidad de registros, con 437 valores distintos al considerar también los datos faltantes (NA). Sin embargo, la revisión de las categorías evidencia que este número no necesariamente corresponde al mismo número de barrios diferentes.

Se observan variaciones en la escritura de una misma ubicación, principalmente por el uso de mayúsculas y minúsculas, tildes y formas diferentes de registrar el nombre. Por ejemplo, aparecen registros como Ciudad Jardín y ciudad jardín, El Caney y el caney, Santa Anita y santa anita, así como Valle Del Lili y valle del lili. Estas diferencias hacen que R los reconozca como categorías distintas aunque puedan referirse a una misma ubicación.

También se identifican algunos registros con posibles errores de digitación o codificación y otros valores que parecen corresponder a denominaciones generales de zonas más que a nombres específicos de barrios. Adicionalmente, la variable presenta valores faltantes.

Por tanto, barrio evidencia problemas de estandarización que deberán considerarse posteriormente en la revisión de calidad de los datos. En esta etapa únicamente se identifican estas situaciones, sin realizar todavía modificaciones sobre la información original.

# Contar la cantidad de viviendas registradas en cada zona
table(vivienda$zona, useNA = "ifany")
## 
##  Zona Centro   Zona Norte   Zona Oeste Zona Oriente     Zona Sur         <NA> 
##          124         1920         1198          351         4726            3

Interpretación:
La distribución de viviendas por zona es desigual. La mayor concentración de registros se encuentra en la Zona Sur, con 4.726 observaciones, seguida por la Zona Norte con 1.920 y la Zona Oeste con 1.198. En contraste, la Zona Oriente presenta 351 registros y la Zona Centro 124.

Esta distribución muestra que algunas zonas tienen una representación mucho mayor dentro de la base. Este aspecto será relevante posteriormente, ya que el tamaño de los subconjuntos disponibles para cada solicitud dependerá de la zona y del tipo de vivienda seleccionado.

También se identifican 3 registros con valores faltantes en la variable zona, cantidad reducida frente al total de observaciones.

# Contar la cantidad de viviendas registradas por tipo
table(vivienda$tipo, useNA = "ifany")
## 
## Apartamento        Casa        <NA> 
##        5100        3219           3

Interpretación:
La base contiene una mayor proporción de apartamentos, con 5.100 registros, frente a 3.219 registros correspondientes a casas. Esta diferencia muestra que la oferta disponible en la base está más concentrada en apartamentos.

La distribución por tipo será relevante posteriormente al construir los subconjuntos requeridos para cada solicitud, ya que el número de observaciones disponibles para la modelación dependerá de la combinación entre tipo de vivienda y zona.

También se identifican 3 registros con valores faltantes en la variable tipo, cantidad reducida frente al total de observaciones.

# Contar la cantidad de viviendas registradas en cada estrato
table(vivienda$estrato, useNA = "ifany")
## 
##    3    4    5    6 <NA> 
## 1453 2129 2750 1987    3

Interpretación:
La distribución por estrato muestra una mayor concentración de viviendas en los niveles 5 y 4, con 2.750 y 2.129 registros, respectivamente. Le siguen el estrato 6, con 1.987 observaciones, y el estrato 3, con 1.453 registros.

La base presenta, por tanto, una participación importante de viviendas pertenecientes a estratos medios y altos, lo cual resulta relevante para las solicitudes analizadas, especialmente porque la primera requiere inmuebles de estrato 4 o 5 y la segunda de estrato 5 o 6.

También se identifican 3 registros con valores faltantes en la variable estrato, cantidad reducida frente al total de observaciones.

# Contar la cantidad de viviendas registradas en cada piso
table(vivienda$piso, useNA = "ifany")
## 
##   01   02   03   04   05   06   07   08   09   10   11   12 <NA> 
##  860 1450 1097  607  567  245  204  211  146  130   84   83 2638

Interpretación:
La variable piso presenta registros desde el piso 01 hasta el 12. La mayor cantidad de observaciones se concentra en los pisos bajos, especialmente en los pisos 2, 3 y 1, mientras que a partir de los pisos superiores la frecuencia disminuye progresivamente.

También se observa una cantidad importante de valores faltantes, con 2.638 registros NA. Esta ausencia de información es considerable frente al tamaño total de la base y requiere una revisión posterior antes de decidir su tratamiento.

La elevada presencia de valores faltantes podría estar relacionada con el tipo de vivienda, dado que para algunas casas esta variable puede no haber sido registrada o no resultar aplicable de la misma forma que en los apartamentos. Esta relación deberá comprobarse posteriormente mediante un análisis conjunto entre piso y tipo.

2.2 Calidad de la información

2.2.1 Valores faltantes

# Contar la cantidad de valores faltantes en cada variable
colSums(is.na(vivienda))
##           id         zona         piso      estrato      preciom    areaconst 
##            3            3         2638            3            2            3 
## parqueaderos       banios habitaciones         tipo       barrio     longitud 
##         1605            3            3            3            3            3 
##      latitud 
##            3

Interpretación:
La revisión de valores faltantes muestra que la mayoría de las variables presenta una cantidad muy reducida de datos ausentes, generalmente entre 2 y 3 registros.

Las principales excepciones son piso, con 2.638 valores faltantes, y parqueaderos, con 1.605. Estas dos variables concentran la mayor parte de la información incompleta de la base y requieren una revisión más detallada antes de definir su tratamiento.

En el caso de piso, la cantidad de valores faltantes podría estar relacionada con el tipo de vivienda, dado que esta característica puede no registrarse de la misma manera para casas y apartamentos. Por su parte, los valores faltantes en parqueaderos son especialmente relevantes porque esta variable hace parte de las características consideradas en los modelos de regresión planteados en la actividad.

Las demás variables presentan un nivel de ausencia muy bajo frente al total de 8.322 observaciones, por lo que inicialmente no representan un problema importante de completitud.

# Resumir cantidad y porcentaje de valores faltantes
# en piso según el tipo de vivienda
faltantes_piso <- vivienda |>
  dplyr::group_by(tipo) |>
  dplyr::summarise(
    total = dplyr::n(),
    piso_faltantes = sum(is.na(piso)),
    piso_porcentaje = round(
      100 * piso_faltantes / total,
      2
    )
  )

# Mostrar tabla de valores faltantes en piso
faltantes_piso
# Resumir cantidad y porcentaje de valores faltantes
# en parqueaderos según el tipo de vivienda
faltantes_parqueaderos <- vivienda |>
  dplyr::group_by(tipo) |>
  dplyr::summarise(
    total = dplyr::n(),
    parqueaderos_faltantes = sum(is.na(parqueaderos)),
    parqueaderos_porcentaje = round(
      100 * parqueaderos_faltantes / total,
      2
    )
  )

# Mostrar tabla de valores faltantes en parqueaderos
faltantes_parqueaderos

Interpretación:
La proporción de valores faltantes es mayor en las casas que en los apartamentos tanto para piso como para parqueaderos. En piso, los datos ausentes representan el 38,96 % de las casas y el 27,08 % de los apartamentos; mientras que en parqueaderos corresponden al 22,77 % y 17,04 %, respectivamente.

Aunque se observa una mayor ausencia de información en las casas, las diferencias entre ambos tipos de vivienda no son suficientemente marcadas como para atribuir los valores faltantes principalmente al tipo de inmueble. Los resultados sugieren más bien un problema general de completitud en estas variables.

Por tanto, la presencia de valores faltantes en piso y parqueaderos deberá tratarse posteriormente como un aspecto de calidad de la información, especialmente en el caso de parqueaderos, debido a que esta variable será utilizada en los modelos de regresión.

2.2.2 Registros duplicados e identificadores

# Contar cuántos registros completos están duplicados en la base
sum(duplicated(vivienda))
## [1] 1

Interpretación:
La revisión identifica 1 registro completamente duplicado en la base de datos. Esto significa que existe al menos una fila cuya información coincide exactamente con la de otra observación en todas las variables.

Aunque la cantidad es mínima frente al total de 8.322 registros, este caso deberá revisarse posteriormente para determinar si corresponde a una duplicación real de la información y, de ser así, considerar su eliminación antes de la modelación.

# Contar cuántos identificadores se encuentran repetidos
sum(duplicated(vivienda$id))
## [1] 2
# Mostrar los identificadores que aparecen más de una vez
vivienda$id[duplicated(vivienda$id)]
## [1] NA NA

Interpretación:
La revisión inicial muestra 2 valores identificados como duplicados en la variable id; sin embargo, ambos corresponden a valores faltantes (NA). Esto ocurre porque R considera como repetidos el segundo y los siguientes NA encontrados en una variable.

Por tanto, este resultado no evidencia todavía la existencia de identificadores numéricos repetidos. Los registros observados corresponden a los 3 casos en los que id no fue diligenciado.

# Revisar si existen identificadores repetidos,
# excluyendo previamente los valores faltantes
id_validos <- vivienda$id[!is.na(vivienda$id)]

# Contar identificadores repetidos
sum(duplicated(id_validos))
## [1] 0
# Mostrar los identificadores repetidos, en caso de existir
id_validos[duplicated(id_validos)]
## numeric(0)

Interpretación:
Una vez excluidos los valores faltantes de la variable id, no se identifican identificadores numéricos repetidos. El resultado de 0 registros duplicados y la salida numeric(0) confirman que cada identificador válido aparece una sola vez en la base.

Por tanto, el problema observado previamente en id se limita a los 3 valores faltantes y no a la existencia de identificadores duplicados entre los registros válidos.

2.2.3 Revisión de valores inconsistentes

# Contar viviendas registradas con cero baños
sum(vivienda$banios == 0, na.rm = TRUE)
## [1] 45
# Contar viviendas registradas con cero habitaciones
sum(vivienda$habitaciones == 0, na.rm = TRUE)
## [1] 66

Interpretación:
Se identifican 45 viviendas registradas con cero baños y 66 viviendas con cero habitaciones. Aunque estas cantidades representan una proporción reducida frente al total de 8.322 observaciones, requieren una revisión específica por tratarse de características que, en principio, deberían estar presentes en una vivienda.

En el caso de banios = 0, el valor resulta especialmente llamativo, ya que una vivienda ofertada normalmente debería disponer de al menos un baño. Por tanto, estos registros podrían corresponder a errores de diligenciamiento o codificación.

Para habitaciones = 0, la interpretación requiere mayor cautela. Algunos inmuebles, como apartamentos tipo estudio, podrían no registrar habitaciones independientes. Sin embargo, este valor sería menos coherente en determinados tipos de vivienda, por lo que conviene revisar estos casos junto con la variable tipo.

En consecuencia, los valores cero en baños y habitaciones deben considerarse como registros potencialmente inconsistentes y serán revisados con mayor detalle antes de decidir su tratamiento en la base utilizada para la modelación.

# Resumir cantidad y porcentaje de viviendas con cero baños
# según el tipo de vivienda
banios_cero_tipo <- vivienda |>
  dplyr::group_by(tipo) |>
  dplyr::summarise(
    total = dplyr::n(),
    banios_cero = sum(banios == 0, na.rm = TRUE),
    banios_cero_porcentaje = round(
      100 * banios_cero / total,
      2
    )
  )

# Mostrar tabla de viviendas con cero baños
banios_cero_tipo
# Resumir cantidad y porcentaje de viviendas con cero habitaciones
# según el tipo de vivienda
habitaciones_cero_tipo <- vivienda |>
  dplyr::group_by(tipo) |>
  dplyr::summarise(
    total = dplyr::n(),
    habitaciones_cero = sum(habitaciones == 0, na.rm = TRUE),
    habitaciones_cero_porcentaje = round(
      100 * habitaciones_cero / total,
      2
    )
  )

# Mostrar tabla de viviendas con cero habitaciones
habitaciones_cero_tipo

Interpretación:
Los registros con cero baños y cero habitaciones representan una proporción reducida dentro de cada tipo de vivienda. En el caso de banios = 0, corresponden al 0,27 % de los apartamentos y al 0,96 % de las casas. Para habitaciones = 0, representan el 0,41 % de los apartamentos y el 1,40 % de las casas.

Aunque las proporciones son mayores en las casas, los valores cero se presentan en ambos tipos de vivienda y no se observa una concentración exclusiva en una categoría determinada. Por tanto, estos casos parecen corresponder a registros aislados que requieren revisión individual, más que a una característica asociada al tipo de inmueble.

Dado que una vivienda con cero baños resulta poco plausible y que una casa con cero habitaciones también genera dudas sobre la consistencia del registro, estos casos deberán considerarse posteriormente al definir los criterios de depuración de la base.

2.2.4 Revisión de valores extremos

# Organizar varios gráficos en una misma figura
# Se muestran dos gráficos por fila
par(mfrow = c(4, 2))

# Precio de las viviendas
boxplot(
  vivienda$preciom,
  horizontal = TRUE,
  main = "Precio",
  xlab = "Millones de pesos"
)

# Área construida
boxplot(
  vivienda$areaconst,
  horizontal = TRUE,
  main = "Área construida",
  xlab = "m²"
)

# Número de parqueaderos
boxplot(
  vivienda$parqueaderos,
  horizontal = TRUE,
  main = "Parqueaderos",
  xlab = "Número"
)

# Número de baños
boxplot(
  vivienda$banios,
  horizontal = TRUE,
  main = "Baños",
  xlab = "Número"
)

# Número de habitaciones
boxplot(
  vivienda$habitaciones,
  horizontal = TRUE,
  main = "Habitaciones",
  xlab = "Número"
)

# Longitud geográfica
boxplot(
  vivienda$longitud,
  horizontal = TRUE,
  main = "Longitud",
  xlab = "Coordenada"
)

# Latitud geográfica
boxplot(
  vivienda$latitud,
  horizontal = TRUE,
  main = "Latitud",
  xlab = "Coordenada"
)

# Restaurar la configuración gráfica
par(mfrow = c(1, 1))

Interpretación:
Los diagramas de caja muestran que varias de las variables cuantitativas presentan observaciones que, de acuerdo con el criterio estadístico del boxplot, se encuentran alejadas del comportamiento central de los datos.

  • preciom: la distribución presenta una clara asimetría hacia la derecha y numerosos valores por encima del límite superior del diagrama. Esto indica la presencia de viviendas con precios considerablemente mayores frente a la mayoría de las ofertas. Sin embargo, estos valores no deben interpretarse automáticamente como errores, ya que pueden corresponder a inmuebles de alto valor.

  • areaconst: se observa un comportamiento similar al precio, con una concentración importante de viviendas en áreas relativamente menores y numerosos registros con superficies superiores al rango central. Los valores más elevados pueden corresponder a propiedades de gran tamaño, por lo que deberán contrastarse posteriormente con otras características del inmueble.

  • parqueaderos: la mayor parte de las viviendas se concentra entre uno y dos parqueaderos. Los registros con cuatro o más aparecen como valores extremos según el criterio del boxplot. Aunque son poco frecuentes, podrían ser razonables en viviendas de gran área o de características particulares.

  • banios: la mayoría de las observaciones se concentra aproximadamente entre dos y cuatro baños. Se identifican valores elevados, principalmente entre ocho y diez baños, que aparecen como extremos. También se conserva la presencia de registros con cero baños, cuya consistencia requiere una revisión diferente, debido a que este valor resulta poco plausible para una vivienda.

  • habitaciones: la distribución se concentra principalmente entre tres y cuatro habitaciones. Se observan valores extremos tanto en la parte inferior como en la superior, incluyendo registros con cero habitaciones y viviendas con seis o más. Los valores altos pueden ser razonables para propiedades grandes, mientras que los registros con cero habitaciones requieren una revisión adicional.

  • longitud: se identifican observaciones en ambos extremos de la distribución, especialmente hacia los valores más altos de longitud. Debido a que esta variable representa una coordenada geográfica, estos puntos no deben considerarse errores únicamente por aparecer como extremos en el boxplot. Su validez deberá evaluarse posteriormente mediante la ubicación espacial de los registros.

  • latitud: presenta una distribución más regular y no se evidencian observaciones claramente identificadas como extremas bajo el criterio del boxplot.

En conjunto, los resultados muestran que las variables preciom y areaconst presentan una importante concentración de valores altos, mientras que parqueaderos, banios y habitaciones contienen algunos casos poco frecuentes. La identificación estadística de estos valores no implica que deban eliminarse de forma automática; su tratamiento deberá considerar si corresponden a registros válidos y el posible efecto que puedan tener sobre los modelos de regresión.

# Variables cuantitativas que se revisarán
variables_extremos <- c(
  "preciom",
  "areaconst",
  "parqueaderos",
  "banios",
  "habitaciones",
  "longitud",
  "latitud"
)

# Calcular los límites del criterio IQR
# y resumir la cantidad de valores extremos
tabla_extremos <- lapply(
  variables_extremos,
  function(variable) {

    x <- vivienda[[variable]]

    # Calcular cuartiles eliminando el nombre que genera quantile()
    q1 <- unname(quantile(x, 0.25, na.rm = TRUE))
    q3 <- unname(quantile(x, 0.75, na.rm = TRUE))
    iqr <- IQR(x, na.rm = TRUE)

    # Límites utilizados por el criterio del boxplot
    limite_inferior <- q1 - 1.5 * iqr
    limite_superior <- q3 + 1.5 * iqr

    # Número de observaciones válidas
    total_validos <- sum(!is.na(x))

    # Contar valores ubicados fuera de los límites
    total_extremos <- sum(
      x < limite_inferior | x > limite_superior,
      na.rm = TRUE
    )

    data.frame(
      Variable = variable,
      `Límite inferior` = round(limite_inferior, 2),
      `Límite superior` = round(limite_superior, 2),
      `Valores extremos` = total_extremos,
      `Porcentaje (%)` = round(
        100 * total_extremos / total_validos,
        2
      ),
      check.names = FALSE
    )
  }
) |>
  dplyr::bind_rows()

# Presentar el resultado como una tabla limpia en el informe
knitr::kable(
  tabla_extremos,
  align = c("l", "r", "r", "r", "r"),
  caption = "Valores extremos según el criterio del rango intercuartílico (IQR)"
)
Valores extremos según el criterio del rango intercuartílico (IQR)
Variable Límite inferior Límite superior Valores extremos Porcentaje (%)
preciom -260.00 1020.00 552 6.63
areaconst -143.50 452.50 382 4.59
parqueaderos -0.50 3.50 567 8.44
banios -1.00 7.00 72 0.87
habitaciones 1.50 5.50 888 10.67
longitud -76.58 -76.48 130 1.56
latitud 3.27 3.56 0 0.00

Interpretación:
La aplicación del criterio del rango intercuartílico (IQR) permite identificar observaciones alejadas del comportamiento central de cada variable. Estos registros deben entenderse como potenciales valores extremos y no necesariamente como errores de la base.

  • preciom: se identifican 552 valores extremos, equivalentes al 6,63 % de las observaciones válidas. El límite superior se ubica en 1.020 millones de pesos. Aunque estos valores se encuentran alejados del centro de la distribución, resultan plausibles dentro de un mercado inmobiliario en el que pueden existir propiedades de alto valor.

  • areaconst: se identifican 382 valores extremos, correspondientes al 4,59 %. El límite superior se establece en 452,5 m². Las viviendas que superan este valor pueden corresponder a propiedades de gran tamaño, por lo que su presencia no implica necesariamente una inconsistencia.

  • parqueaderos: presenta 567 valores extremos, equivalentes al 8,44 % de los registros válidos. El criterio considera extremos los valores iguales o superiores a 4 parqueaderos. Aunque son menos frecuentes, este tipo de inmuebles puede encontrarse en propiedades de mayor tamaño o valor.

  • banios: se identifican 72 valores extremos, que representan el 0,87 % de los registros válidos. El límite superior corresponde a 7 baños. Los valores por encima de este nivel pueden resultar poco frecuentes, pero son posibles en viviendas de características especiales.

  • habitaciones: presenta la mayor proporción de valores extremos, con 888 registros, equivalentes al 10,67 %. El criterio IQR clasifica como extremos los valores inferiores a 1,5 y superiores a 5,5 habitaciones. Sin embargo, viviendas con 6 o más habitaciones pueden ser perfectamente válidas dentro del mercado inmobiliario, por lo que este resultado evidencia que el criterio estadístico no debe utilizarse de manera automática como regla de eliminación.

  • longitud: presenta 130 valores extremos, equivalentes al 1,56 %. Al tratarse de una coordenada geográfica, estos valores no deben interpretarse como inconsistentes únicamente por ubicarse fuera de los límites del IQR. Su coherencia deberá evaluarse mediante la representación espacial de las viviendas.

  • latitud: no presenta observaciones clasificadas como extremas bajo este criterio.

En conjunto, se observa una mayor presencia de valores extremos en habitaciones, parqueaderos y preciom. No obstante, las magnitudes encontradas son razonables dentro del contexto inmobiliario, especialmente considerando que la base puede incluir propiedades de diferentes tamaños, características y niveles de valor.

Por esta razón, los valores extremos identificados mediante el criterio IQR se mantendrán inicialmente en la base. Su posible influencia será evaluada posteriormente durante el ajuste y diagnóstico de los modelos, mientras que la depuración se concentrará principalmente en registros con características poco plausibles, problemas de completitud o inconsistencias evidentes.

2.3 Limpieza general de la base

A partir de los hallazgos obtenidos en la exploración inicial y en la revisión de calidad de los datos, se realizan algunas transformaciones generales antes de construir los subconjuntos correspondientes a cada solicitud.

# Crear una copia de la base original para realizar
# las transformaciones sin modificar el objeto vivienda
vivienda_new <- vivienda

Interpretación:
Se crea la base vivienda_new como copia de la información original. De esta manera, las transformaciones y decisiones de limpieza se realizan sobre una nueva base, conservando vivienda sin modificaciones como referencia del conjunto de datos inicial.

# Convertir las variables categóricas a tipo factor
# para que R las reconozca como categorías en los análisis posteriores
vivienda_new <- vivienda_new |>
  dplyr::mutate(
    zona = as.factor(zona),
    tipo = as.factor(tipo),
    barrio = as.factor(barrio),
    piso = as.factor(piso)
  )

Interpretación:
Las variables zona, tipo, barrio y piso se convierten a tipo factor debido a que representan categorías. La variable estrato se mantiene inicialmente en formato numérico para facilitar la construcción de los subconjuntos requeridos, aunque conceptualmente corresponde a una variable cualitativa ordinal.

Su tratamiento dentro de los modelos se definirá posteriormente. En particular, al tratarse de una variable categórica, podrá representarse mediante variables binarias de acuerdo con el procedimiento utilizado para variables cualitativas en regresión lineal.

# Recodificar como valores faltantes los registros
# con cero baños o cero habitaciones
vivienda_new <- vivienda_new |>
  dplyr::mutate(
    banios = ifelse(banios == 0, NA, banios),
    habitaciones = ifelse(habitaciones == 0, NA, habitaciones)
  )

Interpretación:
Los registros con banios = 0 y habitaciones = 0 se recodifican como valores faltantes (NA), debido a que representan características poco plausibles para una vivienda y pueden corresponder a errores de registro o ausencia de información.

La cantidad de casos involucrados es reducida frente al tamaño total de la base, por lo que esta recodificación no afecta de manera importante el volumen de información disponible. En particular, se habían identificado 45 registros con cero baños y 66 con cero habitaciones.

Esta decisión permite tratar posteriormente estos casos dentro del análisis general de valores faltantes, evitando que valores potencialmente inconsistentes sean utilizados directamente en la estimación de los modelos.

# Eliminar registros completamente duplicados
# conservando únicamente la primera aparición
vivienda_new <- vivienda_new |>
  dplyr::distinct()

Interpretación:
Se elimina el registro completamente duplicado identificado durante la revisión de calidad de los datos. Al tratarse de una observación que repite exactamente la información de otro registro, su eliminación evita contabilizar dos veces la misma oferta sin generar una pérdida relevante de información.

Dado que se identificó únicamente un registro duplicado frente al tamaño total de la base, esta decisión tiene un efecto mínimo sobre el número de observaciones disponibles.

# Eliminar registros con valores faltantes únicamente
# en las variables necesarias para el análisis y la modelación
vivienda_new <- vivienda_new |>
  tidyr::drop_na(
    zona,
    estrato,
    preciom,
    areaconst,
    parqueaderos,
    banios,
    habitaciones,
    tipo,
    longitud,
    latitud
  )

Interpretación:
Se eliminan los registros que presentan valores faltantes en las variables necesarias para la construcción de las solicitudes y para la estimación de los modelos de regresión.

La depuración se limita a las variables directamente relacionadas con el análisis, evitando eliminar observaciones únicamente por ausencia de información en piso o barrio, dado que estas variables no forman parte del modelo planteado.

Esta decisión permite conservar la mayor cantidad posible de información útil, al mismo tiempo que garantiza que los registros utilizados posteriormente cuenten con datos completos en las variables requeridas para la modelación.

# Comparar el tamaño de la base original con la base depurada
registros_originales <- nrow(vivienda)
registros_limpios <- nrow(vivienda_new)
registros_eliminados <- registros_originales - registros_limpios

# Calcular el porcentaje de registros eliminados
porcentaje_eliminado <- round(
  100 * registros_eliminados / registros_originales,
  2
)

# Mostrar el resumen del proceso de limpieza
data.frame(
  Base = c(
    "Base original",
    "Base después de la limpieza",
    "Registros eliminados"
  ),
  Registros = c(
    registros_originales,
    registros_limpios,
    registros_eliminados
  )
)
# Mostrar porcentaje eliminado
porcentaje_eliminado
## [1] 19.63

Interpretación:
Después del proceso de limpieza general, la base pasa de 8.322 a 6.688 registros, lo que representa la eliminación de 1.634 observaciones, equivalentes al 19,63 % del total inicial.

La reducción se explica principalmente por la exclusión de registros con valores faltantes en las variables necesarias para la construcción de las solicitudes y la estimación de los modelos, así como por la recodificación de valores poco plausibles en baños y habitaciones y la eliminación del registro completamente duplicado.

A pesar de la reducción, se conserva más del 80 % de la información original, por lo que la base mantiene un tamaño amplio para continuar con la construcción de los subconjuntos correspondientes a cada solicitud y realizar posteriormente los análisis exploratorios y modelos de regresión.

2.4 Construcción de la base para la Vivienda 1

# Construir la base correspondiente a la primera solicitud:
# casas ubicadas en la Zona Norte y de estrato 4 o 5
vivienda1 <- vivienda_new |>
  dplyr::filter(
    tipo == "Casa",
    zona == "Zona Norte",
    estrato %in% c(4, 5)
  )

# Revisar el tamaño de la base obtenida
dim(vivienda1)
## [1] 323  13
# Mostrar los primeros tres registros
head(vivienda1, 3)

Interpretación:
La base correspondiente a la Vivienda 1 quedó conformada por 323 casas ubicadas en la Zona Norte y pertenecientes a los estratos 4 o 5. El subconjunto conserva las 13 variables de la base depurada; sin embargo, en las etapas posteriores se seleccionarán y tratarán únicamente aquellas variables necesarias para el análisis exploratorio y la construcción del modelo de regresión.

2.5 Construcción de la base para la Vivienda 2

# Construir la base correspondiente a la segunda solicitud:
# apartamentos ubicados en la Zona Sur y de estrato 5 o 6
vivienda2 <- vivienda_new |>
  dplyr::filter(
    tipo == "Apartamento",
    zona == "Zona Sur",
    estrato %in% c(5, 6)
  )

# Revisar el tamaño de la base obtenida
dim(vivienda2)
## [1] 1437   13
# Mostrar los primeros tres registros
head(vivienda2, 3)

Interpretación:
La base correspondiente a la Vivienda 2 quedó conformada por apartamentos ubicados en la Zona Sur y pertenecientes a los estratos 5 o 6. El subconjunto conserva las 13 variables de la base depurada; sin embargo, en las etapas posteriores se seleccionarán y tratarán únicamente aquellas variables necesarias para el análisis exploratorio y la construcción del modelo de regresión.

3 Análisis de la Vivienda 1: Casa en Zona Norte

3.1 Caracterización de la base

# Revisar el tamaño de la base correspondiente a la Vivienda 1
dim(vivienda1)
## [1] 323  13

Interpretación:
La base correspondiente a la Vivienda 1 está conformada por 323 registros y 13 variables. Las observaciones corresponden a casas ubicadas en la Zona Norte y pertenecientes a los estratos 4 o 5, de acuerdo con las condiciones definidas para la primera solicitud.

El tamaño del subconjunto permite contar con una cantidad suficiente de observaciones para continuar con el análisis exploratorio y la posterior estimación del modelo de regresión. Las 13 variables se conservan inicialmente para mantener toda la información disponible, aunque en las etapas posteriores se seleccionarán aquellas que resulten relevantes para el análisis y la modelación.

# Obtener un resumen descriptivo de las variables cuantitativas
# relevantes para el análisis de la Vivienda 1
summary(
  vivienda1[, c(
    "preciom",
    "areaconst",
    "parqueaderos",
    "banios",
    "habitaciones"
  )]
)
##     preciom       areaconst     parqueaderos      banios      habitaciones  
##  Min.   : 215   Min.   :  73   Min.   :1.00   Min.   :2.00   Min.   : 2.00  
##  1st Qu.: 350   1st Qu.: 201   1st Qu.:1.00   1st Qu.:3.00   1st Qu.: 4.00  
##  Median : 450   Median : 280   Median :2.00   Median :4.00   Median : 4.00  
##  Mean   : 511   Mean   : 309   Mean   :2.31   Mean   :3.96   Mean   : 4.82  
##  3rd Qu.: 600   3rd Qu.: 364   3rd Qu.:3.00   3rd Qu.:5.00   3rd Qu.: 5.00  
##  Max.   :1940   Max.   :1188   Max.   :9.00   Max.   :8.00   Max.   :10.00

Interpretación:

  • Precio (preciom): los precios de las casas se encuentran entre 215 y 1.940 millones de pesos. El 50 % central de las ofertas está aproximadamente entre 350 y 600 millones, con una mediana de 450 millones. La media, de 511 millones, es superior a la mediana, lo que sugiere que algunas viviendas de mayor valor están desplazando el promedio hacia arriba. El precio máximo de 1.940 millones es considerablemente superior al comportamiento central de la base, pero resulta posible dentro del mercado inmobiliario para una casa de características especiales, por lo que no se considera por sí solo un dato inconsistente.

  • Área construida (areaconst): las viviendas presentan áreas entre 73 y 1.188 m². La mitad central de las observaciones se encuentra entre 201 y 364 m², con una mediana de 280 m² y una media de 309 m². La diferencia entre media y mediana también sugiere cierta concentración de propiedades de gran tamaño en la parte superior de la distribución. Aunque el máximo de 1.188 m² es elevado, puede corresponder a una vivienda de gran tamaño y no constituye necesariamente un error de registro.

  • Parqueaderos: las casas cuentan entre 1 y 9 parqueaderos. El 50 % central de las observaciones se encuentra entre 1 y 3, con una mediana de 2 y un promedio de 2,31. Por tanto, lo habitual dentro de este subconjunto es encontrar viviendas con pocos parqueaderos. Los valores más altos son poco frecuentes frente al comportamiento central, pero son posibles en casas grandes o de mayor valor y no muestran, en principio, una inconsistencia evidente.

  • Baños (banios): el número de baños varía entre 2 y 8. La mitad de las viviendas se concentra entre 3 y 5 baños, mientras que la mediana es de 4 y la media de 3,96. La cercanía entre media y mediana indica un comportamiento central bastante similar en esta variable. Además, después del proceso de limpieza ya no aparecen viviendas con cero baños. Tanto el mínimo de 2 como el máximo de 8 resultan plausibles para casas pertenecientes a los estratos y la zona considerados.

  • Habitaciones: el número de habitaciones se encuentra entre 2 y 10. El 50 % central de las viviendas presenta entre 4 y 5 habitaciones, con una mediana de 4 y una media de 4,82. La mayor diferencia entre la media y la mediana puede estar asociada con algunas propiedades que presentan un número elevado de habitaciones. Sin embargo, valores de hasta 10 habitaciones pueden encontrarse en casas de gran tamaño y no se consideran necesariamente inconsistentes. Asimismo, ya no aparecen registros con cero habitaciones después de la limpieza realizada.

En general, las variables presentan valores coherentes con las características que podrían encontrarse en el mercado de casas de la Zona Norte y de estratos 4 y 5. Se observan algunas propiedades con precios, áreas y características físicas considerablemente superiores al comportamiento central, pero estas observaciones pueden representar inmuebles reales de mayor tamaño o dotación. Por esta razón, no se identifican en este resumen nuevos valores que justifiquen una eliminación automática. La forma de las distribuciones y la presencia de observaciones alejadas del comportamiento central se examinarán con mayor claridad mediante histogramas y diagramas de cajas.

3.2 Análisis exploratorio específico

3.2.1 Distribución de las variables cuantitativas

# Organizar los histogramas en una sola figura
par(mfrow = c(3, 2))

# Distribución del precio
hist(
  vivienda1$preciom,
  main = "Distribución del precio",
  xlab = "Precio (millones de pesos)"
)

# Distribución del área construida
hist(
  vivienda1$areaconst,
  main = "Distribución del área construida",
  xlab = "Área construida (m²)"
)

# Distribución del número de parqueaderos
hist(
  vivienda1$parqueaderos,
  main = "Distribución de parqueaderos",
  xlab = "Número de parqueaderos"
)

# Distribución del número de baños
hist(
  vivienda1$banios,
  main = "Distribución de baños",
  xlab = "Número de baños"
)

# Distribución del número de habitaciones
hist(
  vivienda1$habitaciones,
  main = "Distribución de habitaciones",
  xlab = "Número de habitaciones"
)

# Restablecer la configuración gráfica
par(mfrow = c(1, 1))

Interpretación:

  • Precio (preciom): la distribución presenta una clara asimetría hacia la derecha. La mayor parte de las viviendas se concentra en los rangos de precios bajos y medios, principalmente por debajo de aproximadamente 600 millones de pesos. A medida que aumenta el precio, la frecuencia disminuye considerablemente y se observa una cola larga hacia valores altos. Este comportamiento es coherente con el resumen descriptivo, donde la media fue superior a la mediana. En el contexto inmobiliario, esta distribución resulta razonable, ya que es esperable encontrar muchas más propiedades en rangos intermedios que viviendas de muy alto valor.

  • Área construida (areaconst): también se observa una distribución asimétrica hacia la derecha. La mayor concentración de viviendas se encuentra aproximadamente entre 150 y 400 m², mientras que las propiedades con áreas superiores son cada vez menos frecuentes. Se identifica una cola que se extiende hacia viviendas de gran tamaño, incluso por encima de 800 m². Aunque estas áreas son poco frecuentes, pueden corresponder a casas grandes y no se consideran necesariamente inconsistencias.

  • Parqueaderos: la distribución se encuentra fuertemente concentrada en los valores bajos. La mayoría de las viviendas dispone de uno o dos parqueaderos y, a medida que aumenta su número, la frecuencia disminuye rápidamente. Las casas con cuatro o más parqueaderos son poco frecuentes, aunque resultan posibles en propiedades de mayor tamaño o valor. La distribución presenta, por tanto, una marcada asimetría hacia la derecha.

  • Baños (banios): la distribución presenta una mayor concentración entre tres y cinco baños, siendo cuatro baños uno de los valores más frecuentes. A diferencia del precio, el área y los parqueaderos, la distribución muestra una concentración más definida alrededor de valores centrales. A partir de seis baños la frecuencia disminuye considerablemente. Los valores de siete u ocho baños son poco frecuentes, pero pueden ser razonables en viviendas de gran tamaño.

  • Habitaciones: la mayor parte de las viviendas se concentra entre tres y cinco habitaciones, con una disminución progresiva de la frecuencia a medida que aumenta el número de habitaciones. Se observa una asimetría hacia la derecha debido a la presencia de algunas propiedades con seis o más habitaciones. Aunque los valores más altos son poco frecuentes, pueden corresponder a casas de mayor tamaño y no representan por sí mismos inconsistencias.

En conjunto, las distribuciones muestran que preciom, areaconst, parqueaderos y, en menor medida, habitaciones presentan asimetría positiva, caracterizada por una mayor concentración en valores bajos o intermedios y una cola hacia valores superiores. Este comportamiento es razonable en el contexto inmobiliario y sugiere que existen algunas propiedades con características considerablemente mayores al comportamiento central de la base. Estas diferencias deberán tenerse en cuenta posteriormente al analizar las relaciones entre las variables y al evaluar el ajuste del modelo de regresión.

# Organizar los diagramas de cajas en una sola figura
par(mfrow = c(3, 2))

# Diagrama de cajas del precio
boxplot(
  vivienda1$preciom,
  main = "Precio",
  ylab = "Millones de pesos"
)

# Diagrama de cajas del área construida
boxplot(
  vivienda1$areaconst,
  main = "Área construida",
  ylab = "Área construida (m²)"
)

# Diagrama de cajas del número de parqueaderos
boxplot(
  vivienda1$parqueaderos,
  main = "Parqueaderos",
  ylab = "Número de parqueaderos"
)

# Diagrama de cajas del número de baños
boxplot(
  vivienda1$banios,
  main = "Baños",
  ylab = "Número de baños"
)

# Diagrama de cajas del número de habitaciones
boxplot(
  vivienda1$habitaciones,
  main = "Habitaciones",
  ylab = "Número de habitaciones"
)

# Restablecer la configuración gráfica
par(mfrow = c(1, 1))

Interpretación:

  • Precio (preciom): el diagrama de cajas confirma una marcada asimetría hacia valores altos. La mayor parte de los precios se concentra alrededor del rango central identificado previamente, mientras que aparecen varias observaciones por encima del bigote superior. Estas viviendas son clasificadas estadísticamente como valores extremos, pero su magnitud puede ser razonable dentro del mercado inmobiliario, especialmente para casas de mayor tamaño, ubicación o dotación.

  • Área construida (areaconst): también se observa una concentración importante en los valores intermedios y varias observaciones por encima del límite superior del diagrama. Esto coincide con la cola derecha observada en el histograma. Las áreas elevadas corresponden a propiedades poco frecuentes dentro del subconjunto, pero pueden representar casas grandes y no necesariamente errores de registro.

  • Parqueaderos: la mayor parte de las viviendas se concentra entre 1 y 3 parqueaderos, mientras que algunos registros con cantidades superiores aparecen como valores extremos. Aunque estos casos son menos comunes, disponer de 7, 8 o 9 parqueaderos puede ser plausible en propiedades de gran tamaño, por lo que no se considera suficiente para excluir dichas observaciones.

  • Baños (banios): presenta un comportamiento más compacto que las variables anteriores. La mayoría de las viviendas se encuentra aproximadamente entre 3 y 5 baños, y el diagrama no evidencia una presencia importante de observaciones alejadas del comportamiento general. Los valores superiores, que alcanzan hasta 8 baños, permanecen dentro de un rango plausible para este tipo de inmuebles.

  • Habitaciones: la mayor concentración se encuentra alrededor de 4 y 5 habitaciones. Se observan algunas viviendas con cantidades altas de habitaciones y también algunos valores bajos que el criterio del boxplot identifica como alejados del comportamiento central. Sin embargo, tanto una casa con 2 habitaciones como propiedades con 7 a 10 habitaciones son posibles en el mercado y no constituyen por sí mismas inconsistencias.

En conjunto, los diagramas de cajas confirman lo observado en los histogramas: preciom, areaconst y parqueaderos presentan una mayor concentración de observaciones alejadas hacia valores altos, mientras que banios muestra un comportamiento más estable. En habitaciones existen valores tanto inferiores como superiores al rango central. No obstante, los casos identificados como extremos son plausibles desde el punto de vista inmobiliario, por lo que se mantienen para los análisis posteriores. Su posible influencia sobre la estimación se evaluará posteriormente durante el diagnóstico del modelo.

3.2.2 Comportamiento del estrato

# Calcular la frecuencia de viviendas por estrato
frecuencia_estrato <- table(vivienda1$estrato)

# Calcular el porcentaje de viviendas por estrato
porcentaje_estrato <- prop.table(frecuencia_estrato) * 100

# Mostrar la distribución por estrato
data.frame(
  Estrato = names(frecuencia_estrato),
  Frecuencia = as.vector(frecuencia_estrato),
  Porcentaje = round(as.vector(porcentaje_estrato), 2)
)

Interpretación:
La distribución por estrato muestra que la base correspondiente a la Vivienda 1 se encuentra conformada por 101 viviendas de estrato 4 y 222 viviendas de estrato 5. En términos porcentuales, esto equivale al 31,27 % y 68,73 %, respectivamente.

Estos resultados evidencian una mayor participación de viviendas de estrato 5 dentro del subconjunto analizado. No obstante, ambos estratos requeridos para la solicitud se encuentran representados en la base, lo que permite considerar su comportamiento posteriormente en el análisis del precio.

# Resumir el precio de las viviendas de estrato 4
summary(
  vivienda1$preciom[vivienda1$estrato == 4]
)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     215     330     380     427     530     830
# Resumir el precio de las viviendas de estrato 5
summary(
  vivienda1$preciom[vivienda1$estrato == 5]
)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     245     380     480     549     650    1940
# Comparar visualmente el precio entre estratos
boxplot(
  preciom ~ estrato,
  data = vivienda1,
  main = "Precio de las viviendas según estrato",
  xlab = "Estrato",
  ylab = "Precio (millones de pesos)"
)

Interpretación:

  • Estrato 4: los precios se encuentran entre 215 y 830 millones de pesos. La mediana es de 380 millones y la media de 427 millones. El 50 % central de las viviendas se encuentra aproximadamente entre 330 y 530 millones.

  • Estrato 5: los precios presentan un rango mucho más amplio, entre 245 y 1.940 millones de pesos. La mediana aumenta a 480 millones y la media a 549 millones. El 50 % central se encuentra aproximadamente entre 380 y 650 millones.

La comparación evidencia que las viviendas de estrato 5 presentan, en general, precios más altos que las de estrato 4. Esto se observa tanto en la media como en la mediana y también en la posición de las cajas del diagrama.

Además, el estrato 5 presenta una mayor dispersión y varios valores elevados por encima del comportamiento central, mientras que en el estrato 4 la distribución es más compacta. No obstante, existe una zona importante de superposición entre ambos grupos, por lo que el estrato por sí solo no determina completamente el precio de la vivienda.

En términos del análisis posterior, estos resultados sugieren que el estrato puede aportar información relevante para explicar el precio, aunque será necesario evaluarlo conjuntamente con variables como el área construida, los baños, las habitaciones y los parqueaderos.

3.2.3 Relación entre el precio y las variables explicativas

# Calcular la correlación entre el precio
# y el área construida
cor(
  vivienda1$preciom,
  vivienda1$areaconst,
  use = "complete.obs"
)
## [1] 0.7029
# Graficar la relación entre el precio
# y el área construida
plot(
  vivienda1$areaconst,
  vivienda1$preciom,
  main = "Precio vs. área construida",
  xlab = "Área construida (m²)",
  ylab = "Precio (millones de pesos)",
  pch = 19
)

# Agregar una línea de tendencia lineal
abline(
  lm(preciom ~ areaconst, data = vivienda1),
  lwd = 2
)

Interpretación:

La relación entre el precio y el área construida es positiva y relativamente fuerte, con una correlación de 0,7029. Esto indica que, en términos generales, las casas con mayor área construida tienden a presentar precios más altos.

La nube de puntos muestra una tendencia ascendente clara, coherente con la línea de ajuste lineal. Sin embargo, la relación no parece completamente uniforme a lo largo de toda la distribución. En particular, a medida que aumenta el área construida también se incrementa la dispersión de los precios, especialmente en las viviendas de mayor tamaño.

Este comportamiento sugiere que la relación entre ambas variables podría no estar representándose de la mejor manera únicamente en su escala original. Por esta razón, antes de definir la especificación del modelo se evaluarán distintas transformaciones logarítmicas de estas variables, con el propósito de determinar si alguna de ellas permite representar de forma más adecuada la relación observada.

En particular, se compararán las siguientes alternativas:

  • precio en escala original frente al logaritmo del área construida;
  • logaritmo del precio frente al área construida en escala original;
  • logaritmo del precio frente al logaritmo del área construida.

Estas comparaciones permitirán establecer si alguna transformación mejora la linealidad de la relación y reduce la dispersión observada en los valores altos. La decisión final sobre la forma funcional que se utilizará en el modelo se tomará posteriormente con base en la evidencia obtenida y no únicamente a partir de la inspección visual.

En conjunto, el área construida se perfila como una de las variables con mayor capacidad explicativa sobre el precio, pero su forma de incorporación al modelo deberá evaluarse cuidadosamente.

# Comparar diferentes formas funcionales de la relación
# entre el precio y el área construida

# 1. Precio vs. área construida
cor(
  vivienda1$preciom,
  vivienda1$areaconst,
  use = "complete.obs"
)
## [1] 0.7029
# 2. Precio vs. logaritmo del área construida
cor(
  vivienda1$preciom,
  log(vivienda1$areaconst),
  use = "complete.obs"
)
## [1] 0.6672
# 3. Logaritmo del precio vs. área construida
cor(
  log(vivienda1$preciom),
  vivienda1$areaconst,
  use = "complete.obs"
)
## [1] 0.7113
# 4. Logaritmo del precio vs. logaritmo del área construida
cor(
  log(vivienda1$preciom),
  log(vivienda1$areaconst),
  use = "complete.obs"
)
## [1] 0.7312
# Comparar gráficamente las cuatro relaciones
par(mfrow = c(2, 2))

# Precio vs. área
plot(
  vivienda1$areaconst,
  vivienda1$preciom,
  main = "Precio vs. área",
  xlab = "Área construida (m²)",
  ylab = "Precio (millones)",
  pch = 19
)

# Precio vs. log(área)
plot(
  log(vivienda1$areaconst),
  vivienda1$preciom,
  main = "Precio vs. log(área)",
  xlab = "Logaritmo del área construida",
  ylab = "Precio (millones)",
  pch = 19
)

# log(precio) vs. área
plot(
  vivienda1$areaconst,
  log(vivienda1$preciom),
  main = "log(Precio) vs. área",
  xlab = "Área construida (m²)",
  ylab = "Logaritmo del precio",
  pch = 19
)

# log(precio) vs. log(área)
plot(
  log(vivienda1$areaconst),
  log(vivienda1$preciom),
  main = "log(Precio) vs. log(área)",
  xlab = "Logaritmo del área construida",
  ylab = "Logaritmo del precio",
  pch = 19
)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación:

La comparación de las cuatro formas funcionales muestra diferencias importantes en la relación entre el precio y el área construida:

  • Precio vs. área construida: presenta una correlación de 0,7029, lo que confirma una relación positiva y relativamente fuerte entre ambas variables en su escala original.

  • Precio vs. log(área construida): la correlación disminuye a 0,6672. En este caso, transformar únicamente el área construida no mejora la asociación lineal observada y, por el contrario, la reduce frente a la relación original.

  • log(precio) vs. área construida: la correlación aumenta ligeramente hasta 0,7113. Esto sugiere que la transformación logarítmica del precio permite representar de manera algo más adecuada la relación con el área construida.

  • log(precio) vs. log(área construida): presenta la correlación más alta de las cuatro alternativas, con un valor de 0,7312. Además, visualmente la nube de puntos muestra una relación más próxima a una tendencia lineal y una concentración más homogénea de las observaciones.

Los resultados indican que, para la base correspondiente a la Vivienda 1, la transformación logarítmica de ambas variables ofrece la asociación lineal más fuerte entre precio y área construida. Es importante señalar que la transformación únicamente del área no produjo una mejora, por lo que el comportamiento observado en esta base no coincide necesariamente con el obtenido en otros ejemplos del curso.

La alternativa log(precio) frente a log(área) se considera, por tanto, una especificación relevante para evaluar posteriormente dentro del modelo de regresión múltiple. No obstante, la selección definitiva no debe basarse únicamente en el valor de la correlación. Será necesario comparar el ajuste de los modelos y revisar posteriormente el comportamiento de sus residuos y demás supuestos.

# Comparar las correlaciones bajo diferentes transformaciones

comparacion_cor <- data.frame(
  Variable = c(
    "Parqueaderos",
    "Baños",
    "Habitaciones"
  ),

  `Precio vs. variable` = c(
    cor(vivienda1$preciom, vivienda1$parqueaderos),
    cor(vivienda1$preciom, vivienda1$banios),
    cor(vivienda1$preciom, vivienda1$habitaciones)
  ),

  `Precio vs. log(variable)` = c(
    cor(vivienda1$preciom, log(vivienda1$parqueaderos)),
    cor(vivienda1$preciom, log(vivienda1$banios)),
    cor(vivienda1$preciom, log(vivienda1$habitaciones))
  ),

  `log(Precio) vs. variable` = c(
    cor(log(vivienda1$preciom), vivienda1$parqueaderos),
    cor(log(vivienda1$preciom), vivienda1$banios),
    cor(log(vivienda1$preciom), vivienda1$habitaciones)
  ),

  `log(Precio) vs. log(variable)` = c(
    cor(log(vivienda1$preciom), log(vivienda1$parqueaderos)),
    cor(log(vivienda1$preciom), log(vivienda1$banios)),
    cor(log(vivienda1$preciom), log(vivienda1$habitaciones))
  ),

  check.names = FALSE
)

# Redondear las correlaciones
comparacion_cor[, -1] <- round(
  comparacion_cor[, -1],
  4
)

# Mostrar una tabla compacta
knitr::kable(
  comparacion_cor,
  align = "lcccc",
  caption = "Comparación de correlaciones según transformación"
)
Comparación de correlaciones según transformación
Variable Precio vs. variable Precio vs. log(variable) log(Precio) vs. variable log(Precio) vs. log(variable)
Parqueaderos 0.3217 0.3204 0.3629 0.3643
Baños 0.3933 0.3606 0.4208 0.3937
Habitaciones 0.3910 0.3631 0.3802 0.3694

Interpretación:

La comparación de las diferentes transformaciones muestra que el efecto del logaritmo no es uniforme entre las variables discretas analizadas.

Para parqueaderos, la utilización del logaritmo del precio aumenta la correlación respecto a la escala original, pasando de 0,3217 a 0,3629. La transformación adicional de parqueaderos genera únicamente un incremento marginal, hasta 0,3643, por lo que no se observa una mejora suficiente que justifique transformar esta variable.

En banios, la mayor correlación se obtiene entre el logaritmo del precio y el número de baños en su escala original, con un valor de 0,4208. La transformación logarítmica de baños reduce la correlación, por lo que resulta preferible conservar esta variable sin transformación.

Para habitaciones, la relación más alta corresponde a las variables en su escala original, con una correlación de 0,3910. Al utilizar el logaritmo del precio, la correlación disminuye ligeramente a 0,3802, y la transformación adicional de las habitaciones tampoco representa una mejora.

En conjunto, los resultados no muestran evidencia suficiente para aplicar transformaciones logarítmicas a parqueaderos, banios o habitaciones. Debido además a que estas variables corresponden a conteos discretos con un número limitado de valores posibles, se considera más conveniente conservarlas en su escala original.

Por otra parte, el análisis realizado previamente entre precio y área construida sí mostró una mejora al transformar ambas variables mediante logaritmos. En consecuencia, para la etapa de modelación se considerará como una de las principales especificaciones candidatas el uso de log(precio) como variable respuesta, log(área construida) para representar el área, y las variables discretas en su escala original. La selección definitiva se realizará posteriormente mediante la comparación del ajuste y los supuestos de los modelos.

3.2.4 Visualización interactiva de las relaciones

# Gráfico interactivo: log(precio) vs. log(área construida)
g_area <- plotly::plot_ly(
  data = vivienda1,
  x = ~log(areaconst),
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Área construida:", areaconst, "m²",
    "<br>Precio:", preciom, "millones",
    "<br>Estrato:", estrato,
    "<br>Baños:", banios,
    "<br>Habitaciones:", habitaciones,
    "<br>Parqueaderos:", parqueaderos
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. log(área construida)",
    xaxis = list(title = "Logaritmo del área construida"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) vs. parqueaderos
g_parqueaderos <- plotly::plot_ly(
  data = vivienda1,
  x = ~parqueaderos,
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Parqueaderos:", parqueaderos,
    "<br>Precio:", preciom, "millones",
    "<br>Área construida:", areaconst, "m²",
    "<br>Estrato:", estrato
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. parqueaderos",
    xaxis = list(title = "Número de parqueaderos"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) vs. baños
g_banios <- plotly::plot_ly(
  data = vivienda1,
  x = ~banios,
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Baños:", banios,
    "<br>Precio:", preciom, "millones",
    "<br>Área construida:", areaconst, "m²",
    "<br>Estrato:", estrato
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. baños",
    xaxis = list(title = "Número de baños"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) vs. habitaciones
g_habitaciones <- plotly::plot_ly(
  data = vivienda1,
  x = ~habitaciones,
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Habitaciones:", habitaciones,
    "<br>Precio:", preciom, "millones",
    "<br>Área construida:", areaconst, "m²",
    "<br>Estrato:", estrato
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. habitaciones",
    xaxis = list(title = "Número de habitaciones"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) según estrato
g_estrato <- plotly::plot_ly(
  data = vivienda1,
  x = ~as.factor(estrato),
  y = ~log(preciom),
  type = "box",
  text = ~paste(
    "Estrato:", estrato,
    "<br>Precio:", preciom, "millones"
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) según estrato",
    xaxis = list(title = "Estrato"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Mostrar los gráficos interactivos
g_area
g_parqueaderos
g_banios
g_habitaciones
g_estrato

Interpretación:

Las visualizaciones interactivas se construyen a partir de la transformación del precio mediante logaritmos, debido a que el análisis previo mostró que esta escala ofrece una representación más adecuada de la relación con el área construida. Para esta última variable también se utiliza su transformación logarítmica, mientras que parqueaderos, banios y habitaciones se conservan en su escala original, dado que las transformaciones evaluadas no evidenciaron mejoras suficientes para justificar su modificación.

La relación entre log(precio) y log(área construida) continúa siendo la asociación más clara entre las variables analizadas. En el caso de parqueaderos, baños y habitaciones se mantienen relaciones positivas de menor intensidad y una mayor dispersión de las observaciones. Esta forma de representación es esperable debido a que corresponden a variables discretas, por lo que los puntos se concentran en un número limitado de valores posibles.

Por su parte, la comparación por estrato permite observar el comportamiento del logaritmo del precio entre las viviendas de estrato 4 y 5, manteniendo la diferencia identificada previamente entre ambos grupos.

En conjunto, las visualizaciones interactivas permiten explorar de forma complementaria las relaciones que posteriormente serán consideradas en la construcción del modelo de regresión múltiple.

3.2.5 Matriz de correlación entre variables

# Construir una base con las variables cuantitativas
# que se utilizarán como referencia para la modelación

variables_cor <- data.frame(
  log_precio = log(vivienda1$preciom),
  log_area = log(vivienda1$areaconst),
  parqueaderos = vivienda1$parqueaderos,
  banios = vivienda1$banios,
  habitaciones = vivienda1$habitaciones
)

# Calcular la matriz de correlación
matriz_cor <- cor(
  variables_cor,
  use = "complete.obs"
)

# Mostrar la matriz redondeada
round(matriz_cor, 4)
##              log_precio log_area parqueaderos banios habitaciones
## log_precio       1.0000   0.7312       0.3629 0.4208       0.3802
## log_area         0.7312   1.0000       0.2768 0.3910       0.3949
## parqueaderos     0.3629   0.2768       1.0000 0.3630       0.2954
## banios           0.4208   0.3910       0.3630 1.0000       0.6146
## habitaciones     0.3802   0.3949       0.2954 0.6146       1.0000

Interpretación:

La matriz de correlación permite observar conjuntamente las relaciones lineales entre las variables que se consideran para la etapa de modelación.

  • log_precio y log_area: presentan la correlación más alta de toda la matriz, con un valor de 0,7312. Esto confirma que el área construida, en escala logarítmica, es la variable que muestra la relación lineal más fuerte con el logaritmo del precio.

  • log_precio y banios: presentan una correlación de 0,4208, lo que indica una asociación positiva moderada. En general, un mayor número de baños tiende a estar relacionado con viviendas de mayor precio.

  • log_precio y habitaciones: la correlación es de 0,3802, por lo que existe una relación positiva, aunque de menor intensidad que la observada para baños y área construida.

  • log_precio y parqueaderos: presentan una correlación de 0,3629, siendo la asociación más débil con la variable respuesta entre los predictores cuantitativos considerados.

Al analizar las relaciones entre las propias variables explicativas, se destaca la correlación entre banios y habitaciones, con un valor de 0,6146. Esta asociación es relativamente alta frente a las demás y resulta razonable, ya que las viviendas con mayor número de habitaciones suelen disponer también de un mayor número de baños.

Por su parte, log_area presenta correlaciones moderadas con banios (0,3910) y habitaciones (0,3949), mientras que su relación con parqueaderos es menor (0,2768). Las demás asociaciones entre predictores se mantienen por debajo de 0,40.

En conjunto, la matriz no evidencia correlaciones extremadamente altas entre las variables explicativas. Sin embargo, la relación entre baños y habitaciones deberá observarse posteriormente en el diagnóstico del modelo, dado que ambas variables podrían compartir parte de la información explicativa. La presencia de multicolinealidad no puede determinarse únicamente a partir de esta matriz, por lo que será necesario evaluarla formalmente después de estimar la regresión múltiple.

3.2.6 Distribución geográfica de las ofertas

# Calcular los puntos de corte de los cuartiles del precio
cuartiles_precio <- quantile(
  vivienda1$preciom,
  probs = c(0, 0.25, 0.50, 0.75, 1)
)

# Crear etiquetas con los rangos de precio
etiquetas_precio <- c(
  paste0(
    "Q1: ", round(cuartiles_precio[1]), " - ",
    round(cuartiles_precio[2]), " millones"
  ),
  paste0(
    "Q2: ", round(cuartiles_precio[2]), " - ",
    round(cuartiles_precio[3]), " millones"
  ),
  paste0(
    "Q3: ", round(cuartiles_precio[3]), " - ",
    round(cuartiles_precio[4]), " millones"
  ),
  paste0(
    "Q4: ", round(cuartiles_precio[4]), " - ",
    round(cuartiles_precio[5]), " millones"
  )
)

# Clasificar cada vivienda según el cuartil de precio
vivienda1$grupo_precio <- cut(
  vivienda1$preciom,
  breaks = cuartiles_precio,
  include.lowest = TRUE,
  labels = etiquetas_precio
)

# Crear una paleta de colores para los grupos de precio
paleta_precio <- leaflet::colorFactor(
  palette = "YlOrRd",
  domain = vivienda1$grupo_precio
)

# Crear el mapa interactivo
leaflet::leaflet(
  vivienda1,
  width = "100%",
  height = 380
) |>
  # Utilizar un mapa base más limpio
  leaflet::addProviderTiles(
    leaflet::providers$CartoDB.Positron
  ) |>

  # Agregar las ofertas de vivienda
  leaflet::addCircleMarkers(
    lng = ~longitud,
    lat = ~latitud,
    radius = 3.5,
    color = ~paleta_precio(grupo_precio),
    fillColor = ~paleta_precio(grupo_precio),
    fillOpacity = 0.7,
    stroke = FALSE,

    # Mostrar información de cada vivienda
    popup = ~paste(
      "<b>Precio:</b>", preciom, "millones",
      "<br><b>Grupo:</b>", grupo_precio,
      "<br><b>Área:</b>", areaconst, "m²",
      "<br><b>Estrato:</b>", estrato,
      "<br><b>Baños:</b>", banios,
      "<br><b>Habitaciones:</b>", habitaciones,
      "<br><b>Parqueaderos:</b>", parqueaderos
    )
  ) |>

  # Agregar la leyenda de los cuartiles
  leaflet::addLegend(
    position = "bottomright",
    pal = paleta_precio,
    values = ~grupo_precio,
    title = "Precio por cuartiles",
    opacity = 1
  ) |>

  # Ajustar automáticamente el mapa
  # al rango de coordenadas de las viviendas
  leaflet::fitBounds(
    lng1 = min(vivienda1$longitud),
    lat1 = min(vivienda1$latitud),
    lng2 = max(vivienda1$longitud),
    lat2 = max(vivienda1$latitud)
  )

Interpretación:

La base correspondiente a la Vivienda 1 fue construida utilizando únicamente los registros clasificados como Zona Norte. Sin embargo, al representar las coordenadas geográficas se identifican varias observaciones cuya ubicación espacial no resulta coherente con esta clasificación, ya que algunos puntos aparecen localizados en sectores centrales e incluso del sur de Cali.

Este hallazgo evidencia posibles errores en las variables de georreferenciación, específicamente en los valores de latitud y longitud de algunos registros. Por tanto, aunque la variable categórica zona clasifica estas viviendas como pertenecientes a la Zona Norte, no todas las coordenadas permiten confirmar espacialmente dicha ubicación.

La mayor parte de las observaciones sí presenta una concentración geográfica consistente con el norte de la ciudad, por lo que el problema parece corresponder a un conjunto particular de registros y no a la totalidad del subconjunto.

En cuanto al precio, los cuatro cuartiles se encuentran representados dentro del núcleo principal de viviendas y no se observa una separación espacial absoluta entre los diferentes niveles de valor.

En consecuencia, el mapa no solo permite describir la distribución territorial de las ofertas, sino también identificar inconsistencias de georreferenciación que deben considerarse al interpretar cualquier análisis espacial posterior.

3.3 Modelo de regresión lineal múltiple

# Crear una copia de la base para la etapa de modelación
modelo_vivienda1 <- vivienda1

# Convertir el estrato en variable categórica
modelo_vivienda1$estrato <- as.factor(
  modelo_vivienda1$estrato
)

# Verificar la estructura de la variable
str(modelo_vivienda1$estrato)
##  Factor w/ 2 levels "4","5": 2 2 1 2 1 2 2 1 2 2 ...
# Revisar las categorías disponibles
levels(modelo_vivienda1$estrato)
## [1] "4" "5"

Interpretación:

La base destinada a la etapa de modelación conserva las observaciones correspondientes a la Vivienda 1 y prepara la variable estrato para su inclusión adecuada en la regresión lineal múltiple.

La conversión de estrato a tipo factor confirma que la variable será tratada como categórica y no como una magnitud numérica continua. Se identifican dos niveles, correspondientes a los estratos 4 y 5.

Dado que el estrato 4 aparece como el primer nivel del factor, este será utilizado por R como categoría de referencia. En consecuencia, el coeficiente asociado al estrato 5 en el modelo representará la diferencia esperada en el precio respecto a una vivienda de estrato 4, manteniendo constantes las demás características incluidas en la regresión.

3.3.1 Modelo 1: variables en escala original

El Modelo 1 se establece como modelo de referencia utilizando el precio y el área construida en su escala original. Esta especificación permite contar con una base de comparación antes de evaluar la transformación logarítmica identificada durante el análisis exploratorio.

# Estimar el Modelo 1 de regresión lineal múltiple
# utilizando las variables en su escala original

modelo1 <- lm(
  preciom ~
    areaconst +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda1
)

# Mostrar el resumen del Modelo 1
summary(modelo1)
## 
## Call:
## lm(formula = preciom ~ areaconst + parqueaderos + banios + habitaciones + 
##     estrato, data = modelo_vivienda1)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -680.2  -77.6  -14.6   49.6  925.5 
## 
## Coefficients:
##              Estimate Std. Error t value            Pr(>|t|)    
## (Intercept)   58.7325    34.7891    1.69              0.0923 .  
## areaconst      0.8316     0.0618   13.46 <0.0000000000000002 ***
## parqueaderos  18.0413     6.8828    2.62              0.0092 ** 
## banios        10.7720     9.5430    1.13              0.2598    
## habitaciones  14.5779     7.3577    1.98              0.0484 *  
## estrato5      59.3206    19.3151    3.07              0.0023 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 156 on 317 degrees of freedom
## Multiple R-squared:  0.54,   Adjusted R-squared:  0.532 
## F-statistic: 74.3 on 5 and 317 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 1:

En este primer modelo, el precio de la vivienda se explica a partir del área construida, el número de parqueaderos, baños y habitaciones, y el estrato socioeconómico, manteniendo todas las variables en su escala original. Para interpretar los coeficientes se considera que, manteniendo constantes las demás características de la vivienda, cada estimación representa el cambio esperado en el precio, expresado en millones de pesos, ante una variación de una unidad en la variable correspondiente. Para evaluar la significancia estadística se utiliza como referencia un nivel del 5 % (\(p<0,05\)).

  • Área construida: presenta un coeficiente de 0,8316 y un valor \(p<0,001\), por lo que su relación con el precio es positiva y estadísticamente significativa. Manteniendo constantes las demás variables, un metro cuadrado adicional de área construida se asocia, en promedio, con un incremento aproximado de 0,83 millones de pesos en el precio de la vivienda.

  • Parqueaderos: el coeficiente estimado es de 18,0413 y su valor \(p=0,0092\). Por tanto, existe evidencia de una asociación positiva y significativa. Un parqueadero adicional se relaciona con un incremento aproximado de 18,04 millones de pesos en el precio, manteniendo constantes las demás características.

  • Baños: presenta un coeficiente positivo de 10,7720, pero su valor \(p=0,2598\) es superior a 0,05. En consecuencia, aunque el modelo estima un aumento del precio asociado con un baño adicional, no existe evidencia estadística suficiente para afirmar que este efecto sea diferente de cero una vez se controlan las demás variables.

  • Habitaciones: presenta un coeficiente de 14,5779 y un valor \(p=0,0484\). El efecto resulta estadísticamente significativo al nivel del 5 %, aunque se encuentra muy próximo al límite de significancia. Manteniendo constantes las demás características, una habitación adicional se relaciona con un incremento aproximado de 14,58 millones de pesos.

  • Estrato: al tratarse como una variable categórica, el estrato 4 constituye la categoría de referencia. El coeficiente de estrato5 es 59,3206, con un valor \(p=0,0023\), indicando que una vivienda de estrato 5 presenta, en promedio, un precio aproximadamente 59,32 millones de pesos superior al de una vivienda de estrato 4 con características equivalentes en las demás variables.

El intercepto presenta un valor estimado de 58,73 millones de pesos y no resulta estadísticamente significativo (\(p=0,0923\)). Además, su interpretación práctica es limitada, ya que corresponde al precio esperado cuando las variables cuantitativas toman el valor cero, situación que no representa una vivienda real dentro del contexto analizado.

En cuanto al ajuste general, el modelo presenta un \(R^2=0,540\), lo que significa que aproximadamente el 54,0 % de la variabilidad observada en el precio es explicada conjuntamente por las variables incorporadas. El \(R^2\) ajustado es de 0,532, valor cercano al anterior, lo cual indica que el nivel de explicación se mantiene después de considerar el número de variables incluidas.

El error estándar residual es de aproximadamente 156 millones de pesos, reflejando la magnitud típica de las diferencias entre los precios observados y los estimados por el modelo. Finalmente, la prueba F global presenta un valor de 74,3 con un \(p<0,001\), por lo que se concluye que el modelo es estadísticamente significativo en su conjunto; es decir, al menos una de las variables explicativas aporta información relevante para explicar el precio de las viviendas.

Estos resultados describen el ajuste del Modelo 1, pero todavía no permiten determinar si es el modelo más adecuado. Para ello es necesario evaluar el comportamiento de sus residuos y verificar los supuestos de regresión antes de compararlo con el modelo que incorpora las transformaciones logarítmicas.

# Revisar los gráficos básicos de diagnóstico
# del Modelo 1

par(mfrow = c(2, 2))

plot(modelo1)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 1:

Los gráficos de diagnóstico permiten realizar una primera evaluación del comportamiento de los residuos antes de aplicar las pruebas formales. Cada gráfico analiza un aspecto diferente del modelo.

  • Residuos frente a valores ajustados: idealmente, los residuos deberían distribuirse aleatoriamente alrededor de cero y mantener una dispersión relativamente constante. En este caso se observa una mayor concentración de residuos para valores ajustados bajos y medios, mientras que la dispersión aumenta a medida que crecen los valores predichos. También aparecen algunas observaciones alejadas del patrón general, como las identificadas alrededor de 175, 227 y 49. Esto sugiere posibles problemas de heterocedasticidad y la presencia de algunos casos atípicos.

  • Gráfico Q-Q de los residuos: si los residuos siguieran aproximadamente una distribución normal, los puntos deberían ubicarse cerca de la línea de referencia. En la parte central existe cierta aproximación a la línea, pero se presentan desviaciones importantes en ambos extremos, especialmente en la cola superior. Por tanto, el gráfico proporciona indicios de que la normalidad de los residuos no se cumple adecuadamente.

  • Scale-Location: este gráfico permite evaluar nuevamente la constancia de la varianza. Una línea aproximadamente horizontal indicaría una dispersión homogénea de los residuos. En el Modelo 1, la línea presenta una tendencia claramente creciente, mostrando que la variabilidad de los residuos aumenta conforme aumenta el precio estimado. Este comportamiento constituye una señal gráfica importante de varianza no constante.

  • Residuos frente a leverage: la mayoría de las observaciones presenta niveles bajos de leverage; sin embargo, algunos registros se encuentran más alejados del conjunto principal. En particular, aparecen observaciones con leverage relativamente alto, como las identificadas alrededor de 227, 278 y 49. Algunas de ellas se aproximan a las curvas de referencia de la distancia de Cook, por lo que podrían ejercer una influencia mayor sobre la estimación del modelo.

En conjunto, el diagnóstico gráfico sugiere que el Modelo 1 en escala original presenta principalmente problemas relacionados con la normalidad de los residuos y la homogeneidad de la varianza, además de algunas observaciones potencialmente influyentes. Estos resultados deben confirmarse mediante las pruebas formales de Shapiro-Wilk, Breusch-Pagan y Durbin-Watson antes de establecer conclusiones definitivas sobre el cumplimiento de los supuestos.

Pruebas formales de supuestos del Modelo 1:

# Prueba de normalidad de los residuos
shapiro.test(
  residuals(modelo1)
)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo1)
## W = 0.87, p-value = 0.0000000000000006
# Prueba de homocedasticidad
lmtest::bptest(
  modelo1
)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo1
## BP = 47, df = 5, p-value = 0.000000006
# Prueba de independencia de los errores
lmtest::dwtest(
  modelo1
)
## 
##  Durbin-Watson test
## 
## data:  modelo1
## DW = 1.8, p-value = 0.02
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 1:

Las pruebas formales permiten complementar el diagnóstico gráfico de los residuos. En cada caso se utiliza un nivel de significancia del 5 %. Cuando el valor \(p<0,05\), se rechaza la hipótesis nula de la prueba.

  • Prueba de Shapiro-Wilk: esta prueba evalúa la normalidad de los residuos. La hipótesis nula establece que los residuos siguen una distribución normal. Para el Modelo 1 se obtiene \(W=0,87\) y un valor \(p<0,001\). Por tanto, se rechaza la hipótesis de normalidad. Este resultado confirma lo observado en el gráfico Q-Q, donde se evidenciaron desviaciones importantes, especialmente en las colas de la distribución.

  • Prueba de Breusch-Pagan: permite evaluar si la varianza de los residuos permanece constante. La hipótesis nula establece que existe homocedasticidad. El resultado obtenido es \(BP=47\), con un valor \(p<0,001\), por lo que se rechaza la hipótesis nula. En consecuencia, existe evidencia estadística de heterocedasticidad, confirmando la tendencia creciente observada previamente en el gráfico Scale-Location.

  • Prueba de Durbin-Watson: evalúa la presencia de autocorrelación en los residuos. Bajo la hipótesis nula no existe autocorrelación. El Modelo 1 presenta un estadístico \(DW=1,8\) y un valor \(p=0,02\). Al ser inferior a 0,05, se rechaza la hipótesis nula y se encuentra evidencia de autocorrelación positiva de los residuos según el orden de las observaciones. No obstante, al tratarse de datos de viviendas de corte transversal y no de una serie temporal, este resultado debe interpretarse con cautela, puesto que el orden de los registros no necesariamente representa una secuencia con significado estadístico.

En conjunto, las pruebas formales confirman que el Modelo 1 presenta incumplimientos importantes de los supuestos de normalidad y homocedasticidad. Adicionalmente, la prueba de Durbin-Watson señala una posible dependencia entre residuos. Estos resultados respaldan la necesidad de comparar este modelo en escala original con una especificación alternativa, como el modelo con transformaciones logarítmicas planteado a partir del análisis exploratorio.

Evaluación de la multicolinealidad del Modelo 1:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF)

car::vif(modelo1)
##    areaconst parqueaderos       banios habitaciones      estrato 
##        1.319        1.183        1.769        1.693        1.058

Interpretación de la multicolinealidad del Modelo 1:

El Factor de Inflación de la Varianza (VIF) permite evaluar si existe una relación lineal elevada entre las variables explicativas del modelo. En términos generales, valores cercanos a 1 indican una baja relación entre predictores, mientras que valores superiores a 5 suelen considerarse una señal de posible multicolinealidad y valores mayores a 10 representarían un problema más serio.

Para el Modelo 1, los valores obtenidos son bajos: área construida = 1,319, parqueaderos = 1,183, baños = 1,769, habitaciones = 1,693 y estrato = 1,058.

Todos los valores se encuentran claramente por debajo del umbral de 5, por lo que no se evidencia un problema importante de multicolinealidad entre las variables explicativas incluidas en el modelo.

Los valores más altos corresponden a baños y habitaciones, lo cual es consistente con la relación moderada que ya se había observado entre ambas variables durante el análisis exploratorio. Sin embargo, esa relación no alcanza un nivel que comprometa de manera importante la estabilidad de las estimaciones.

En consecuencia, la multicolinealidad no parece explicar los problemas detectados previamente en el Modelo 1. Las principales dificultades continúan asociadas con la normalidad de los residuos y la heterocedasticidad, más que con una alta dependencia entre las variables explicativas.

Análisis de observaciones influyentes del Modelo 1:

# Calcular la distancia de Cook para cada observación
# del Modelo 1

dist_cook_m1 <- cooks.distance(modelo1)

# Graficar las distancias de Cook
plot(
  dist_cook_m1,
  type = "h",
  main = "Distancia de Cook - Modelo 1",
  xlab = "Observación",
  ylab = "Distancia de Cook"
)

# Agregar una línea de referencia con el criterio 4/n
abline(
  h = 4 / nrow(modelo_vivienda1),
  lty = 2
)

# Mostrar las 10 observaciones con mayor distancia de Cook
head(
  sort(dist_cook_m1, decreasing = TRUE),
  10
)
##      49     227     278     221     151     175     263      74     284     203 
## 0.40011 0.35306 0.15520 0.09134 0.07396 0.05185 0.04906 0.02880 0.02827 0.02353

Interpretación de las observaciones influyentes del Modelo 1:

La distancia de Cook permite identificar observaciones que pueden ejercer una influencia importante sobre los coeficientes estimados del modelo. Como criterio de referencia se utiliza \(4/n\), que para las 323 observaciones analizadas corresponde aproximadamente a 0,0124. Las observaciones que superan este valor deben ser examinadas, aunque esto no implica que deban eliminarse automáticamente.

En el Modelo 1 se observan varios registros por encima del umbral. Los casos más destacados son las observaciones 49 y 227, con distancias de Cook de 0,4001 y 0,3531, respectivamente. Estos valores son considerablemente superiores al resto y muestran que ambas observaciones tienen un efecto importante sobre la estimación del modelo.

También presentan valores relevantes las observaciones 278 (0,1552), 221 (0,0913), 151 (0,0740) y 175 (0,0519). En menor magnitud, aunque todavía por encima del criterio de referencia, aparecen las observaciones 263, 74, 284 y 203, entre otras.

La revisión realizada previamente de las características de algunas de estas viviendas ayuda a comprender este comportamiento. Por ejemplo, la observación 49 corresponde a una vivienda con un área construida de 1.188 m², claramente superior a la mayor parte de la muestra, mientras que la observación 227 presenta un precio de 1.940 millones de pesos, 734 m² de área, 8 baños y 10 habitaciones. De manera similar, varias de las observaciones identificadas corresponden a viviendas con precios o áreas considerablemente superiores al comportamiento central de la base.

Por tanto, los valores elevados de Cook parecen estar asociados principalmente con viviendas reales pero extremas dentro del mercado analizado, y no necesariamente con errores de registro. En consecuencia, no existe justificación para eliminarlas automáticamente.

Sin embargo, el hecho de que algunas observaciones alcancen distancias de Cook cercanas a 0,4 evidencia que el Modelo 1 en escala original es relativamente sensible a determinados registros extremos. Este resultado, junto con los problemas de normalidad y heterocedasticidad identificados anteriormente, constituye un argumento adicional para evaluar una especificación alternativa mediante transformaciones logarítmicas y posteriormente comparar el comportamiento de ambos modelos.

Revisión de las observaciones que superan el umbral de Cook:

# Definir el umbral de referencia para la distancia de Cook
umbral_cook_m1 <- 4 / nrow(modelo_vivienda1)

# Identificar todas las observaciones que superan el umbral
obs_influyentes_m1 <- which(
  dist_cook_m1 > umbral_cook_m1
)

# Construir una tabla compacta con las observaciones influyentes
revision_influyentes_m1 <- data.frame(
  Observacion = obs_influyentes_m1,
  Precio = modelo_vivienda1$preciom[obs_influyentes_m1],
  Area = modelo_vivienda1$areaconst[obs_influyentes_m1],
  Parqueaderos = modelo_vivienda1$parqueaderos[obs_influyentes_m1],
  Banios = modelo_vivienda1$banios[obs_influyentes_m1],
  Habitaciones = modelo_vivienda1$habitaciones[obs_influyentes_m1],
  Estrato = modelo_vivienda1$estrato[obs_influyentes_m1],
  Distancia_Cook = round(
    dist_cook_m1[obs_influyentes_m1],
    5
  )
)

# Ordenar de mayor a menor influencia
revision_influyentes_m1 <- revision_influyentes_m1[
  order(
    revision_influyentes_m1$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla
knitr::kable(
  revision_influyentes_m1,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 1"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 1
Observacion Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
49 49 650 1188.0 4 6 6 5 0.4001
227 227 1940 734.0 3 8 10 5 0.3531
278 278 1600 942.0 4 4 10 5 0.1552
221 221 1530 776.0 6 6 10 5 0.0913
151 151 1400 838.0 1 5 5 5 0.0740
175 175 1500 400.0 2 3 4 5 0.0518
263 263 800 900.0 6 5 4 5 0.0491
74 74 990 290.0 4 3 3 5 0.0288
284 284 1200 523.3 2 4 7 5 0.0283
203 203 650 765.0 2 6 5 5 0.0235
242 242 850 296.0 4 2 4 5 0.0196
273 273 360 389.0 2 6 9 4 0.0168
43 43 680 780.0 2 5 5 5 0.0163
79 79 950 450.0 8 5 5 5 0.0163
238 238 1000 350.0 2 3 3 5 0.0163
10 10 870 292.0 2 5 8 5 0.0157
310 310 830 292.0 4 6 8 4 0.0150
247 247 800 800.0 3 7 7 5 0.0138
288 288 1200 730.0 4 6 6 5 0.0127

Interpretación de las observaciones influyentes del Modelo 1:

La tabla identifica 19 observaciones que superan el umbral de referencia \(4/n \approx 0,0124\) para la distancia de Cook. Estas observaciones tienen un potencial de influencia mayor sobre los coeficientes estimados del modelo y, por tanto, deben revisarse antes de considerar cualquier modificación de la base.

Los casos más relevantes corresponden a las observaciones 49, 227 y 278, con distancias de Cook de 0,4001, 0,3531 y 0,1552, respectivamente. Estos valores se encuentran claramente por encima del resto y muestran que el Modelo 1 en escala original es especialmente sensible a estas viviendas.

  • La observación 49 presenta un área construida de 1.188 m², considerablemente superior al comportamiento central de la muestra, pero un precio de 650 millones de pesos. Esta combinación entre una superficie excepcionalmente grande y un precio relativamente moderado puede generar una desviación importante respecto a la relación lineal estimada.
  • La observación 227 corresponde a una vivienda con un precio de 1.940 millones de pesos, 734 m² de área, 8 baños y 10 habitaciones, por lo que reúne varias características extremas dentro del conjunto analizado.
  • La observación 278 presenta un precio de 1.600 millones de pesos, un área de 942 m² y 10 habitaciones, constituyendo también una vivienda claramente alejada del comportamiento típico de la muestra.

Otras observaciones como la 221, 151 y 175 presentan distancias de Cook entre aproximadamente 0,05 y 0,09 y están asociadas principalmente con viviendas de precios y áreas elevados. También aparecen casos como las observaciones 263, 203, 43, 247 y 288, caracterizadas por áreas considerablemente grandes, así como otros registros con combinaciones poco frecuentes de baños, habitaciones o parqueaderos.

En términos generales, la revisión no evidencia errores manifiestos de digitación o valores imposibles. Las observaciones identificadas parecen corresponder principalmente a viviendas plausibles, pero con características extremas o poco frecuentes dentro del subconjunto analizado. Por esta razón, no se justifica su eliminación automática.

Sin embargo, la presencia de varios registros con distancias de Cook elevadas, especialmente los casos 49 y 227, evidencia que el Modelo 1 en escala original puede verse afectado de manera importante por viviendas extremas. Este resultado se suma a los problemas de normalidad y heterocedasticidad previamente identificados y constituye una razón adicional para comparar este modelo con una especificación que reduzca el efecto de los valores extremos, como el Modelo 2 con transformación logarítmica.

3.3.2 Modelo 2: transformación logarítmica del precio y del área construida

El Modelo 1 permitió establecer una primera relación entre el precio y las características de las viviendas utilizando las variables en su escala original. Aunque el modelo resultó globalmente significativo, la validación de sus supuestos evidenció problemas importantes de normalidad y homocedasticidad de los residuos. Adicionalmente, algunas observaciones presentaron una influencia considerable sobre la estimación, alcanzando distancias de Cook de 0,4001 y 0,3531.

Estos resultados son consistentes con lo observado previamente durante el análisis exploratorio, donde la relación entre precio y área construida presentaba una dispersión creciente para viviendas de mayor tamaño. En dicho análisis, la transformación log(precio) frente a log(área) mostró una relación más lineal y homogénea que las demás alternativas evaluadas.

Por esta razón, se plantea un segundo modelo utilizando transformaciones logarítmicas para el precio y el área construida, manteniendo las demás variables en su escala original. El objetivo es evaluar si esta especificación representa de manera más adecuada la relación entre las variables y reduce algunos de los problemas identificados en el Modelo 1.

# Estimar el Modelo 2 de regresión lineal múltiple
# utilizando transformación logarítmica del precio
# y del área construida

modelo2 <- lm(
  log(preciom) ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda1
)

# Mostrar el resumen del Modelo 2
summary(modelo2)
## 
## Call:
## lm(formula = log(preciom) ~ log(areaconst) + parqueaderos + banios + 
##     habitaciones + estrato, data = modelo_vivienda1)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.5716 -0.1548 -0.0093  0.1347  0.9942 
## 
## Coefficients:
##                Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)      3.2126     0.1583   20.30 < 0.0000000000000002 ***
## log(areaconst)   0.4648     0.0318   14.61 < 0.0000000000000002 ***
## parqueaderos     0.0368     0.0106    3.46              0.00062 ***
## banios           0.0340     0.0147    2.32              0.02110 *  
## habitaciones     0.0086     0.0114    0.75              0.45106    
## estrato5         0.1113     0.0299    3.72              0.00024 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.241 on 317 degrees of freedom
## Multiple R-squared:  0.591,  Adjusted R-squared:  0.585 
## F-statistic: 91.7 on 5 and 317 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 2:

El Modelo 2 mantiene las mismas variables explicativas del Modelo 1, pero incorpora una transformación logarítmica tanto en el precio como en el área construida. Debido a esta transformación, la interpretación de algunos coeficientes cambia respecto al modelo anterior.

Para evaluar la significancia estadística se mantiene como referencia un nivel del 5 % (\(p<0,05\)).

  • Área construida: log(areaconst) presenta un coeficiente de 0,4648 y un valor p inferior a 0,001, por lo que continúa siendo una variable altamente significativa. Debido a que tanto el precio como el área se encuentran expresados en logaritmos, el coeficiente se interpreta como una elasticidad: manteniendo constantes las demás características, un incremento del 1 % en el área construida se asocia aproximadamente con un aumento del 0,465 % en el precio esperado.

  • Parqueaderos: presenta un coeficiente de 0,0368 y un valor p de 0,00062, por lo que mantiene una asociación positiva y estadísticamente significativa con el precio. Un parqueadero adicional se relaciona aproximadamente con un incremento del 3,7 % en el precio esperado, manteniendo constantes las demás variables.

  • Baños: el coeficiente estimado es de 0,0340, con un valor p de 0,0211. En esta especificación la variable resulta estadísticamente significativa, a diferencia de lo observado en el Modelo 1. Manteniendo constantes las demás características, un baño adicional se asocia aproximadamente con un aumento del 3,5 % en el precio esperado.

  • Habitaciones: presenta un coeficiente de 0,0086 y un valor p de 0,4511, por lo que no resulta estadísticamente significativa en el Modelo 2. Este comportamiento contrasta con el Modelo 1, donde la variable se encontraba apenas por debajo del nivel de significancia del 5 %. El cambio evidencia que el aporte de esta variable es sensible a la forma funcional utilizada y que, una vez considerada la relación logarítmica entre precio y área, el número de habitaciones aporta poca información adicional para explicar el precio.

  • Estrato: estrato5 presenta un coeficiente de 0,1113 y un valor p de 0,00024, manteniéndose como una variable estadísticamente significativa. Tomando el estrato 4 como categoría de referencia, una vivienda de estrato 5 presenta un precio esperado aproximadamente 11,8 % superior, manteniendo constantes las demás características.

El Modelo 2 presenta un \(R^2=0,591\) y un \(R^2\) ajustado de 0,585, indicando que aproximadamente el 59,1 % de la variabilidad del logaritmo del precio es explicada por las variables incorporadas. Debido a que la variable respuesta se encuentra en una escala diferente a la utilizada en el Modelo 1, estos valores no deben compararse directamente como único criterio para seleccionar entre ambos modelos.

La prueba F global alcanza un valor de 91,7, con un valor p inferior a 0,001, por lo que el Modelo 2 resulta estadísticamente significativo en su conjunto.

En términos de los coeficientes, el área construida, los parqueaderos y el estrato mantienen asociaciones significativas en ambas especificaciones. En cambio, baños y habitaciones presentan cambios en su significancia estadística, lo que evidencia la importancia de evaluar la forma funcional del modelo.

Por tanto, la selección entre ambos modelos no debe realizarse únicamente a partir de la significancia de los coeficientes o del \(R^2\), sino también considerando el comportamiento de los residuos y el cumplimiento de los supuestos de regresión.

Validación gráfica de los supuestos del Modelo 2:

# Revisar los gráficos básicos de diagnóstico
# del Modelo 2

par(mfrow = c(2, 2))

plot(modelo2)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 2:

Los gráficos de diagnóstico muestran un comportamiento más regular de los residuos que el observado en el Modelo 1, aunque todavía se presentan algunas desviaciones.

  • Residuos frente a valores ajustados: los residuos se encuentran distribuidos alrededor de cero y la dispersión creciente observada en el Modelo 1 se reduce de manera apreciable. Sin embargo, todavía se perciben algunas variaciones hacia los valores ajustados más altos, por lo que no puede concluirse únicamente de manera gráfica que la varianza sea completamente constante.

  • Gráfico Q-Q de los residuos: se observa una mejora importante respecto al Modelo 1. La mayor parte de los residuos se aproxima a la línea de referencia, especialmente en la zona central. No obstante, persisten desviaciones en las colas, particularmente en la parte superior, indicando que la transformación mejora la aproximación a la normalidad pero no elimina completamente el problema.

  • Scale-Location: continúa observándose una ligera tendencia creciente, aunque menos pronunciada que en el Modelo 1. Esto sugiere que la transformación logarítmica reduce la heterogeneidad de la varianza, pero todavía podría existir cierto grado de heterocedasticidad.

  • Residuos frente a leverage: continúan apareciendo algunas observaciones potencialmente influyentes. Sin embargo, visualmente su efecto parece menos marcado que en el Modelo 1, aspecto que debe comprobarse mediante la distancia de Cook.

En conjunto, los gráficos sugieren que la transformación logarítmica produce una mejora en el comportamiento de los residuos, especialmente frente a los problemas observados en la escala original. Sin embargo, las mejoras deben confirmarse mediante las pruebas formales de diagnóstico.

Pruebas formales de supuestos del Modelo 2:

# Prueba de normalidad de los residuos
shapiro.test(
  residuals(modelo2)
)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo2)
## W = 0.98, p-value = 0.001
# Prueba de homocedasticidad
lmtest::bptest(
  modelo2
)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo2
## BP = 19, df = 5, p-value = 0.002
# Prueba de independencia de los errores
lmtest::dwtest(
  modelo2
)
## 
##  Durbin-Watson test
## 
## data:  modelo2
## DW = 1.7, p-value = 0.001
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 2:

Las pruebas formales permiten evaluar si las mejoras observadas gráficamente son suficientes para considerar cumplidos los supuestos del modelo. Se utiliza un nivel de significancia del 5 %.

  • Prueba de Shapiro-Wilk: la hipótesis nula establece que los residuos siguen una distribución normal. Se obtiene un estadístico \(W=0,98\) y un valor p de 0,001. Por tanto, se mantiene evidencia estadística para rechazar la normalidad de los residuos. Sin embargo, el estadístico se encuentra considerablemente más próximo a 1 que el obtenido en el Modelo 1 (\(W=0,87\)), lo que evidencia una mejora importante en la aproximación a la normalidad, aunque el supuesto no se cumple completamente.

  • Prueba de Breusch-Pagan: la hipótesis nula establece que la varianza de los residuos es constante. El Modelo 2 presenta un estadístico \(BP=19\), con un valor p de 0,002, por lo que todavía existe evidencia de heterocedasticidad. No obstante, el estadístico disminuye de manera importante frente al Modelo 1, donde se obtuvo \(BP=47\). Este resultado es consistente con los gráficos de diagnóstico y muestra que la transformación reduce el problema de varianza no constante, aunque no lo elimina por completo.

  • Prueba de Durbin-Watson: bajo la hipótesis nula no existe autocorrelación en los residuos. Para el Modelo 2 se obtiene un estadístico \(DW=1,7\) y un valor p de 0,001, por lo que se encuentra evidencia de autocorrelación positiva según el orden de las observaciones. En este aspecto no se observa una mejora frente al Modelo 1. No obstante, al tratarse de información de corte transversal sobre viviendas y no de una serie temporal, este resultado debe interpretarse con cautela, dado que el orden de los registros no necesariamente representa una secuencia con significado estadístico.

En síntesis, el Modelo 2 no logra satisfacer completamente todos los supuestos de regresión, pero muestra una mejora clara respecto al Modelo 1 en dos aspectos relevantes: la distribución de los residuos se aproxima más a la normalidad y la heterocedasticidad disminuye considerablemente. Por tanto, la transformación logarítmica parece representar de mejor manera la estructura de los datos, aunque todavía es necesario evaluar la influencia de observaciones particulares antes de seleccionar una especificación definitiva.

Evaluación de la multicolinealidad del Modelo 2:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF)

car::vif(modelo2)
## log(areaconst)   parqueaderos         banios   habitaciones        estrato 
##          1.336          1.188          1.757          1.706          1.066

Interpretación de la multicolinealidad del Modelo 2:

Los valores VIF obtenidos se encuentran entre 1,066 y 1,757, todos claramente por debajo de los niveles que indicarían un problema importante de multicolinealidad.

Frente al Modelo 1, los valores permanecen prácticamente estables: el VIF máximo pasa de aproximadamente 1,769 a 1,757. Por tanto, la transformación logarítmica del precio y del área no deteriora el comportamiento de las variables explicativas ni introduce problemas adicionales de multicolinealidad.

Los valores más altos continúan correspondiendo a baños y habitaciones, coherentemente con la asociación observada entre ambas variables durante el análisis exploratorio. Sin embargo, sus magnitudes siguen siendo bajas y no comprometen la estabilidad de las estimaciones.

En consecuencia, este aspecto del Modelo 2 se mantiene adecuadamente respecto al Modelo 1. Además, la falta de significancia de habitaciones en el Modelo 2 no parece explicarse por una inflación severa de la varianza asociada con multicolinealidad, sino por el menor aporte adicional de esta variable una vez consideradas las demás características de la vivienda.

Análisis de observaciones influyentes del Modelo 2:

# Calcular la distancia de Cook para cada observación
dist_cook_m2 <- cooks.distance(modelo2)

# Graficar las distancias de Cook
plot(
  dist_cook_m2,
  type = "h",
  main = "Distancia de Cook - Modelo 2",
  xlab = "Observación",
  ylab = "Distancia de Cook"
)

# Agregar una línea de referencia
abline(
  h = 4 / nrow(modelo_vivienda1),
  lty = 2
)

# Identificar las observaciones con mayor distancia de Cook
head(
  sort(dist_cook_m2, decreasing = TRUE),
  10
)
##     227     278      49     175     221     151      74     273     242     284 
## 0.08161 0.05940 0.03122 0.02937 0.02764 0.02754 0.02321 0.02247 0.02077 0.01862

Interpretación de las observaciones influyentes del Modelo 2:

La distancia de Cook evidencia una reducción importante de la influencia ejercida por las observaciones extremas después de incorporar las transformaciones logarítmicas.

En el Modelo 1, las mayores distancias de Cook correspondieron a las observaciones 49, 227 y 278, con valores de 0,4001, 0,3531 y 0,1552, respectivamente. En el Modelo 2, las mayores distancias corresponden a las observaciones 227 y 278, con valores de 0,0816 y 0,0594, mientras que la observación 49 disminuye hasta aproximadamente 0,0312.

La reducción es especialmente importante para la observación 49, correspondiente a una vivienda de 1.188 m² de área construida. En el modelo en escala original este registro ejercía la mayor influencia sobre la estimación, mientras que al utilizar la transformación logarítmica su efecto disminuye considerablemente. Esto resulta coherente con el propósito de la transformación, pues comprime las diferencias entre valores muy grandes y el resto de la distribución.

Aunque continúan existiendo observaciones que superan el umbral \(4/n \approx 0,0124\), sus distancias de Cook presentan magnitudes considerablemente menores que en el Modelo 1. Por tanto, el Modelo 2 resulta menos sensible a las viviendas con características extremas.

La revisión de estas observaciones tampoco evidencia errores manifiestos de registro, por lo que no existe fundamento para eliminarlas automáticamente. Los casos identificados parecen corresponder principalmente a viviendas reales con características poco frecuentes dentro del mercado analizado.

En conjunto, este resultado constituye una evidencia adicional de que la transformación logarítmica mejora la estabilidad del modelo frente a los valores extremos, aunque todavía permanecen algunos casos que requieren atención.

Revisión de las observaciones que superan el umbral de Cook:

# Definir el umbral de referencia para la distancia de Cook
umbral_cook_m2 <- 4 / nrow(modelo_vivienda1)

# Identificar las observaciones que superan el umbral
obs_influyentes_m2 <- which(
  dist_cook_m2 > umbral_cook_m2
)

# Construir una tabla compacta con las observaciones influyentes
revision_influyentes_m2 <- data.frame(
  Observacion = obs_influyentes_m2,
  Precio = modelo_vivienda1$preciom[obs_influyentes_m2],
  Area = modelo_vivienda1$areaconst[obs_influyentes_m2],
  Parqueaderos = modelo_vivienda1$parqueaderos[obs_influyentes_m2],
  Banios = modelo_vivienda1$banios[obs_influyentes_m2],
  Habitaciones = modelo_vivienda1$habitaciones[obs_influyentes_m2],
  Estrato = modelo_vivienda1$estrato[obs_influyentes_m2],
  Distancia_Cook = round(
    dist_cook_m2[obs_influyentes_m2],
    5
  )
)

# Ordenar de mayor a menor influencia
revision_influyentes_m2 <- revision_influyentes_m2[
  order(
    revision_influyentes_m2$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla
knitr::kable(
  revision_influyentes_m2,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 2"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 2
Observacion Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
227 227 1940 734.0 3 8 10 5 0.0816
278 278 1600 942.0 4 4 10 5 0.0594
49 49 650 1188.0 4 6 6 5 0.0312
175 175 1500 400.0 2 3 4 5 0.0294
221 221 1530 776.0 6 6 10 5 0.0276
151 151 1400 838.0 1 5 5 5 0.0275
74 74 990 290.0 4 3 3 5 0.0232
273 273 360 389.0 2 6 9 4 0.0225
242 242 850 296.0 4 2 4 5 0.0208
284 284 1200 523.3 2 4 7 5 0.0186
213 213 340 355.0 2 5 8 5 0.0182
214 214 750 250.0 3 6 8 4 0.0166
10 10 870 292.0 2 5 8 5 0.0165
5 5 600 160.0 1 4 5 4 0.0162
310 310 830 292.0 4 6 8 4 0.0160
238 238 1000 350.0 2 3 3 5 0.0148
204 204 380 450.0 2 6 7 4 0.0144
289 289 680 176.9 3 6 6 5 0.0132
156 156 230 250.0 2 3 5 4 0.0126

Interpretación de la revisión de las observaciones influyentes del Modelo 2:

La tabla presenta las 19 observaciones que superan el umbral de referencia \(4/n \approx 0,0124\) para la distancia de Cook. Este criterio permite identificar registros que podrían ejercer una influencia mayor sobre la estimación del modelo, aunque superar el umbral no implica que deban eliminarse automáticamente.

Las observaciones 227 y 278 destacan claramente sobre las demás, con distancias de Cook de 0,0816 y 0,0594, respectivamente. Ambas corresponden a viviendas con características alejadas del comportamiento central de la base: precios de 1.940 y 1.600 millones de pesos, áreas de 734 y 942 m² y 10 habitaciones en ambos casos.

También se identifican otros casos con valores extremos o poco frecuentes. Por ejemplo, la observación 49 presenta un área de 1.188 m², la mayor del subconjunto, mientras que las observaciones 175, 221 y 151 corresponden a viviendas con precios entre 1.400 y 1.530 millones de pesos. En otros casos, la influencia parece estar asociada a combinaciones particulares entre área, precio, baños y habitaciones, más que a un único valor extremo.

En general, las observaciones influyentes identificadas parecen corresponder principalmente a viviendas reales con características poco frecuentes dentro del subconjunto, y no se evidencia un error manifiesto de registro que justifique su eliminación inmediata.

Por tanto, estas observaciones deben mantenerse inicialmente en el análisis. Sin embargo, las observaciones 227 y 278 continúan presentando las mayores distancias de Cook dentro del Modelo 2 y constituyen los casos más relevantes para evaluar la sensibilidad de la estimación.

Balance del Modelo 2 frente al Modelo 1:

La evaluación conjunta permite establecer que el Modelo 2 presenta un comportamiento más favorable que el Modelo 1, aunque todavía no corrige completamente todos los incumplimientos.

En normalidad se observa una mejora importante: el estadístico de Shapiro-Wilk pasa de 0,87 a 0,98, acercándose considerablemente a 1, aunque el valor p continúa siendo inferior a 0,05. En homocedasticidad también existe una mejora: el estadístico de Breusch-Pagan disminuye de 47 a 19, lo que evidencia una reducción de la heterocedasticidad, aunque esta continúa siendo estadísticamente significativa.

La multicolinealidad se mantiene en niveles bajos y prácticamente sin cambios frente al Modelo 1, por lo que la transformación no genera una desmejora en este aspecto. Asimismo, la influencia de las observaciones extremas disminuye de forma considerable: la mayor distancia de Cook pasa de 0,4001 a 0,0816.

La prueba de Durbin-Watson no presenta una mejora y continúa sugiriendo autocorrelación positiva según el orden de los registros. Sin embargo, al tratarse de datos de corte transversal, este resultado debe interpretarse con cautela.

En cuanto a la significancia individual, área construida, parqueaderos y estrato permanecen significativos; baños pasa a ser significativo en el Modelo 2, mientras que habitaciones deja de serlo. Debido a que no se evidencia multicolinealidad importante y la variable habitaciones forma parte de las características requeridas en el ejercicio, se conserva dentro de la especificación.

Por tanto, el Modelo 2 representa una mejora respecto al Modelo 1 principalmente por el comportamiento de sus residuos y por su menor sensibilidad a valores extremos. No obstante, debido a que aún persisten problemas de normalidad y heterocedasticidad, se plantea un tercer y último modelo orientado específicamente a buscar una transformación de la variable respuesta que pueda mejorar estos aspectos.

3.3.3 Modelo 3: transformación Box-Cox del precio

Los resultados del Modelo 2 muestran que la transformación logarítmica mejora de manera importante el comportamiento del modelo respecto a la escala original, especialmente en la aproximación a la normalidad, la reducción de la heterocedasticidad y la disminución de la influencia de valores extremos. Sin embargo, las pruebas formales indican que todavía persisten incumplimientos en normalidad y homocedasticidad.

Por esta razón, el Modelo 3 no se construye eliminando observaciones plausibles ni suprimiendo variables de manera automática. En su lugar, se utiliza la transformación de Box-Cox sobre el precio, procedimiento que permite buscar de manera sistemática una potencia de transformación de la variable respuesta orientada a mejorar problemas como la no normalidad y la varianza no constante.

Se conserva log(areaconst) porque el análisis exploratorio mostró que esta transformación representa mejor la relación entre precio y área. También se mantienen parqueaderos, baños, habitaciones y estrato, dado que los modelos anteriores no evidenciaron problemas relevantes de multicolinealidad y estas variables forman parte de la especificación requerida para el ejercicio.

La transformación Box-Cox determina un parámetro \(\lambda\). Cuando \(\lambda\) es cercano a cero, la transformación sugerida es muy similar al logaritmo; por tanto, este tercer modelo también permitirá comprobar si el Modelo 2 ya se encontraba próximo a la transformación más adecuada o si otra potencia produce una mejora adicional.

Estimación de la transformación Box-Cox:

# Ajustar un modelo base conservando la transformación del área
# encontrada durante el análisis exploratorio.
# La variable respuesta se mantiene inicialmente en su escala original
# para estimar la transformación Box-Cox.

modelo_base_boxcox <- lm(
  preciom ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda1
)

# Evaluar diferentes valores de lambda mediante Box-Cox
boxcox_modelo3 <- MASS::boxcox(
  modelo_base_boxcox,
  lambda = seq(-2, 2, by = 0.1)
)

# Identificar el valor de lambda que maximiza
# la log-verosimilitud
lambda_modelo3 <- boxcox_modelo3$x[
  which.max(boxcox_modelo3$y)
]

# Mostrar el lambda seleccionado
lambda_modelo3
## [1] -0.6263

Interpretación de la transformación Box-Cox:

La transformación de Box-Cox permite identificar una potencia de transformación para la variable respuesta con el propósito de mejorar el comportamiento del modelo, especialmente cuando se presentan problemas de normalidad, heterocedasticidad o falta de linealidad.

Para el precio de las viviendas se obtiene un valor óptimo de \(\lambda=-0,6263\), correspondiente al punto donde la log-verosimilitud alcanza su valor máximo. El gráfico muestra además que el valor óptimo se encuentra claramente por debajo de cero.

Este resultado es relevante frente al Modelo 2. Cuando \(\lambda=0\), la transformación Box-Cox equivale a utilizar el logaritmo de la variable respuesta. En este caso, el valor estimado de \(\lambda\) se encuentra suficientemente alejado de cero, por lo que la transformación sugerida por Box-Cox es diferente de la transformación logarítmica utilizada previamente.

Al ser \(\lambda\) negativo, la transformación comprime con mayor intensidad los valores elevados del precio. Esto podría contribuir a reducir la influencia de las viviendas de precios extremos y a estabilizar la variabilidad de los residuos, dos aspectos que todavía presentaban dificultades en el Modelo 2.

Por tanto, el resultado proporciona una justificación estadística para estimar el Modelo 3 utilizando la transformación Box-Cox del precio con \(\lambda=-0,6263\). Sin embargo, no puede afirmarse todavía que este modelo sea superior al Modelo 2. Para determinarlo será necesario evaluar nuevamente sus coeficientes, los gráficos de residuos, las pruebas de normalidad y homocedasticidad, la multicolinealidad y las observaciones influyentes.

Estimación del Modelo 3:

# Crear una copia de la base para aplicar
# la transformación Box-Cox al precio
modelo_vivienda1_m3 <- modelo_vivienda1

# Aplicar la transformación Box-Cox al precio.
# Cuando lambda es cero o numéricamente muy cercano a cero,
# se utiliza la transformación logarítmica.
if (abs(lambda_modelo3) < 1e-8) {
  
  modelo_vivienda1_m3$precio_boxcox <- log(
    modelo_vivienda1_m3$preciom
  )
  
} else {
  
  modelo_vivienda1_m3$precio_boxcox <- (
    modelo_vivienda1_m3$preciom^lambda_modelo3 - 1
  ) / lambda_modelo3
  
}

# Estimar el Modelo 3 conservando la misma estructura
# de variables explicativas utilizada en el Modelo 2
modelo3 <- lm(
  precio_boxcox ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda1_m3
)

# Mostrar el resumen del Modelo 3
summary(modelo3)
## 
## Call:
## lm(formula = precio_boxcox ~ log(areaconst) + parqueaderos + 
##     banios + habitaciones + estrato, data = modelo_vivienda1_m3)
## 
## Residuals:
##       Min        1Q    Median        3Q       Max 
## -0.014873 -0.003249  0.000083  0.003005  0.014793 
## 
## Coefficients:
##                 Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)    1.5010605  0.0031517  476.27 < 0.0000000000000002 ***
## log(areaconst) 0.0097060  0.0006335   15.32 < 0.0000000000000002 ***
## parqueaderos   0.0008026  0.0002119    3.79              0.00018 ***
## banios         0.0007230  0.0002922    2.47              0.01388 *  
## habitaciones   0.0000466  0.0002269    0.21              0.83734    
## estrato5       0.0024325  0.0005959    4.08             0.000057 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.00481 on 317 degrees of freedom
## Multiple R-squared:  0.61,   Adjusted R-squared:  0.604 
## F-statistic: 99.2 on 5 and 317 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 3:

El Modelo 3 utiliza una transformación Box-Cox del precio con \(\lambda=-0,6263\), manteniendo log(areaconst) y las demás variables explicativas en la misma forma utilizada en el Modelo 2. Debido a que la variable respuesta se encuentra en una escala transformada, los coeficientes no se interpretan directamente en millones de pesos ni como porcentajes.

Para evaluar la significancia estadística se mantiene como referencia un nivel del 5 % (\(p<0,05\)).

  • Área construida: log(areaconst) presenta un coeficiente de 0,0097060 y un valor p inferior a 0,001, por lo que continúa siendo una variable altamente significativa dentro del modelo.

  • Parqueaderos: presenta un coeficiente de 0,0008026 y un valor p de 0,00018, manteniendo una asociación estadísticamente significativa con la variable respuesta transformada.

  • Baños: el coeficiente estimado es de 0,0007230, con un valor p de 0,01388, por lo que también resulta estadísticamente significativo.

  • Habitaciones: presenta un coeficiente de 0,0000466 y un valor p de 0,83734, por lo que continúa sin mostrar evidencia estadística de un efecto adicional una vez se controlan las demás variables.

  • Estrato: estrato5 presenta un coeficiente de 0,0024325 y un valor p de 0,000057, por lo que mantiene una asociación estadísticamente significativa respecto al estrato 4, que continúa siendo la categoría de referencia.

El modelo presenta un \(R^2=0,610\) y un \(R^2\) ajustado de 0,604, lo que indica que aproximadamente el 61 % de la variabilidad de la variable respuesta transformada es explicada por las variables incorporadas. Sin embargo, este valor no debe utilizarse como criterio directo para afirmar que el Modelo 3 es superior al Modelo 2, dado que ambos utilizan transformaciones diferentes del precio.

La prueba F global alcanza un valor de 99,2, con un valor p inferior a 0,001, por lo que el Modelo 3 resulta estadísticamente significativo en su conjunto.

En comparación con el Modelo 2, se mantiene el mismo patrón general de significancia: área construida, parqueaderos, baños y estrato continúan siendo variables relevantes, mientras que habitaciones permanece sin significancia estadística. Esto sugiere que la transformación Box-Cox modifica principalmente la escala y el comportamiento de la variable respuesta, pero no altera de manera importante la estructura general de relaciones identificada previamente.

Por tanto, el resultado del summary() muestra que el Modelo 3 es estadísticamente consistente y mantiene relaciones similares a las observadas en el Modelo 2. No obstante, la decisión sobre si representa una mejora real depende principalmente de la validación de los supuestos, especialmente normalidad, homocedasticidad e influencia de observaciones extremas.

Validación gráfica de los supuestos del Modelo 3:

# Revisar los gráficos básicos de diagnóstico
# del Modelo 3

par(mfrow = c(2, 2))

plot(modelo3)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 3:

Los gráficos de diagnóstico del Modelo 3 muestran un comportamiento más favorable de los residuos en comparación con los modelos anteriores.

  • Residuos frente a valores ajustados: los residuos se distribuyen de manera relativamente equilibrada alrededor de cero y no se observa el patrón de dispersión creciente que era claramente evidente en el Modelo 1. Frente al Modelo 2, la dispersión también parece más homogénea. La línea de tendencia presenta únicamente una ligera curvatura, por lo que visualmente la relación resulta más estable.

  • Gráfico Q-Q de los residuos: la mayoría de las observaciones se encuentra muy próxima a la línea de referencia. En comparación con el Modelo 1, donde existían desviaciones importantes en las colas, y con el Modelo 2, donde todavía permanecían algunas diferencias, el Modelo 3 muestra una aproximación visual más clara a la normalidad. Solo se observan pequeñas desviaciones en los extremos.

  • Scale-Location: la línea presenta un comportamiento considerablemente más horizontal que en el Modelo 1 y ligeramente más estable que en el Modelo 2. Esto sugiere una mayor homogeneidad en la dispersión de los residuos y, por tanto, una posible reducción adicional de la heterocedasticidad.

  • Residuos frente a leverage: la mayor parte de las observaciones se concentra en valores bajos de leverage. Se identifican algunos registros más alejados, entre ellos una observación con leverage relativamente elevado, pero no se aprecia gráficamente una concentración severa de observaciones con influencia extrema. Este aspecto deberá complementarse posteriormente con la distancia de Cook.

En conjunto, el diagnóstico gráfico sugiere que la transformación Box-Cox utilizada en el Modelo 3 mejora el comportamiento de los residuos respecto a los Modelos 1 y 2, particularmente en términos de normalidad y estabilidad de la varianza. Sin embargo, esta conclusión debe confirmarse mediante las pruebas formales de Shapiro-Wilk y Breusch-Pagan.

Pruebas formales de supuestos del Modelo 3:

# Prueba de normalidad de los residuos
shapiro_m3 <- shapiro.test(
  residuals(modelo3)
)

shapiro_m3
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo3)
## W = 1, p-value = 0.8
# Prueba de homocedasticidad
bp_m3 <- lmtest::bptest(
  modelo3
)

bp_m3
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo3
## BP = 3, df = 5, p-value = 0.7
# Prueba de independencia de los errores
dw_m3 <- lmtest::dwtest(
  modelo3
)

dw_m3
## 
##  Durbin-Watson test
## 
## data:  modelo3
## DW = 1.7, p-value = 0.001
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 3:

Las pruebas formales confirman las mejoras que se observaron previamente en los gráficos de diagnóstico. Se utiliza un nivel de significancia del 5 %, por lo que valores \(p>0,05\) indican que no existe evidencia suficiente para rechazar la hipótesis nula correspondiente.

  • Prueba de Shapiro-Wilk: esta prueba evalúa la normalidad de los residuos. La hipótesis nula establece que los residuos siguen una distribución normal. Para el Modelo 3 se obtiene un estadístico \(W=1,00\) y un valor \(p=0,80\). Debido a que el valor p es ampliamente superior a 0,05, no se rechaza la hipótesis nula. Por tanto, no se encuentra evidencia estadística de incumplimiento del supuesto de normalidad.

    Este resultado representa una mejora sustancial frente a los modelos anteriores. En el Modelo 1 se obtuvo \(W=0,87\) con un valor p inferior a 0,001, mientras que en el Modelo 2 el estadístico aumentó a \(W=0,98\), aunque el valor p continuó siendo 0,001. En el Modelo 3, la transformación Box-Cox permite finalmente alcanzar un comportamiento de los residuos compatible con la normalidad.

  • Prueba de Breusch-Pagan: esta prueba evalúa si la varianza de los residuos permanece constante. La hipótesis nula establece la existencia de homocedasticidad. El Modelo 3 presenta un estadístico \(BP=3\) y un valor \(p=0,70\). Como el valor p es superior a 0,05, no se rechaza la hipótesis nula. En consecuencia, no existe evidencia estadística de heterocedasticidad en este modelo.

    La mejora frente a los modelos anteriores es igualmente importante. El estadístico de Breusch-Pagan disminuyó de aproximadamente 47 en el Modelo 1, a 19 en el Modelo 2 y finalmente a 3 en el Modelo 3. De esta manera, la transformación Box-Cox logra corregir el problema de varianza no constante que permanecía presente incluso después de utilizar la transformación logarítmica.

  • Prueba de Durbin-Watson: esta prueba evalúa la presencia de autocorrelación positiva de los residuos según el orden de las observaciones. El Modelo 3 presenta un estadístico \(DW=1,7\) y un valor \(p=0,001\). Al ser inferior a 0,05, se mantiene evidencia estadística de autocorrelación positiva.

    En este aspecto, el Modelo 3 no presenta una mejora respecto al Modelo 2. Sin embargo, este resultado debe continuar interpretándose con cautela debido a que la información analizada corresponde a datos de corte transversal de viviendas y no a una serie temporal. El orden de los registros no necesariamente representa una secuencia con significado estadístico, por lo que este resultado no debe utilizarse de manera aislada para descartar el modelo.

En conjunto, las pruebas formales muestran que el Modelo 3 representa una mejora sustancial frente a los Modelos 1 y 2. La transformación Box-Cox permite corregir los principales incumplimientos relacionados con la normalidad y la homocedasticidad de los residuos, mientras que el único resultado que continúa siendo desfavorable corresponde a la prueba de Durbin-Watson, cuya interpretación es limitada en el contexto transversal de los datos.

Por tanto, hasta este punto, el Modelo 3 presenta el comportamiento estadístico más favorable de las tres especificaciones evaluadas.

Evaluación de la multicolinealidad del Modelo 3:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF)

vif_m3 <- car::vif(modelo3)

vif_m3
## log(areaconst)   parqueaderos         banios   habitaciones        estrato 
##          1.336          1.188          1.757          1.706          1.066

Interpretación de la multicolinealidad del Modelo 3:

El Factor de Inflación de la Varianza (VIF) permite evaluar si existe una relación lineal elevada entre las variables explicativas. Como referencia, valores cercanos a 1 indican una baja dependencia entre predictores, mientras que valores superiores a 5 pueden sugerir un problema de multicolinealidad.

Para el Modelo 3 se obtienen valores de 1,336 para log(areaconst), 1,188 para parqueaderos, 1,757 para baños, 1,706 para habitaciones y 1,066 para estrato.

Todos los valores se encuentran claramente por debajo del umbral de 5, por lo que no se evidencia un problema importante de multicolinealidad entre las variables explicativas.

En comparación con el Modelo 2, los valores VIF permanecen prácticamente iguales. Esto es esperable, dado que la transformación Box-Cox aplicada en el Modelo 3 modifica únicamente la variable respuesta (precio) y mantiene exactamente las mismas variables explicativas y transformaciones utilizadas en el Modelo 2. Por tanto, la estructura de relaciones entre los predictores no cambia.

Los valores más elevados continúan correspondiendo a baños y habitaciones, pero sus magnitudes siguen siendo suficientemente bajas para descartar un problema relevante de multicolinealidad.

En consecuencia, el Modelo 3 mantiene el buen comportamiento observado en los modelos anteriores respecto a este supuesto. La mejora obtenida con Box-Cox se concentra principalmente en la normalidad y la homocedasticidad de los residuos, sin generar efectos negativos sobre la relación entre las variables explicativas.

Análisis de observaciones influyentes del Modelo 3:

# Calcular la distancia de Cook para cada observación
dist_cook_m3 <- cooks.distance(modelo3)

# Definir el umbral de referencia
umbral_cook_m3 <- 4 / nrow(modelo_vivienda1_m3)

# Graficar las distancias de Cook
plot(
  dist_cook_m3,
  type = "h",
  main = "Distancia de Cook - Modelo 3",
  xlab = "Observación",
  ylab = "Distancia de Cook"
)

# Agregar la línea de referencia
abline(
  h = umbral_cook_m3,
  lty = 2
)

# Mostrar las 10 observaciones
# con mayor distancia de Cook
head(
  sort(dist_cook_m3, decreasing = TRUE),
  10
)
##      49     156     163     273       5     214     213     242     227      74 
## 0.03204 0.02235 0.02096 0.02015 0.01996 0.01891 0.01856 0.01828 0.01796 0.01757

Interpretación de las observaciones influyentes del Modelo 3:

La distancia de Cook permite identificar observaciones que pueden ejercer una influencia importante sobre los coeficientes estimados del modelo. Manteniendo como criterio de referencia \(4/n\), con 323 observaciones el umbral corresponde aproximadamente a 0,0124.

En el Modelo 3 se observan varias viviendas que superan este valor de referencia. Las mayores distancias de Cook corresponden a las observaciones 49 (0,0320), 156 (0,0224), 163 (0,0210), 273 (0,0202) y 5 (0,0200). También aparecen, con valores ligeramente menores, las observaciones 214, 213, 242, 227 y 74.

Estos registros deben considerarse potencialmente influyentes y merecen atención, pero sus valores presentan una magnitud considerablemente menor que la observada en los modelos anteriores. En el Modelo 1, la distancia de Cook máxima alcanzó aproximadamente 0,4001, mientras que en el Modelo 2 el máximo disminuyó a 0,0816. En el Modelo 3, el mayor valor es únicamente 0,0320.

Por tanto, se observa una reducción sustancial de la sensibilidad del modelo frente a observaciones particulares. Especialmente relevante es el comportamiento de la observación 227, que presentó una distancia de Cook de 0,3531 en el Modelo 1 y 0,0816 en el Modelo 2, mientras que en el Modelo 3 disminuye hasta aproximadamente 0,0180. Esto evidencia que la transformación Box-Cox reduce de manera importante la influencia que esta vivienda ejercía sobre la estimación.

La observación 49 continúa apareciendo entre los registros más influyentes y presenta una distancia de Cook cercana a la obtenida en el Modelo 2. Sin embargo, su valor permanece muy por debajo del registrado en el Modelo 1, donde alcanzaba aproximadamente 0,4001. Esto confirma que la transformación aplicada reduce considerablemente su efecto, aunque no lo elimina por completo.

En general, aunque todavía existen observaciones que superan el umbral de referencia, no se identifican casos con una influencia extrema comparable con la observada inicialmente. Además, las revisiones anteriores mostraron que estas viviendas corresponden principalmente a registros plausibles con características poco frecuentes, por lo que no existe una justificación para eliminarlas automáticamente.

En consecuencia, el Modelo 3 presenta el comportamiento más estable frente a observaciones influyentes entre las tres especificaciones evaluadas. Este resultado se suma a las mejoras obtenidas previamente en normalidad y homocedasticidad, fortaleciendo la evidencia a favor de la transformación Box-Cox.

Revisión de las observaciones que superan el umbral de Cook del Modelo 3:

# Identificar las observaciones que superan el umbral
obs_influyentes_m3 <- which(
  dist_cook_m3 > umbral_cook_m3
)

# Construir la tabla de revisión
revision_influyentes_m3 <- data.frame(
  Observacion = obs_influyentes_m3,
  Precio = modelo_vivienda1_m3$preciom[
    obs_influyentes_m3
  ],
  Area = modelo_vivienda1_m3$areaconst[
    obs_influyentes_m3
  ],
  Parqueaderos = modelo_vivienda1_m3$parqueaderos[
    obs_influyentes_m3
  ],
  Banios = modelo_vivienda1_m3$banios[
    obs_influyentes_m3
  ],
  Habitaciones = modelo_vivienda1_m3$habitaciones[
    obs_influyentes_m3
  ],
  Estrato = modelo_vivienda1_m3$estrato[
    obs_influyentes_m3
  ],
  Distancia_Cook = round(
    dist_cook_m3[obs_influyentes_m3],
    5
  )
)

# Ordenar de mayor a menor influencia
revision_influyentes_m3 <- revision_influyentes_m3[
  order(
    revision_influyentes_m3$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla
knitr::kable(
  revision_influyentes_m3,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 3"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 3
Observacion Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
49 49 650 1188.0 4 6 6 5 0.0320
156 156 230 250.0 2 3 5 4 0.0223
163 163 470 128.0 4 8 10 4 0.0210
273 273 360 389.0 2 6 9 4 0.0202
5 5 600 160.0 1 4 5 4 0.0200
214 214 750 250.0 3 6 8 4 0.0189
213 213 340 355.0 2 5 8 5 0.0186
242 242 850 296.0 4 2 4 5 0.0183
227 227 1940 734.0 3 8 10 5 0.0180
74 74 990 290.0 4 3 3 5 0.0176
175 175 1500 400.0 2 3 4 5 0.0164
310 310 830 292.0 4 6 8 4 0.0160
10 10 870 292.0 2 5 8 5 0.0157
174 174 260 280.0 2 4 6 4 0.0155
289 289 680 176.9 3 6 6 5 0.0154
204 204 380 450.0 2 6 7 4 0.0131
45 45 250 243.0 1 4 5 5 0.0130
263 263 800 900.0 6 5 4 5 0.0125

Interpretación de las observaciones influyentes del Modelo 3:

La tabla identifica 18 observaciones que superan el umbral de referencia \(4/n \approx 0,0124\) para la distancia de Cook. Estas observaciones presentan un potencial de influencia mayor sobre los coeficientes estimados, aunque superar este criterio no implica que deban eliminarse automáticamente.

La mayor distancia de Cook corresponde a la observación 49 (0,0320), asociada con una vivienda de 1.188 m² y un precio de 650 millones de pesos. Esta combinación continúa siendo poco frecuente dentro de la muestra, dado que presenta el área más elevada del subconjunto sin encontrarse entre los precios más altos.

También se destacan algunos registros con combinaciones particulares de características. Por ejemplo, la observación 163 presenta únicamente 128 m², pero registra 8 baños y 10 habitaciones; la observación 5 presenta 160 m² y un precio de 600 millones; mientras que la observación 156 presenta un precio relativamente bajo de 230 millones. Estos casos pueden apartarse del patrón predominante sin que necesariamente constituyan errores de registro.

Por otra parte, continúan apareciendo algunas viviendas de precios y áreas elevados, como las observaciones 227, con un precio de 1.940 millones y 734 m²; 175, con 1.500 millones y 400 m²; y 263, con 900 m². Sin embargo, sus distancias de Cook son considerablemente menores que las registradas en los modelos anteriores.

La reducción de la influencia es especialmente evidente al comparar las tres especificaciones. En el Modelo 1, la distancia de Cook máxima alcanzó aproximadamente 0,4001; en el Modelo 2 disminuyó a 0,0816; y en el Modelo 3 se reduce hasta 0,0320. Además, la observación 227, que era una de las más influyentes en los modelos anteriores, presenta ahora una distancia de Cook de aproximadamente 0,0180.

Aunque continúan existiendo observaciones por encima del umbral de referencia, sus magnitudes son relativamente moderadas y ninguna presenta una influencia comparable con la observada en el Modelo 1. La revisión de sus características muestra principalmente viviendas con combinaciones poco frecuentes de precio, área, baños, habitaciones o parqueaderos, pero no evidencia de manera general valores imposibles que justifiquen su eliminación.

En consecuencia, se considera adecuado mantener estas observaciones dentro de la base. La transformación Box-Cox reduce de manera importante la sensibilidad del modelo frente a los valores extremos y, junto con las mejoras obtenidas en normalidad y homocedasticidad, evidencia una mayor estabilidad del Modelo 3 respecto a las especificaciones anteriores. Comparación final de los Modelos 2 y 3:

Dado que los Modelos 2 y 3 pueden utilizar transformaciones diferentes de la variable respuesta, no resulta adecuado seleccionar entre ellos únicamente comparando sus valores de \(R^2\). La decisión se realizará principalmente a partir del cumplimiento de los supuestos y de la estabilidad del modelo.

# Calcular los principales diagnósticos
# para los tres modelos

# Prueba de normalidad
shapiro_m1 <- shapiro.test(
  residuals(modelo1)
)

shapiro_m2 <- shapiro.test(
  residuals(modelo2)
)

shapiro_m3 <- shapiro.test(
  residuals(modelo3)
)

# Prueba de homocedasticidad
bp_m1 <- lmtest::bptest(
  modelo1
)

bp_m2 <- lmtest::bptest(
  modelo2
)

bp_m3 <- lmtest::bptest(
  modelo3
)

# Prueba de independencia
dw_m1 <- lmtest::dwtest(
  modelo1
)

dw_m2 <- lmtest::dwtest(
  modelo2
)

dw_m3 <- lmtest::dwtest(
  modelo3
)

# Calcular los valores VIF
vif_m1 <- car::vif(modelo1)
vif_m2 <- car::vif(modelo2)
vif_m3 <- car::vif(modelo3)

# Calcular las distancias de Cook
dist_cook_m1 <- cooks.distance(modelo1)
dist_cook_m2 <- cooks.distance(modelo2)
dist_cook_m3 <- cooks.distance(modelo3)

# Construir una tabla comparativa
comparacion_modelos <- data.frame(
  Indicador = c(
    "Shapiro-Wilk (W)",
    "p-valor Shapiro-Wilk",
    "Breusch-Pagan (BP)",
    "p-valor Breusch-Pagan",
    "Durbin-Watson (DW)",
    "p-valor Durbin-Watson",
    "VIF máximo",
    "Distancia de Cook máxima"
  ),
  
  Modelo_1 = c(
    unname(shapiro_m1$statistic),
    shapiro_m1$p.value,
    unname(bp_m1$statistic),
    bp_m1$p.value,
    unname(dw_m1$statistic),
    dw_m1$p.value,
    max(vif_m1),
    max(dist_cook_m1)
  ),
  
  Modelo_2 = c(
    unname(shapiro_m2$statistic),
    shapiro_m2$p.value,
    unname(bp_m2$statistic),
    bp_m2$p.value,
    unname(dw_m2$statistic),
    dw_m2$p.value,
    max(vif_m2),
    max(dist_cook_m2)
  ),
  
  Modelo_3 = c(
    unname(shapiro_m3$statistic),
    shapiro_m3$p.value,
    unname(bp_m3$statistic),
    bp_m3$p.value,
    unname(dw_m3$statistic),
    dw_m3$p.value,
    max(vif_m3),
    max(dist_cook_m3)
  )
)

# Redondear los resultados
comparacion_modelos[, 2:4] <- round(
  comparacion_modelos[, 2:4],
  5
)

# Mostrar la comparación
knitr::kable(
  comparacion_modelos,
  caption = "Comparación de diagnósticos entre los Modelos 1, 2 y 3"
)
Comparación de diagnósticos entre los Modelos 1, 2 y 3
Indicador Modelo_1 Modelo_2 Modelo_3
Shapiro-Wilk (W) 0.8685 0.9838 0.9971
p-valor Shapiro-Wilk 0.0000 0.0011 0.8325
Breusch-Pagan (BP) 46.8920 18.7182 2.9898
p-valor Breusch-Pagan 0.0000 0.0022 0.7016
Durbin-Watson (DW) 1.7754 1.6663 1.6740
p-valor Durbin-Watson 0.0191 0.0011 0.0014
VIF máximo 1.7688 1.7565 1.7565
Distancia de Cook máxima 0.4001 0.0816 0.0320

Interpretación comparativa de los Modelos 1, 2 y 3:

La comparación de los tres modelos muestra una mejora progresiva en varios de los principales diagnósticos de regresión a medida que se incorporan transformaciones sobre la variable respuesta.

  • Normalidad de los residuos: el estadístico de Shapiro-Wilk aumenta de 0,8685 en el Modelo 1, a 0,9838 en el Modelo 2 y finalmente a 0,9971 en el Modelo 3. En los dos primeros modelos los valores p son inferiores a 0,05, por lo que se rechaza la hipótesis de normalidad. En cambio, en el Modelo 3 se obtiene un valor p de 0,8325, por lo que no existe evidencia para rechazar la normalidad de los residuos. Este resultado representa una mejora clara frente a las especificaciones anteriores.

  • Homocedasticidad: el estadístico de Breusch-Pagan disminuye considerablemente, pasando de 46,8920 en el Modelo 1, a 18,7182 en el Modelo 2 y a 2,9898 en el Modelo 3. Los valores p de los Modelos 1 y 2 son inferiores a 0,05, indicando heterocedasticidad. En el Modelo 3, el valor p aumenta hasta 0,7016, por lo que no se encuentra evidencia estadística de varianza no constante. La transformación Box-Cox logra, por tanto, corregir el principal problema de heterocedasticidad identificado en los modelos anteriores.

  • Independencia de los errores: los estadísticos de Durbin-Watson son 1,7754, 1,6663 y 1,6740 para los Modelos 1, 2 y 3, respectivamente. En los tres casos los valores p son inferiores a 0,05, por lo que la prueba continúa indicando autocorrelación positiva según el orden de las observaciones. En este aspecto no se evidencia una mejora con las transformaciones. Sin embargo, dado que se trabaja con datos de corte transversal de viviendas y no con una serie temporal, este resultado debe interpretarse con cautela.

  • Multicolinealidad: el VIF máximo permanece prácticamente constante y en niveles bajos: 1,7688 en el Modelo 1 y 1,7565 en los Modelos 2 y 3. Todos los valores se encuentran ampliamente por debajo de los niveles que indicarían un problema de multicolinealidad. Por tanto, este supuesto presenta un comportamiento adecuado en las tres especificaciones y no constituye un criterio de diferenciación importante entre ellas.

  • Observaciones influyentes: la distancia de Cook máxima disminuye de forma notable, pasando de 0,4001 en el Modelo 1, a 0,0816 en el Modelo 2 y finalmente a 0,0320 en el Modelo 3. Esto evidencia una reducción progresiva en la sensibilidad del modelo frente a viviendas con características extremas. Aunque continúan existiendo observaciones que superan el umbral de referencia, su capacidad de modificar las estimaciones es considerablemente menor en el Modelo 3.

En conjunto, el Modelo 1 presenta los mayores problemas de normalidad, heterocedasticidad e influencia de observaciones extremas. El Modelo 2, mediante la transformación logarítmica, mejora de manera importante estos aspectos, aunque todavía no logra satisfacer los supuestos de normalidad y homocedasticidad. Finalmente, el Modelo 3, utilizando la transformación Box-Cox con \(\lambda=-0,6263\), presenta el comportamiento diagnóstico más favorable: los residuos son compatibles con normalidad, no se encuentra evidencia de heterocedasticidad, se mantiene una baja multicolinealidad y se reduce considerablemente la influencia de observaciones particulares.

Por estas razones, el Modelo 3 se selecciona como la especificación más adecuada entre las tres alternativas evaluadas para continuar con la etapa de predicción. La única limitación que permanece corresponde al resultado de Durbin-Watson, cuya interpretación debe considerarse con precaución debido a la naturaleza transversal de los datos.

3.4 Predicción del precio para la vivienda 1

# Crear los dos escenarios solicitados
nueva_vivienda1 <- data.frame(
  areaconst = c(200, 200),
  parqueaderos = c(1, 1),
  banios = c(2, 2),
  habitaciones = c(4, 4),
  estrato = factor(
    c("4", "5"),
    levels = levels(modelo_vivienda1$estrato)
  )
)

# Predicción en la escala Box-Cox
prediccion_boxcox <- predict(
  modelo3,
  newdata = nueva_vivienda1,
  interval = "prediction",
  level = 0.95
)

# Transformación inversa para regresar
# a millones de pesos
if (abs(lambda_modelo3) < 1e-8) {
  
  prediccion_precio <- exp(
    prediccion_boxcox
  )
  
} else {
  
  prediccion_precio <- (
    lambda_modelo3 * prediccion_boxcox + 1
  )^(1 / lambda_modelo3)
  
}

# Tabla final de resultados
resultado_prediccion_v1 <- data.frame(
  Estrato = c(4, 5),
  `Precio estimado (millones)` = round(
    prediccion_precio[, "fit"],
    2
  ),
  `Intervalo de predicción 95% - Inferior` = round(
    prediccion_precio[, "lwr"],
    2
  ),
  `Intervalo de predicción 95% - Superior` = round(
    prediccion_precio[, "upr"],
    2
  ),
  `Crédito máximo (millones)` = 350,
  check.names = FALSE
)

knitr::kable(
  resultado_prediccion_v1,
  caption = "Predicción del precio para la Vivienda 1"
)
Predicción del precio para la Vivienda 1
Estrato Precio estimado (millones) Intervalo de predicción 95% - Inferior Intervalo de predicción 95% - Superior Crédito máximo (millones)
4 335.2 241.4 506.9 350
5 368.9 261.0 573.8 350

Interpretación de la predicción para la Vivienda 1:

A partir del Modelo 3 se estimó el precio de una vivienda con 200 m² de área construida, 1 parqueadero, 2 baños y 4 habitaciones, considerando los dos estratos admitidos en la solicitud.

Para una vivienda de estrato 4, el precio estimado es de aproximadamente $335,2 millones, valor que se encuentra por debajo del crédito máximo preaprobado de $350 millones. Por tanto, bajo las características consideradas, este escenario resulta compatible con la capacidad de financiación disponible.

Para una vivienda de estrato 5, el precio estimado aumenta a aproximadamente $368,9 millones, superando en cerca de $18,9 millones el presupuesto máximo. En consecuencia, una vivienda con estas mismas características en estrato 5 tendría, en promedio, un precio superior a la capacidad de financiación establecida.

Los intervalos de predicción del 95 % son relativamente amplios: entre $241,4 y $506,9 millones para estrato 4 y entre $261,0 y $573,8 millones para estrato 5. Esta amplitud refleja la variabilidad existente en los precios de viviendas individuales con características similares y la incertidumbre propia de realizar una predicción sobre una nueva propiedad. Por esta razón, estos intervalos no deben interpretarse como precios mínimos y máximos obligatorios, sino como un rango de valores plausibles según el modelo.

En términos de la decisión de compra, el estrato 4 presenta el escenario más favorable, dado que su estimación puntual se encuentra dentro del presupuesto disponible. Sin embargo, la amplitud del intervalo de predicción evidencia que el precio real de una vivienda particular puede diferir de la estimación, por lo que resulta necesario complementar el resultado del modelo con la búsqueda de ofertas efectivamente disponibles por debajo de los $350 millones.

3.5 Selección de ofertas potenciales

# Filtrar las viviendas que se encuentran
# dentro del presupuesto máximo de $350 millones
ofertas_v1 <- vivienda1 |>
  dplyr::filter(
    preciom <= 350
  ) |>
  
  # Calcular qué tan cerca se encuentra cada oferta
  # de las características solicitadas
  dplyr::mutate(
    Coincidencias = 
      (parqueaderos == 1) +
      (banios == 2) +
      (habitaciones == 4),
    
    Diferencia_area = abs(
      areaconst - 200
    )
  )

# Revisar cuántas ofertas cumplen con el presupuesto
nrow(ofertas_v1)
## [1] 82
# Seleccionar las ofertas que mejor se aproximan
# a las características solicitadas
ofertas_seleccionadas_v1 <- ofertas_v1 |>
  dplyr::arrange(
    dplyr::desc(Coincidencias),
    Diferencia_area,
    preciom
  ) |>
  dplyr::slice_head(
    n = 5
  )

# Mostrar las cinco ofertas seleccionadas
tabla_ofertas_v1 <- ofertas_seleccionadas_v1 |>
  dplyr::select(
    id,
    barrio,
    preciom,
    areaconst,
    parqueaderos,
    banios,
    habitaciones,
    estrato,
    Coincidencias,
    Diferencia_area
  )

knitr::kable(
  tabla_ofertas_v1,
  col.names = c(
    "ID",
    "Barrio",
    "Precio (millones)",
    "Área (m²)",
    "Parqueaderos",
    "Baños",
    "Habitaciones",
    "Estrato",
    "Coincidencias",
    "Diferencia área (m²)"
  ),
  caption = "Ofertas potenciales para la Vivienda 1"
)
Ofertas potenciales para la Vivienda 1
ID Barrio Precio (millones) Área (m²) Parqueaderos Baños Habitaciones Estrato Coincidencias Diferencia área (m²)
1666 alamos 275 120 1 2 4 4 3 80
1943 vipasa 350 346 1 2 4 5 3 146
1163 la merced 350 216 2 2 4 5 2 16
464 el bosque 330 165 1 4 4 4 2 35
94 zona norte 265 162 1 3 4 4 2 38

Interpretación de las ofertas potenciales para la Vivienda 1:

A partir de las viviendas disponibles en Zona Norte, de estratos 4 y 5, se seleccionaron cinco ofertas cuyo precio no supera el crédito máximo preaprobado de $350 millones. La selección considera la cercanía con las características solicitadas: 200 m² de área construida, 1 parqueadero, 2 baños y 4 habitaciones.

La oferta ubicada en Álamos presenta un precio de $275 millones y coincide exactamente con el número solicitado de parqueaderos, baños y habitaciones. Sin embargo, su área construida es de 120 m², es decir, 80 m² inferior a la requerida. Su principal ventaja es que cumple ampliamente con el presupuesto y con las demás características.

La vivienda de Vipasa tiene un precio de $350 millones y también coincide exactamente en parqueaderos, baños y habitaciones. No obstante, presenta un área considerablemente mayor, con 346 m². Aunque cumple con el presupuesto máximo, corresponde a una vivienda de mayor tamaño que el solicitado.

La oferta de La Merced se encuentra igualmente en el límite del presupuesto, con un precio de $350 millones, y presenta un área de 216 m², siendo la más cercana a los 200 m² solicitados. Cuenta con 2 parqueaderos en lugar de 1, mientras que coincide en 2 baños y 4 habitaciones. Esta característica adicional no representa necesariamente una desventaja y, considerando el área, constituye una de las alternativas más cercanas al perfil solicitado.

La vivienda de El Bosque, con un precio de $330 millones, dispone de 165 m², 1 parqueadero y 4 habitaciones. Su principal diferencia corresponde al número de baños, ya que ofrece 4 en lugar de los 2 solicitados. Aun así, se mantiene dentro del presupuesto y presenta una diferencia de área relativamente moderada.

Finalmente, la oferta identificada en Zona Norte tiene un precio de $265 millones, 162 m², 1 parqueadero, 3 baños y 4 habitaciones. Se encuentra ampliamente dentro del presupuesto y conserva varias de las características requeridas, aunque presenta un baño adicional y un área inferior a la solicitada.

En conjunto, las cinco alternativas cumplen con la restricción presupuestal y presentan diferentes grados de aproximación a las características requeridas. Entre ellas, La Merced se destaca por ser la más cercana al área solicitada, mientras que Álamos y Vipasa presentan coincidencia exacta en parqueaderos, baños y habitaciones. Por tanto, la selección final debe considerar el equilibrio entre precio, tamaño y características adicionales, más que únicamente el número de coincidencias exactas.

# Crear una paleta de colores para identificar
# las cinco ofertas seleccionadas
paleta_ofertas_v1 <- leaflet::colorFactor(
  palette = "Set1",
  domain = ofertas_seleccionadas_v1$id
)

# Construir el mapa interactivo
leaflet::leaflet(
  ofertas_seleccionadas_v1,
  width = "100%",
  height = 400
) |>
  leaflet::addProviderTiles(
    leaflet::providers$CartoDB.Positron
  ) |>
  leaflet::addCircleMarkers(
    lng = ~longitud,
    lat = ~latitud,
    radius = 6,
    color = ~paleta_ofertas_v1(id),
    fillOpacity = 0.85,
    stroke = TRUE,
    weight = 1,
    popup = ~paste0(
      "<b>Barrio:</b> ", barrio,
      "<br><b>Precio:</b> $", preciom, " millones",
      "<br><b>Área:</b> ", areaconst, " m²",
      "<br><b>Parqueaderos:</b> ", parqueaderos,
      "<br><b>Baños:</b> ", banios,
      "<br><b>Habitaciones:</b> ", habitaciones,
      "<br><b>Estrato:</b> ", estrato
    )
  ) |>
  leaflet::addLegend(
    position = "bottomright",
    pal = paleta_ofertas_v1,
    values = ~id,
    title = "ID de la oferta"
  ) |>
  leaflet::fitBounds(
    lng1 = min(
      ofertas_seleccionadas_v1$longitud,
      na.rm = TRUE
    ),
    lat1 = min(
      ofertas_seleccionadas_v1$latitud,
      na.rm = TRUE
    ),
    lng2 = max(
      ofertas_seleccionadas_v1$longitud,
      na.rm = TRUE
    ),
    lat2 = max(
      ofertas_seleccionadas_v1$latitud,
      na.rm = TRUE
    )
  )

Interpretación del mapa de ofertas potenciales:

El mapa permite visualizar la distribución espacial de las cinco viviendas seleccionadas que cumplen con el presupuesto máximo de $350 millones y presentan diferentes grados de aproximación a las características solicitadas.

Las ofertas se encuentran distribuidas en distintos sectores de la Zona Norte, lo que permite considerar alternativas con características similares en diferentes ubicaciones. Esta distribución muestra que no existe una única concentración espacial de las opciones potenciales y que la decisión puede complementarse con criterios como accesibilidad, entorno urbano y preferencia de localización.

No obstante, durante el análisis exploratorio se identificaron posibles inconsistencias en las coordenadas geográficas de algunos registros de la base. Por esta razón, la ubicación mostrada en el mapa debe utilizarse como referencia y conviene verificar posteriormente las coordenadas de las ofertas seleccionadas antes de realizar una recomendación definitiva.

En conjunto, el mapa complementa la comparación de precio y características físicas de las viviendas, facilitando una evaluación más integral de las alternativas disponibles.

3.6 Recomendación para la Vivienda 1

A partir del análisis realizado, el Modelo 3 con transformación Box-Cox fue seleccionado como la especificación más adecuada para estimar el precio de las viviendas de la primera solicitud. Este modelo presentó el mejor comportamiento de los residuos entre las alternativas evaluadas, al no encontrarse evidencia de incumplimiento de los supuestos de normalidad y homocedasticidad, mantener bajos niveles de multicolinealidad y reducir considerablemente la influencia de observaciones extremas.

Para una casa de 200 m², 1 parqueadero, 2 baños y 4 habitaciones, el modelo estima un precio aproximado de $335,2 millones en estrato 4 y $368,9 millones en estrato 5. Frente al crédito máximo disponible de $350 millones, el escenario de estrato 4 resulta compatible con la capacidad de financiación, mientras que el precio estimado para estrato 5 supera ligeramente el presupuesto.

La revisión de las ofertas disponibles permitió identificar cinco viviendas con precios iguales o inferiores a $350 millones y diferentes grados de aproximación a las características solicitadas. Entre ellas, la vivienda ubicada en La Merced presenta el área más cercana a los 200 m² requeridos, con 216 m², 2 baños y 4 habitaciones, aunque cuenta con un parqueadero adicional. Por otra parte, las viviendas de Álamos y Vipasa coinciden exactamente en parqueaderos, baños y habitaciones, pero presentan mayores diferencias respecto al área solicitada.

En términos generales, se recomienda priorizar inicialmente las alternativas de estrato 4, dado que presentan una mayor compatibilidad con el presupuesto estimado por el modelo. No obstante, la decisión final debe considerar conjuntamente el precio real de la oferta, el área construida, las características adicionales y la ubicación.

Finalmente, debido a que durante el análisis exploratorio se identificaron posibles inconsistencias en algunas coordenadas geográficas de la base, las ubicaciones presentadas en el mapa deben considerarse como referencia y verificarse antes de realizar una recomendación definitiva de compra.

4 Análisis de la Vivienda 2: Apartamento en Zona Sur

4.1 Caracterización de la base

# Revisar el tamaño de la base correspondiente a la Vivienda 2
dim(vivienda2)
## [1] 1437   13

Interpretación:

La base correspondiente a la Vivienda 2 está conformada por 1.437 registros y 13 variables. Las observaciones corresponden exclusivamente a apartamentos ubicados en la Zona Sur y pertenecientes a los estratos 5 o 6, de acuerdo con las condiciones definidas para la segunda solicitud.

El tamaño del subconjunto es considerablemente mayor que el utilizado para la Vivienda 1, por lo que se dispone de una base amplia para realizar el análisis exploratorio y la posterior estimación de los modelos de regresión. Las 13 variables se conservan inicialmente para mantener la información disponible, aunque la modelación se concentrará en el precio, el área construida, los parqueaderos, los baños, las habitaciones y el estrato.

# Obtener un resumen descriptivo de las variables cuantitativas
# relevantes para el análisis de la Vivienda 2
summary(
  vivienda2[, c(
    "preciom",
    "areaconst",
    "parqueaderos",
    "banios",
    "habitaciones"
  )]
)
##     preciom       areaconst    parqueaderos     banios      habitaciones
##  Min.   : 130   Min.   : 43   Min.   :1.0   Min.   :1.00   Min.   :1.0  
##  1st Qu.: 250   1st Qu.: 85   1st Qu.:1.0   1st Qu.:2.00   1st Qu.:3.0  
##  Median : 315   Median :103   Median :2.0   Median :3.00   Median :3.0  
##  Mean   : 389   Mean   :118   Mean   :1.6   Mean   :2.89   Mean   :3.1  
##  3rd Qu.: 450   3rd Qu.:133   3rd Qu.:2.0   3rd Qu.:3.00   3rd Qu.:3.0  
##  Max.   :1750   Max.   :932   Max.   :4.0   Max.   :8.00   Max.   :6.0

Interpretación:

El resumen descriptivo muestra diferencias importantes en la distribución de las características de los apartamentos:

  • Precio (preciom): varía entre 130 y 1.750 millones de pesos. El 50 % central se encuentra entre 250 y 450 millones, con una mediana de 315 millones y una media de 389 millones. La media superior a la mediana anticipa una distribución asimétrica hacia precios altos.
  • Área construida (areaconst): se encuentra entre 43 y 932 m². La mitad central de los apartamentos presenta áreas entre 85 y 133 m², con una mediana de 103 m² y una media de 118 m². La solicitud de 300 m² se ubica, por tanto, claramente por encima del comportamiento central del subconjunto, aunque continúa dentro del rango observado.
  • Parqueaderos: los apartamentos disponen entre 1 y 4 parqueaderos. La mediana es de 2 y el promedio de 1,6, por lo que los 3 parqueaderos requeridos corresponden a una característica menos frecuente, pero presente en la base.
  • Baños (banios): varían entre 1 y 8, con una mediana de 3 y una media de 2,89. En este caso, los 3 baños solicitados coinciden con el comportamiento central de la muestra.
  • Habitaciones: se encuentran entre 1 y 6, con una mediana de 3 y una media de 3,1. La solicitud de 5 habitaciones se sitúa por encima de lo habitual, aunque existen apartamentos que cumplen esta característica.

En conjunto, la segunda solicitud combina un área, número de parqueaderos y número de habitaciones superiores a los valores típicos del subconjunto. Esto permite anticipar que las viviendas más cercanas al perfil requerido podrían ubicarse en segmentos de mayor precio o ser menos frecuentes dentro de la oferta.

4.2 Análisis exploratorio específico

4.2.1 Distribución de las variables cuantitativas

# Organizar los histogramas en una sola figura
par(mfrow = c(3, 2))

# Distribución del precio
hist(
  vivienda2$preciom,
  main = "Distribución del precio",
  xlab = "Precio (millones de pesos)"
)

# Distribución del área construida
hist(
  vivienda2$areaconst,
  main = "Distribución del área construida",
  xlab = "Área construida (m²)"
)

# Distribución del número de parqueaderos
hist(
  vivienda2$parqueaderos,
  main = "Distribución de parqueaderos",
  xlab = "Número de parqueaderos"
)

# Distribución del número de baños
hist(
  vivienda2$banios,
  main = "Distribución de baños",
  xlab = "Número de baños"
)

# Distribución del número de habitaciones
hist(
  vivienda2$habitaciones,
  main = "Distribución de habitaciones",
  xlab = "Número de habitaciones"
)

# Restablecer la configuración gráfica
par(mfrow = c(1, 1))

Interpretación:

Los histogramas confirman que varias de las variables cuantitativas presentan distribuciones asimétricas:

  • Precio: la mayor parte de los apartamentos se concentra en los rangos bajos y medios, principalmente por debajo de 500 millones de pesos, mientras que la frecuencia disminuye a medida que aumenta el valor. Se observa una cola larga hacia precios superiores, coherente con la diferencia entre la media y la mediana.
  • Área construida: presenta una concentración muy marcada en áreas relativamente pequeñas, principalmente por debajo de 200 m², y una cola extensa hacia apartamentos de mayor tamaño. Los valores de 300 m² o más son poco frecuentes dentro del subconjunto.
  • Parqueaderos: la mayor concentración se encuentra en 1 y 2 espacios. Los apartamentos con 3 parqueaderos son menos frecuentes y los de 4 representan una proporción reducida.
  • Baños: la distribución se concentra especialmente entre 2 y 3 baños. A partir de 4 baños la frecuencia disminuye de forma progresiva, aunque se observan algunos apartamentos con hasta 8.
  • Habitaciones: la categoría dominante corresponde a 3 habitaciones. Los apartamentos con 5 o 6 habitaciones son menos frecuentes, lo cual es relevante porque la solicitud requiere precisamente 5 habitaciones.

En conjunto, los histogramas muestran que el perfil solicitado corresponde a un apartamento de características superiores al comportamiento central de la oferta, especialmente por su área, parqueaderos y habitaciones. Esta heterogeneidad también deberá considerarse al estudiar la relación entre las variables y el precio.

# Organizar los diagramas de cajas en una sola figura
par(mfrow = c(3, 2))

# Diagrama de cajas del precio
boxplot(
  vivienda2$preciom,
  main = "Precio",
  ylab = "Millones de pesos"
)

# Diagrama de cajas del área construida
boxplot(
  vivienda2$areaconst,
  main = "Área construida",
  ylab = "Área construida (m²)"
)

# Diagrama de cajas del número de parqueaderos
boxplot(
  vivienda2$parqueaderos,
  main = "Parqueaderos",
  ylab = "Número de parqueaderos"
)

# Diagrama de cajas del número de baños
boxplot(
  vivienda2$banios,
  main = "Baños",
  ylab = "Número de baños"
)

# Diagrama de cajas del número de habitaciones
boxplot(
  vivienda2$habitaciones,
  main = "Habitaciones",
  ylab = "Número de habitaciones"
)

# Restablecer la configuración gráfica
par(mfrow = c(1, 1))

Interpretación:

Los diagramas de cajas complementan lo observado en los histogramas y permiten identificar registros alejados del comportamiento central:

  • Precio: se observan numerosos valores por encima del bigote superior, correspondientes a apartamentos de precios elevados. Estos casos pueden ser plausibles dentro de los estratos 5 y 6 y no deben considerarse errores únicamente por su magnitud.
  • Área construida: aparecen varias observaciones con superficies muy superiores al rango central, incluyendo algunos apartamentos de varios cientos de metros cuadrados. En particular, los casos de mayor área deberán revisarse posteriormente porque pueden ejercer una influencia importante sobre el modelo.
  • Parqueaderos: la distribución es más acotada, entre 1 y 4 espacios, sin presentar magnitudes imposibles.
  • Baños: se identifican algunos registros elevados, principalmente por encima de 5 baños. Aunque son poco frecuentes, pueden corresponder a apartamentos de gran tamaño o alto valor.
  • Habitaciones: la mayor parte de las observaciones se concentra alrededor de 3 habitaciones. Los apartamentos con 1, 5 o 6 habitaciones aparecen más alejados del comportamiento central, pero siguen siendo posibles dentro del mercado.

Por tanto, los valores identificados como extremos se mantienen inicialmente en la base. Su posible efecto no se evaluará mediante una eliminación automática, sino posteriormente a través de los diagnósticos de influencia del modelo, especialmente la distancia de Cook.

4.2.2 Comportamiento del estrato

# Calcular la frecuencia de viviendas por estrato
frecuencia_estrato <- table(vivienda2$estrato)

# Calcular el porcentaje de viviendas por estrato
porcentaje_estrato <- prop.table(frecuencia_estrato) * 100

# Mostrar la distribución por estrato
data.frame(
  Estrato = names(frecuencia_estrato),
  Frecuencia = as.vector(frecuencia_estrato),
  Porcentaje = round(as.vector(porcentaje_estrato), 2)
)

Interpretación:

La distribución por estrato muestra una mayor representación de apartamentos de estrato 5, con 989 observaciones, equivalentes al 68,82 % del subconjunto. Por su parte, el estrato 6 reúne 448 registros, correspondientes al 31,18 %.

Aunque existe un desbalance entre ambos grupos, los dos estratos solicitados cuentan con una cantidad amplia de observaciones. Esto permite incorporar el estrato como una variable categórica en la regresión y evaluar si, manteniendo constantes las características físicas del apartamento, existe una diferencia sistemática en el precio entre los estratos 5 y 6.

# Resumir el precio de los apartamentos de estrato 5
summary(
  vivienda2$preciom[vivienda2$estrato == 5]
)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     130     235     280     295     332    1250
# Resumir el precio de los apartamentos de estrato 6
summary(
  vivienda2$preciom[vivienda2$estrato == 6]
)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##     180     417     580     596     700    1750
# Comparar visualmente el precio entre estratos
boxplot(
  preciom ~ estrato,
  data = vivienda2,
  main = "Precio de los apartamentos según estrato",
  xlab = "Estrato",
  ylab = "Precio (millones de pesos)"
)

Interpretación:

La comparación de los precios por estrato evidencia una diferencia importante entre ambos grupos.

  • Estrato 5: los precios se encuentran entre 130 y 1.250 millones de pesos. La mediana es de 280 millones, la media de 295 millones y el 50 % central se ubica aproximadamente entre 235 y 332 millones.
  • Estrato 6: el rango aumenta de 180 a 1.750 millones de pesos. La mediana alcanza 580 millones, la media 596 millones y el 50 % central se encuentra entre 417 y 700 millones.

El diagrama de cajas confirma un desplazamiento considerable de la distribución del estrato 6 hacia precios más altos. La diferencia entre las medianas es cercana a 300 millones de pesos, aunque existe cierta superposición entre ambos grupos.

Estos resultados sugieren que el estrato tendrá una capacidad explicativa relevante sobre el precio. Sin embargo, la comparación descriptiva no permite atribuir toda la diferencia únicamente al estrato, ya que los apartamentos de estrato 6 también pueden diferir en área, parqueaderos, baños u otras características. Por esta razón, su efecto se evaluará posteriormente dentro de la regresión múltiple.

4.2.3 Relación entre el precio y las variables explicativas

# Calcular la correlación entre el precio
# y el área construida
cor(
  vivienda2$preciom,
  vivienda2$areaconst,
  use = "complete.obs"
)
## [1] 0.6935
# Graficar la relación entre el precio
# y el área construida
plot(
  vivienda2$areaconst,
  vivienda2$preciom,
  main = "Precio vs. área construida",
  xlab = "Área construida (m²)",
  ylab = "Precio (millones de pesos)",
  pch = 19
)

# Agregar una línea de tendencia lineal
abline(
  lm(preciom ~ areaconst, data = vivienda2),
  lwd = 2
)

Interpretación:

La correlación entre el precio y el área construida es 0,6935, lo que indica una relación positiva y relativamente fuerte: en términos generales, los apartamentos con mayor área tienden a presentar precios superiores.

La nube de puntos confirma una tendencia ascendente, pero también muestra que la relación en escala original no es completamente homogénea. La dispersión de los precios aumenta a medida que crece el área y aparecen algunos apartamentos de áreas excepcionalmente grandes con precios que se apartan de la tendencia general. Este comportamiento es coherente con la asimetría identificada previamente en ambas variables.

Por tanto, aunque el área se perfila como una variable explicativa importante, la relación observada sugiere evaluar transformaciones que puedan mejorar la linealidad y reducir el efecto de las observaciones más extremas antes de definir la forma funcional de la regresión.

# Comparar diferentes formas funcionales de la relación
# entre el precio y el área construida

# 1. Precio vs. área construida
cor(
  vivienda2$preciom,
  vivienda2$areaconst,
  use = "complete.obs"
)
## [1] 0.6935
# 2. Precio vs. logaritmo del área construida
cor(
  vivienda2$preciom,
  log(vivienda2$areaconst),
  use = "complete.obs"
)
## [1] 0.7705
# 3. Logaritmo del precio vs. área construida
cor(
  log(vivienda2$preciom),
  vivienda2$areaconst,
  use = "complete.obs"
)
## [1] 0.6729
# 4. Logaritmo del precio vs. logaritmo del área construida
cor(
  log(vivienda2$preciom),
  log(vivienda2$areaconst),
  use = "complete.obs"
)
## [1] 0.8
# Comparar gráficamente las cuatro relaciones
par(mfrow = c(2, 2))

# Precio vs. área
plot(
  vivienda2$areaconst,
  vivienda2$preciom,
  main = "Precio vs. área",
  xlab = "Área construida (m²)",
  ylab = "Precio (millones)",
  pch = 19
)

# Precio vs. log(área)
plot(
  log(vivienda2$areaconst),
  vivienda2$preciom,
  main = "Precio vs. log(área)",
  xlab = "Logaritmo del área construida",
  ylab = "Precio (millones)",
  pch = 19
)

# log(precio) vs. área
plot(
  vivienda2$areaconst,
  log(vivienda2$preciom),
  main = "log(Precio) vs. área",
  xlab = "Área construida (m²)",
  ylab = "Logaritmo del precio",
  pch = 19
)

# log(precio) vs. log(área)
plot(
  log(vivienda2$areaconst),
  log(vivienda2$preciom),
  main = "log(Precio) vs. log(área)",
  xlab = "Logaritmo del área construida",
  ylab = "Logaritmo del precio",
  pch = 19
)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación de las transformaciones del área:

La comparación de las cuatro formas funcionales muestra una mejora clara cuando se incorporan transformaciones logarítmicas:

  • Precio vs. área construida: correlación de 0,6935.
  • Precio vs. log(área construida): la correlación aumenta a 0,7705, por lo que transformar únicamente el área mejora de manera importante la asociación lineal.
  • log(precio) vs. área construida: la correlación disminuye a 0,6729, por lo que transformar solamente el precio no mejora la relación frente a la escala original.
  • log(precio) vs. log(área construida): presenta la mayor correlación, con un valor de 0,8000.

Además del mayor coeficiente de correlación, la representación log-log muestra visualmente una relación más compacta y cercana a una tendencia lineal. Este resultado es especialmente relevante porque tanto el precio como el área presentan asimetría hacia la derecha.

En consecuencia, la especificación log(precio) frente a log(área) se considera una candidata importante para la modelación. No obstante, al igual que en la Vivienda 1, la decisión final no se basará únicamente en la correlación; será necesario contrastar los modelos y revisar formalmente sus residuos y supuestos.

# Comparar las correlaciones bajo diferentes transformaciones

comparacion_cor_v2 <- data.frame(
  Variable = c(
    "Parqueaderos",
    "Baños",
    "Habitaciones"
  ),

  `Precio vs. variable` = c(
    cor(vivienda2$preciom, vivienda2$parqueaderos),
    cor(vivienda2$preciom, vivienda2$banios),
    cor(vivienda2$preciom, vivienda2$habitaciones)
  ),

  `Precio vs. log(variable)` = c(
    cor(vivienda2$preciom, log(vivienda2$parqueaderos)),
    cor(vivienda2$preciom, log(vivienda2$banios)),
    cor(vivienda2$preciom, log(vivienda2$habitaciones))
  ),

  `log(Precio) vs. variable` = c(
    cor(log(vivienda2$preciom), vivienda2$parqueaderos),
    cor(log(vivienda2$preciom), vivienda2$banios),
    cor(log(vivienda2$preciom), vivienda2$habitaciones)
  ),

  `log(Precio) vs. log(variable)` = c(
    cor(log(vivienda2$preciom), log(vivienda2$parqueaderos)),
    cor(log(vivienda2$preciom), log(vivienda2$banios)),
    cor(log(vivienda2$preciom), log(vivienda2$habitaciones))
  ),

  check.names = FALSE
)

# Redondear las correlaciones
comparacion_cor_v2[, -1] <- round(
  comparacion_cor_v2[, -1],
  4
)

# Mostrar una tabla compacta
knitr::kable(
  comparacion_cor_v2,
  align = "lcccc",
  caption = "Comparación de correlaciones según transformación"
)
Comparación de correlaciones según transformación
Variable Precio vs. variable Precio vs. log(variable) log(Precio) vs. variable log(Precio) vs. log(variable)
Parqueaderos 0.7144 0.6800 0.7339 0.7271
Baños 0.6827 0.6427 0.7107 0.6865
Habitaciones 0.2788 0.2581 0.3049 0.2886

Interpretación de las transformaciones de variables discretas:

La comparación de correlaciones muestra que la transformación de la variable respuesta mediante logaritmo mejora la relación con parqueaderos, baños y habitaciones, mientras que aplicar logaritmos adicionales a estas variables discretas no aporta una mejora relevante.

  • Parqueaderos: la correlación entre precio y parqueaderos es 0,7144. Al utilizar log(precio) y mantener parqueaderos en su escala original aumenta a 0,7339, que corresponde al valor más alto entre las alternativas evaluadas para esta variable. Al transformar también parqueaderos disminuye ligeramente a 0,7271.
  • Baños: la correlación en escala original es 0,6827 y aumenta a 0,7107 al relacionar log(precio) con baños sin transformar. El logaritmo de baños reduce nuevamente la asociación.
  • Habitaciones: presenta relaciones considerablemente más débiles. La correlación aumenta de 0,2788 en escala original a 0,3049 cuando se utiliza log(precio) y habitaciones sin transformación.

Por tanto, no se encuentra una justificación suficiente para transformar parqueaderos, baños o habitaciones. Al tratarse además de variables de conteo con pocos valores posibles, resulta más interpretable mantenerlas en su escala original.

La especificación candidata queda entonces conformada por log(precio) como respuesta, log(área) para el área construida y parqueaderos, baños y habitaciones en su escala original.

4.2.4 Visualización interactiva de las relaciones

# Gráfico interactivo: log(precio) vs. log(área construida)
g_area <- plotly::plot_ly(
  data = vivienda2,
  x = ~log(areaconst),
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Área construida:", areaconst, "m²",
    "<br>Precio:", preciom, "millones",
    "<br>Estrato:", estrato,
    "<br>Baños:", banios,
    "<br>Habitaciones:", habitaciones,
    "<br>Parqueaderos:", parqueaderos
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. log(área construida)",
    xaxis = list(title = "Logaritmo del área construida"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) vs. parqueaderos
g_parqueaderos <- plotly::plot_ly(
  data = vivienda2,
  x = ~parqueaderos,
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Parqueaderos:", parqueaderos,
    "<br>Precio:", preciom, "millones",
    "<br>Área construida:", areaconst, "m²",
    "<br>Estrato:", estrato
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. parqueaderos",
    xaxis = list(title = "Número de parqueaderos"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) vs. baños
g_banios <- plotly::plot_ly(
  data = vivienda2,
  x = ~banios,
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Baños:", banios,
    "<br>Precio:", preciom, "millones",
    "<br>Área construida:", areaconst, "m²",
    "<br>Estrato:", estrato
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. baños",
    xaxis = list(title = "Número de baños"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) vs. habitaciones
g_habitaciones <- plotly::plot_ly(
  data = vivienda2,
  x = ~habitaciones,
  y = ~log(preciom),
  type = "scatter",
  mode = "markers",
  text = ~paste(
    "Habitaciones:", habitaciones,
    "<br>Precio:", preciom, "millones",
    "<br>Área construida:", areaconst, "m²",
    "<br>Estrato:", estrato
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) vs. habitaciones",
    xaxis = list(title = "Número de habitaciones"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Gráfico interactivo: log(precio) según estrato
g_estrato <- plotly::plot_ly(
  data = vivienda2,
  x = ~as.factor(estrato),
  y = ~log(preciom),
  type = "box",
  text = ~paste(
    "Estrato:", estrato,
    "<br>Precio:", preciom, "millones"
  ),
  hoverinfo = "text",
  width = 620,
  height = 360
) |>
  plotly::layout(
    title = "log(Precio) según estrato",
    xaxis = list(title = "Estrato"),
    yaxis = list(title = "Logaritmo del precio")
  )

# Mostrar los gráficos interactivos
g_area
g_parqueaderos
g_banios
g_habitaciones
g_estrato

Interpretación:

Las visualizaciones interactivas confirman los patrones identificados previamente. La relación entre log(precio) y log(área) presenta una tendencia positiva clara y relativamente compacta, siendo la asociación visual más definida entre las variables analizadas.

En parqueaderos y baños se observa también un aumento general del logaritmo del precio a medida que crece el número de estas características. Debido a que son variables discretas, los puntos se agrupan verticalmente en cada número posible de parqueaderos o baños, pero la tendencia ascendente es evidente.

La relación con habitaciones es considerablemente más débil. Existe una amplia dispersión de precios dentro de cada número de habitaciones, lo cual coincide con las correlaciones obtenidas y anticipa que el efecto de esta variable podría cambiar cuando se controle simultáneamente por área, baños y parqueaderos.

Finalmente, el diagrama por estrato muestra una separación clara entre los apartamentos de estrato 5 y 6, con niveles de log(precio) generalmente superiores en el estrato 6. En conjunto, las visualizaciones respaldan la incorporación de estas variables en la regresión múltiple y la evaluación de una especificación logarítmica.

4.2.5 Matriz de correlación entre variables

# Construir una base con las variables cuantitativas
# que se utilizarán como referencia para la modelación

variables_cor_v2 <- data.frame(
  log_precio = log(vivienda2$preciom),
  log_area = log(vivienda2$areaconst),
  parqueaderos = vivienda2$parqueaderos,
  banios = vivienda2$banios,
  habitaciones = vivienda2$habitaciones
)

# Calcular la matriz de correlación
matriz_cor_v2 <- cor(
  variables_cor_v2,
  use = "complete.obs"
)

# Mostrar la matriz redondeada
round(matriz_cor_v2, 4)
##              log_precio log_area parqueaderos banios habitaciones
## log_precio       1.0000   0.8000       0.7339 0.7107       0.3049
## log_area         0.8000   1.0000       0.6734 0.7241       0.4712
## parqueaderos     0.7339   0.6734       1.0000 0.5956       0.2643
## banios           0.7107   0.7241       0.5956 1.0000       0.5311
## habitaciones     0.3049   0.4712       0.2643 0.5311       1.0000

Interpretación:

La matriz de correlación permite evaluar conjuntamente las relaciones entre las variables consideradas para la modelación.

La asociación más alta con la variable respuesta corresponde a log_area, con una correlación de 0,8000 con log_precio. Le siguen parqueaderos (0,7339) y baños (0,7107), lo que muestra que estas tres variables tienen una relación lineal importante con el precio en escala logarítmica. Habitaciones presenta una correlación bastante menor, de 0,3049.

Entre las variables explicativas se observan algunas asociaciones moderadas a relativamente altas: log_area con baños alcanza 0,7241, log_area con parqueaderos 0,6734, parqueaderos con baños 0,5956 y baños con habitaciones 0,5311. Estas relaciones son razonables en el contexto inmobiliario, ya que los apartamentos de mayor tamaño suelen disponer también de más baños y parqueaderos.

Aunque algunas correlaciones entre predictores son relevantes, ninguna permite por sí sola concluir que exista un problema grave de multicolinealidad. Este aspecto se revisará formalmente mediante el VIF después de estimar los modelos.

4.2.6 Distribución geográfica de las ofertas

# Calcular los puntos de corte de los cuartiles del precio
cuartiles_precio_v2 <- quantile(
  vivienda2$preciom,
  probs = c(0, 0.25, 0.50, 0.75, 1)
)

# Crear etiquetas con los rangos de precio
etiquetas_precio_v2 <- c(
  paste0(
    "Q1: ", round(cuartiles_precio_v2[1]), " - ",
    round(cuartiles_precio_v2[2]), " millones"
  ),
  paste0(
    "Q2: ", round(cuartiles_precio_v2[2]), " - ",
    round(cuartiles_precio_v2[3]), " millones"
  ),
  paste0(
    "Q3: ", round(cuartiles_precio_v2[3]), " - ",
    round(cuartiles_precio_v2[4]), " millones"
  ),
  paste0(
    "Q4: ", round(cuartiles_precio_v2[4]), " - ",
    round(cuartiles_precio_v2[5]), " millones"
  )
)

# Clasificar cada vivienda según el cuartil de precio
vivienda2$grupo_precio_v2 <- cut(
  vivienda2$preciom,
  breaks = cuartiles_precio_v2,
  include.lowest = TRUE,
  labels = etiquetas_precio_v2
)

# Crear una paleta de colores para los grupos de precio
paleta_precio_v2 <- leaflet::colorFactor(
  palette = "YlOrRd",
  domain = vivienda2$grupo_precio_v2
)

# Crear el mapa interactivo
leaflet::leaflet(
  vivienda2,
  width = "100%",
  height = 380
) |>
  # Utilizar un mapa base más limpio
  leaflet::addProviderTiles(
    leaflet::providers$CartoDB.Positron
  ) |>

  # Agregar las ofertas de vivienda
  leaflet::addCircleMarkers(
    lng = ~longitud,
    lat = ~latitud,
    radius = 3.5,
    color = ~paleta_precio_v2(grupo_precio_v2),
    fillColor = ~paleta_precio_v2(grupo_precio_v2),
    fillOpacity = 0.7,
    stroke = FALSE,

    # Mostrar información de cada vivienda
    popup = ~paste(
      "<b>Precio:</b>", preciom, "millones",
      "<br><b>Grupo:</b>", grupo_precio_v2,
      "<br><b>Área:</b>", areaconst, "m²",
      "<br><b>Estrato:</b>", estrato,
      "<br><b>Baños:</b>", banios,
      "<br><b>Habitaciones:</b>", habitaciones,
      "<br><b>Parqueaderos:</b>", parqueaderos
    )
  ) |>

  # Agregar la leyenda de los cuartiles
  leaflet::addLegend(
    position = "bottomright",
    pal = paleta_precio_v2,
    values = ~grupo_precio_v2,
    title = "Precio por cuartiles",
    opacity = 1
  ) |>

  # Ajustar automáticamente el mapa
  # al rango de coordenadas de las viviendas
  leaflet::fitBounds(
    lng1 = min(vivienda2$longitud),
    lat1 = min(vivienda2$latitud),
    lng2 = max(vivienda2$longitud),
    lat2 = max(vivienda2$latitud)
  )

Interpretación:

El mapa muestra una concentración importante de los apartamentos en el sector sur y suroccidental de Cali, lo cual resulta coherente en términos generales con el filtro utilizado para construir la base de la Vivienda 2.

Los precios se distribuyen en cuatro cuartiles: aproximadamente 130–250 millones, 250–315 millones, 315–450 millones y 450–1.750 millones. Los distintos grupos aparecen mezclados espacialmente dentro del área principal de concentración, aunque los registros de precios altos también se encuentran representados en diferentes sectores de la Zona Sur.

A diferencia de lo observado con mayor claridad en la Vivienda 1, en este subconjunto la distribución espacial presenta una correspondencia general más consistente con la zona solicitada. No obstante, debido a que previamente se identificaron posibles problemas de georreferenciación en la base general, las coordenadas deben seguir tratándose como una referencia y conviene verificarlas al analizar ofertas específicas.

El mapa complementa así el análisis descriptivo y permite observar simultáneamente la localización y la heterogeneidad de precios de la oferta disponible.

4.3 Modelo de regresión lineal múltiple

# Crear una copia de la base para la etapa de modelación
modelo_vivienda2 <- vivienda2

# Convertir el estrato en variable categórica
modelo_vivienda2$estrato <- as.factor(
  modelo_vivienda2$estrato
)

# Verificar la estructura de la variable
str(modelo_vivienda2$estrato)
##  Factor w/ 2 levels "5","6": 2 1 2 1 1 1 2 1 1 1 ...
# Revisar las categorías disponibles
levels(modelo_vivienda2$estrato)
## [1] "5" "6"

Preparación para la modelación:

Para la etapa de modelación se crea una copia de la base de la Vivienda 2 y se convierte estrato en una variable de tipo factor. De esta manera, R reconoce los estratos 5 y 6 como categorías y no como una variable cuantitativa continua.

Los niveles obtenidos son “5” y “6”. Al aparecer el estrato 5 como primer nivel, este será utilizado como categoría de referencia. En consecuencia, los coeficientes asociados a estrato6 representarán la diferencia esperada respecto a un apartamento de estrato 5, manteniendo constantes las demás características incluidas en cada modelo.

4.3.1 Modelo 1: variables en escala original

# Estimar el Modelo 1 de regresión lineal múltiple
# utilizando las variables en su escala original

modelo1_v2 <- lm(
  preciom ~
    areaconst +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda2
)

# Mostrar el resumen del Modelo 1
summary(modelo1_v2)
## 
## Call:
## lm(formula = preciom ~ areaconst + parqueaderos + banios + habitaciones + 
##     estrato, data = modelo_vivienda2)
## 
## Residuals:
##    Min     1Q Median     3Q    Max 
## -963.5  -53.8    0.4   44.5  892.0 
## 
## Coefficients:
##              Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)    4.7714    15.4451    0.31              0.75742    
## areaconst      1.1769     0.0663   17.76 < 0.0000000000000002 ***
## parqueaderos  82.7285     5.9078   14.00 < 0.0000000000000002 ***
## banios        47.5118     4.6283   10.27 < 0.0000000000000002 ***
## habitaciones -21.4776     5.7715   -3.72              0.00021 ***
## estrato6     138.0976     7.7332   17.86 < 0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 111 on 1431 degrees of freedom
## Multiple R-squared:  0.737,  Adjusted R-squared:  0.736 
## F-statistic:  801 on 5 and 1431 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 1:

El Modelo 1 utiliza el precio y todas las variables explicativas en su escala original. Para interpretar los coeficientes se considera el efecto de cada variable manteniendo constantes las demás características.

  • Área construida: presenta un coeficiente de 1,1769 y un valor p inferior a 0,001. Por cada metro cuadrado adicional, el precio esperado aumenta aproximadamente 1,18 millones de pesos, manteniendo constantes las demás variables.
  • Parqueaderos: el coeficiente es 82,7285 y resulta altamente significativo. Un parqueadero adicional se asocia, en promedio, con un incremento aproximado de 82,73 millones de pesos.
  • Baños: presenta un coeficiente de 47,5118, también significativo. Un baño adicional se relaciona con un aumento aproximado de 47,51 millones de pesos.
  • Habitaciones: el coeficiente es -21,4776 y resulta estadísticamente significativo. Manteniendo constantes área, parqueaderos, baños y estrato, una habitación adicional se asocia con una reducción aproximada de 21,48 millones de pesos. Este signo negativo puede parecer contraintuitivo en términos bivariados, pero debe interpretarse como un efecto condicionado: para apartamentos de igual área y demás características, un mayor número de habitaciones puede implicar una distribución interna distinta del espacio. Este resultado deberá revisarse junto con la multicolinealidad y la estabilidad de los modelos posteriores.
  • Estrato: el estrato 5 constituye la categoría de referencia. El coeficiente de estrato6 es 138,0976, indicando que un apartamento de estrato 6 presenta, en promedio, un precio aproximadamente 138,10 millones de pesos superior al de un apartamento de estrato 5 con características equivalentes.

El intercepto no resulta significativo y tiene poca interpretación práctica, dado que corresponde a un apartamento con valores cero en las variables cuantitativas.

El modelo presenta un R² de 0,737 y un R² ajustado de 0,736, mientras que la prueba F global es altamente significativa. Por tanto, el conjunto de predictores explica una proporción importante de la variabilidad del precio. Sin embargo, antes de considerar adecuada esta especificación es necesario revisar el comportamiento de los residuos y los supuestos del modelo.

Validación gráfica de los supuestos del Modelo 1:

# Revisar los gráficos básicos de diagnóstico
# del Modelo 1

par(mfrow = c(2, 2))

plot(modelo1_v2)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 1:

Los gráficos de diagnóstico muestran varios problemas en la especificación en escala original.

  • Residuos frente a valores ajustados: la dispersión aumenta claramente a medida que crecen los valores predichos. Los apartamentos de mayor precio presentan residuos mucho más variables y aparecen algunos casos alejados del conjunto principal. Este patrón sugiere heterocedasticidad.
  • Gráfico Q-Q: la parte central presenta cierta aproximación a la línea de referencia, pero existen desviaciones muy marcadas en las colas, especialmente asociadas con observaciones extremas. Esto indica un comportamiento alejado de la normalidad.
  • Scale-Location: se observa una tendencia creciente de la dispersión de los residuos estandarizados, reforzando la evidencia visual de varianza no constante.
  • Residuos frente a leverage: la mayoría de los registros presenta leverage bajo, pero aparecen algunas observaciones claramente separadas del resto, particularmente los casos de áreas excepcionalmente grandes. Estas observaciones podrían ejercer una influencia considerable sobre la estimación.

En conjunto, la revisión gráfica indica que el Modelo 1 presenta problemas importantes de normalidad y homocedasticidad y que algunos registros pueden tener una influencia elevada. Esto justifica evaluar la especificación logarítmica sugerida por el análisis exploratorio.

Pruebas formales de supuestos del Modelo 1:

# Prueba de normalidad de los residuos
shapiro.test(
  residuals(modelo1_v2)
)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo1_v2)
## W = 0.81, p-value <0.0000000000000002
# Prueba de homocedasticidad
lmtest::bptest(
  modelo1_v2
)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo1_v2
## BP = 441, df = 5, p-value <0.0000000000000002
# Prueba de independencia de los errores
lmtest::dwtest(
  modelo1_v2
)
## 
##  Durbin-Watson test
## 
## data:  modelo1_v2
## DW = 1.7, p-value = 0.000000007
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 1:

Las pruebas formales confirman los problemas observados en los gráficos. Se utiliza un nivel de significancia del 5 %.

  • Shapiro-Wilk: se obtiene W = 0,8112 con un valor p inferior a 0,001. Se rechaza la hipótesis de normalidad, por lo que los residuos no presentan un comportamiento compatible con una distribución normal.
  • Breusch-Pagan: el estadístico alcanza aproximadamente 441,04, con un valor p inferior a 0,001. Se rechaza la hipótesis de homocedasticidad y existe evidencia muy fuerte de varianza no constante.
  • Durbin-Watson: se obtiene DW = 1,7025 con un valor p inferior a 0,001, señalando autocorrelación positiva según el orden de las observaciones. Como se trata de datos de corte transversal y no de una serie temporal, este resultado debe interpretarse con cautela, pues el orden de los registros no necesariamente representa una secuencia sustantiva.

Por tanto, aunque el Modelo 1 es globalmente significativo y presenta un nivel de explicación importante, incumple de manera clara los supuestos de normalidad y homocedasticidad. Estos resultados respaldan la evaluación de una transformación de las variables.

Evaluación de la multicolinealidad del Modelo 1:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF)

car::vif(modelo1_v2)
##    areaconst parqueaderos       banios habitaciones      estrato 
##        1.826        1.921        2.458        1.481        1.494

Interpretación de la multicolinealidad del Modelo 1:

Los valores VIF se encuentran entre 1,481 y 2,458. El mayor corresponde a baños, seguido de parqueaderos y área construida.

Todos los valores se mantienen claramente por debajo del umbral de 5 utilizado como referencia para identificar problemas relevantes de multicolinealidad. Por tanto, no se evidencia una dependencia lineal excesiva entre los predictores.

Este resultado es importante para interpretar el coeficiente negativo de habitaciones: aunque existen correlaciones entre las características físicas de los apartamentos, el signo negativo no parece originarse en un problema severo de multicolinealidad. En consecuencia, las principales dificultades del Modelo 1 continúan asociadas al comportamiento de los residuos y a la influencia de observaciones extremas.

Análisis de observaciones influyentes del Modelo 1:

# Calcular la distancia de Cook para cada observación
# del Modelo 1

dist_cook_m1_v2 <- cooks.distance(modelo1_v2)

# Graficar las distancias de Cook
plot(
  dist_cook_m1_v2,
  type = "h",
  main = "Distancia de Cook - Modelo 1",
  xlab = "Observación",
  ylab = "Distancia de Cook"
)

# Agregar una línea de referencia con el criterio 4/n
abline(
  h = 4 / nrow(modelo_vivienda2),
  lty = 2
)

# Mostrar las 10 observaciones con mayor distancia de Cook
head(
  sort(dist_cook_m1_v2, decreasing = TRUE),
  10
)
##    1266     532     580     252     483     142     141     822     226     250 
## 5.49455 0.82815 0.19391 0.13092 0.10973 0.09783 0.09494 0.09125 0.08130 0.07699

Interpretación de las observaciones influyentes del Modelo 1:

La distancia de Cook evidencia una influencia especialmente elevada de algunas observaciones. Con 1.437 registros, el criterio de referencia \(4/n\) es aproximadamente 0,0028, por lo que numerosos casos pueden superar el umbral; sin embargo, la magnitud de Cook permite distinguir los registros realmente más preocupantes.

La observación 1266 presenta una distancia de Cook de 5,4946, un valor extraordinariamente alto y muy superior al resto. Corresponde a un apartamento de 932 m² con un precio de 299 millones de pesos, combinación muy alejada del patrón general del subconjunto. La observación 532, con 605 m² y un precio de 170 millones, también presenta una influencia muy alta, con Cook de 0,8282.

Otros registros, como las observaciones 580, 252, 483, 142 y 141, muestran valores de Cook menores pero todavía relevantes. En varios casos se trata de apartamentos con áreas o precios considerablemente superiores al comportamiento central.

Estos resultados muestran que el Modelo 1 es altamente sensible a algunas observaciones particulares. No obstante, de acuerdo con el criterio utilizado durante el análisis, los registros no deben eliminarse automáticamente. Primero se consideran potencialmente influyentes y se evalúa si una transformación reduce su efecto.

# Definir el umbral de referencia para la distancia de Cook
umbral_cook_m1_v2 <- 4 / nrow(modelo_vivienda2)

# Identificar todas las observaciones que superan el umbral
obs_influyentes_m1_v2 <- which(
  dist_cook_m1_v2 > umbral_cook_m1_v2
)

# Construir una tabla compacta con las observaciones influyentes
revision_influyentes_m1_v2 <- data.frame(
  Observacion = obs_influyentes_m1_v2,
  Precio = modelo_vivienda2$preciom[obs_influyentes_m1_v2],
  Area = modelo_vivienda2$areaconst[obs_influyentes_m1_v2],
  Parqueaderos = modelo_vivienda2$parqueaderos[obs_influyentes_m1_v2],
  Banios = modelo_vivienda2$banios[obs_influyentes_m1_v2],
  Habitaciones = modelo_vivienda2$habitaciones[obs_influyentes_m1_v2],
  Estrato = modelo_vivienda2$estrato[obs_influyentes_m1_v2],
  Distancia_Cook = round(
    dist_cook_m1_v2[obs_influyentes_m1_v2],
    5
  )
)

# Ordenar de mayor a menor influencia
revision_influyentes_m1_v2 <- revision_influyentes_m1_v2[
  order(
    revision_influyentes_m1_v2$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla
knitr::kable(
  revision_influyentes_m1_v2,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 1"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 1
Observacion Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
1266 1266 299 932.0 1 3 3 5 5.4946
532 532 170 605.0 1 2 2 5 0.8282
580 580 730 573.0 3 8 5 5 0.1939
252 252 1500 240.0 3 5 6 6 0.1309
483 483 650 600.0 2 4 5 5 0.1097
142 142 1561 399.0 3 4 3 6 0.0978
141 141 1750 342.0 3 5 4 6 0.0949
822 822 1750 290.0 3 4 3 6 0.0912
226 226 1700 290.0 3 4 3 6 0.0813
250 250 1600 345.0 3 6 3 6 0.0770
907 907 1580 296.0 4 4 3 6 0.0727
932 932 1590 310.0 3 4 3 6 0.0694
821 821 1600 290.0 3 5 4 6 0.0478
722 722 1250 251.0 4 5 4 5 0.0464
1098 1098 1250 213.0 3 4 3 5 0.0412
896 896 1350 212.0 3 5 3 6 0.0236
882 882 1200 211.0 2 3 3 6 0.0210
1425 1425 350 174.0 4 3 4 5 0.0162
236 236 1150 346.0 2 6 5 6 0.0161
405 405 690 486.0 2 4 4 5 0.0147
1042 1042 350 250.0 2 5 3 5 0.0130
906 906 1150 222.0 2 4 3 6 0.0129
61 61 350 270.0 3 3 4 5 0.0129
193 193 1240 222.0 3 5 4 6 0.0123
62 62 350 260.0 3 3 3 5 0.0121
126 126 250 94.0 3 2 3 6 0.0118
891 891 1100 220.0 4 4 4 6 0.0109
269 269 1280 346.0 4 6 5 6 0.0100
376 376 231 163.0 2 5 5 5 0.0088
1436 1436 870 245.0 1 4 3 6 0.0088
164 164 660 210.0 4 5 3 6 0.0082
234 234 1350 439.0 4 6 4 6 0.0079
946 946 840 185.0 2 2 2 6 0.0079
122 122 832 213.0 2 2 3 6 0.0074
1028 1028 350 258.0 2 4 5 5 0.0063
329 329 410 295.6 2 4 4 5 0.0060
749 749 450 267.0 3 3 3 5 0.0059
212 212 704 141.0 2 3 2 5 0.0059
825 825 1050 170.0 4 6 3 6 0.0055
305 305 930 145.0 2 3 3 6 0.0050
1032 1032 500 330.0 2 4 4 5 0.0050
698 698 340 236.0 2 4 3 5 0.0049
537 537 240 126.0 2 2 3 6 0.0046
235 235 1150 344.0 4 5 5 6 0.0046
119 119 700 138.0 2 5 4 5 0.0046
934 934 850 352.0 4 3 3 6 0.0044
544 544 380 175.0 3 4 3 5 0.0042
806 806 950 213.0 2 5 4 6 0.0042
853 853 245 50.3 2 1 1 6 0.0041
840 840 920 230.0 2 4 4 6 0.0040
265 265 760 200.0 2 2 3 6 0.0039
921 921 395 120.0 2 5 4 6 0.0038
1088 1088 530 256.0 3 5 5 5 0.0037
1437 1437 1000 189.0 3 5 4 6 0.0037
812 812 390 105.0 3 3 3 6 0.0037
399 399 270 95.0 2 3 4 6 0.0037
807 807 260 55.0 2 1 1 6 0.0036
310 310 320 115.0 2 3 2 6 0.0034
970 970 699 164.0 4 5 3 6 0.0034
123 123 677 108.0 2 2 3 6 0.0033
429 429 220 116.0 2 3 3 6 0.0033
494 494 230 80.0 2 2 3 6 0.0033
375 375 280 154.0 1 3 3 6 0.0032
517 517 290 100.0 2 3 4 6 0.0031
16 16 852 244.0 2 3 3 6 0.0031
1064 1064 850 222.0 2 3 3 6 0.0031
294 294 630 210.0 2 2 3 5 0.0031
771 771 450 120.0 2 5 3 6 0.0030
3 3 910 182.0 2 4 3 6 0.0030
340 340 520 320.0 2 4 4 5 0.0029
1034 1034 620 160.0 2 2 3 5 0.0029
651 651 387 145.0 3 4 3 5 0.0028
904 904 840 161.8 2 4 4 6 0.0028

Interpretación de la revisión de observaciones influyentes del Modelo 1:

La tabla permite revisar las características de las observaciones señaladas por la distancia de Cook. Los dos casos más extremos, 1266 y 532, combinan áreas excepcionalmente grandes con precios muy bajos en comparación con el resto de la base, lo que explica su fuerte capacidad para modificar la pendiente asociada con el área construida.

También aparecen apartamentos de precios elevados —por ejemplo, observaciones con valores entre 1.200 y 1.750 millones— y otros registros con áreas superiores a 300 o 400 m². Estas viviendas pueden ser reales, pero representan segmentos poco frecuentes dentro de un subconjunto cuya mediana de área es de apenas 103 m².

Debido al tamaño de la muestra, el umbral \(4/n\) es pequeño y señala un número amplio de observaciones. Por esta razón, la decisión no debe basarse únicamente en superar el umbral, sino también en la magnitud de Cook y en la plausibilidad del registro.

No se eliminan observaciones en esta etapa. En su lugar, se utiliza esta evidencia como una razón adicional para evaluar el Modelo 2 con transformaciones logarítmicas y comprobar si la influencia de los casos extremos disminuye.

4.3.2 Modelo 2: transformación logarítmica del precio y del área construida

El análisis exploratorio mostró que la relación log(precio) frente a log(área) alcanzó la mayor correlación entre las formas evaluadas (0,8000). Además, el Modelo 1 presentó problemas severos de normalidad, heterocedasticidad y una alta sensibilidad a algunas observaciones extremas. Por estas razones, se plantea el Modelo 2 utilizando logaritmos para el precio y el área construida, manteniendo las variables discretas en su escala original.

# Estimar el Modelo 2 de regresión lineal múltiple
# utilizando transformación logarítmica del precio
# y del área construida

modelo2_v2 <- lm(
  log(preciom) ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda2
)

# Mostrar el resumen del Modelo 2
summary(modelo2_v2)
## 
## Call:
## lm(formula = log(preciom) ~ log(areaconst) + parqueaderos + banios + 
##     habitaciones + estrato, data = modelo_vivienda2)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -1.4108 -0.1193  0.0132  0.1267  0.7489 
## 
## Coefficients:
##                Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)     3.08612    0.08744   35.29 < 0.0000000000000002 ***
## log(areaconst)  0.51173    0.02298   22.27 < 0.0000000000000002 ***
## parqueaderos    0.13568    0.01099   12.34 < 0.0000000000000002 ***
## banios          0.07476    0.00859    8.70 < 0.0000000000000002 ***
## habitaciones   -0.05122    0.01050   -4.88            0.0000012 ***
## estrato6        0.30090    0.01392   21.61 < 0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.199 on 1431 degrees of freedom
## Multiple R-squared:  0.805,  Adjusted R-squared:  0.805 
## F-statistic: 1.18e+03 on 5 and 1431 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 2:

El Modelo 2 conserva las mismas variables explicativas, pero utiliza log(preciom) como respuesta y log(areaconst) para representar el área. Esta forma funcional modifica la interpretación de los coeficientes y busca representar mejor la estructura observada en los datos.

  • Área construida: el coeficiente de log(areaconst) es 0,51173 y resulta altamente significativo. Al tratarse de un modelo log-log para estas dos variables, un aumento del 1 % en el área se asocia aproximadamente con un incremento del 0,512 % en el precio esperado, manteniendo las demás características constantes.
  • Parqueaderos: el coeficiente es 0,13568, con alta significancia. Un parqueadero adicional se asocia aproximadamente con un aumento del 14,5 % en el precio esperado.
  • Baños: presenta un coeficiente de 0,07476, también significativo. Un baño adicional se relaciona con un incremento aproximado del 7,8 % en el precio esperado.
  • Habitaciones: el coeficiente continúa siendo negativo, con -0,05122, y es estadísticamente significativo. Manteniendo constante el área y las demás variables, una habitación adicional se asocia aproximadamente con una reducción del 5,0 % en el precio esperado. La persistencia del signo en dos especificaciones sugiere que se trata de un efecto condicionado por la distribución del espacio y no de un resultado aislado del Modelo 1.
  • Estrato: estrato6 presenta un coeficiente de 0,30090. Frente al estrato 5, un apartamento de estrato 6 presenta un precio esperado aproximadamente 35,1 % superior, manteniendo constantes las demás características.

El Modelo 2 presenta un R² de 0,805 y un R² ajustado igualmente cercano a 0,805, y la prueba F global es altamente significativa. Debido a que la respuesta está en una escala diferente a la del Modelo 1, el R² no debe utilizarse como único criterio de comparación. La selección debe considerar principalmente el comportamiento de los residuos, los supuestos y la estabilidad frente a observaciones extremas.

Validación gráfica de los supuestos del Modelo 2:

# Revisar los gráficos básicos de diagnóstico
# del Modelo 2

par(mfrow = c(2, 2))

plot(modelo2_v2)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 2:

Los gráficos muestran una mejora clara respecto al Modelo 1, aunque todavía permanecen algunas desviaciones.

  • Residuos frente a valores ajustados: la dispersión es considerablemente más compacta y equilibrada que en la escala original. El efecto de embudo disminuye, aunque aún se observan algunos residuos alejados y cierta estructura en los extremos.
  • Gráfico Q-Q: la mayor parte de los puntos se aproxima mejor a la línea de referencia que en el Modelo 1. Sin embargo, persisten desviaciones en ambas colas, especialmente asociadas con observaciones particulares, por lo que la normalidad no parece cumplirse completamente.
  • Scale-Location: la variabilidad de los residuos resulta más estable que en el Modelo 1, pero todavía se observa un patrón que sugiere heterocedasticidad residual.
  • Residuos frente a leverage: la concentración principal se mantiene en leverage bajo. Las observaciones más extremas continúan presentes, aunque su influencia visual es sustancialmente menor que en la especificación original.

En conjunto, la transformación logarítmica produce una mejora importante en los diagnósticos, especialmente al reducir la dispersión extrema y la sensibilidad del modelo. No obstante, es necesario confirmar mediante las pruebas formales si los problemas fueron corregidos completamente.

Pruebas formales de supuestos del Modelo 2:

# Prueba de normalidad de los residuos
shapiro.test(
  residuals(modelo2_v2)
)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo2_v2)
## W = 0.98, p-value = 0.000000000000007
# Prueba de homocedasticidad
lmtest::bptest(
  modelo2_v2
)
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo2_v2
## BP = 198, df = 5, p-value <0.0000000000000002
# Prueba de independencia de los errores
lmtest::dwtest(
  modelo2_v2
)
## 
##  Durbin-Watson test
## 
## data:  modelo2_v2
## DW = 1.6, p-value <0.0000000000000002
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 2:

Las pruebas formales muestran que la transformación logarítmica mejora algunos indicadores, pero no corrige completamente los supuestos.

  • Shapiro-Wilk: el estadístico aumenta de 0,8112 en el Modelo 1 a aproximadamente 0,9757, lo que representa una mejora importante en la aproximación a la normalidad. Sin embargo, el valor p continúa siendo inferior a 0,001, por lo que se mantiene evidencia estadística de no normalidad.
  • Breusch-Pagan: el estadístico disminuye de aproximadamente 441 a 198,10, evidenciando una reducción considerable de la heterocedasticidad. No obstante, el valor p sigue siendo inferior a 0,001 y, por tanto, se rechaza la homocedasticidad.
  • Durbin-Watson: se obtiene aproximadamente 1,5594, con un valor p inferior a 0,001. La prueba continúa señalando autocorrelación positiva según el orden de los registros. Al tratarse de información transversal, esta conclusión se mantiene bajo la misma precaución señalada anteriormente.

Por tanto, el Modelo 2 mejora de forma clara frente al Modelo 1, pero todavía presenta desviaciones de normalidad y varianza constante. Dado que la actividad no exige corregir completamente los incumplimientos, estos resultados pueden acompañarse de recomendaciones como revisar los registros más influyentes y considerar métodos robustos o bootstrap para la inferencia.

Evaluación de la multicolinealidad del Modelo 2:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF)

car::vif(modelo2_v2)
## log(areaconst)   parqueaderos         banios   habitaciones        estrato 
##          2.744          2.076          2.642          1.532          1.512

Interpretación de la multicolinealidad del Modelo 2:

Los valores VIF del Modelo 2 se encuentran entre 1,512 y 2,744. Aunque el VIF máximo aumenta ligeramente respecto al Modelo 1, todos los valores siguen claramente por debajo del umbral de 5.

El mayor VIF corresponde a log(areaconst), seguido por baños y parqueaderos. Este resultado es coherente con las correlaciones observadas en la matriz exploratoria, donde el área presentaba asociaciones moderadas o altas con estas características.

Sin embargo, no existe evidencia de multicolinealidad problemática. Por tanto, la transformación logarítmica no genera una dependencia entre predictores que comprometa la estabilidad del modelo y este aspecto no constituye una razón para descartar la especificación.

Análisis de observaciones influyentes del Modelo 2:

# Calcular la distancia de Cook para cada observación
dist_cook_m2_v2 <- cooks.distance(modelo2_v2)

# Graficar las distancias de Cook
plot(
  dist_cook_m2_v2,
  type = "h",
  main = "Distancia de Cook - Modelo 2",
  xlab = "Observación",
  ylab = "Distancia de Cook"
)

# Agregar una línea de referencia
abline(
  h = 4 / nrow(modelo_vivienda2),
  lty = 2
)

# Identificar las observaciones con mayor distancia de Cook
head(
  sort(dist_cook_m2_v2, decreasing = TRUE),
  10
)
##     532    1266     580     252    1098     126     722    1052     376      62 
## 0.59463 0.41856 0.03375 0.03371 0.02010 0.01728 0.01689 0.01653 0.01637 0.01581

Interpretación de las observaciones influyentes del Modelo 2:

La transformación logarítmica reduce de manera muy importante la influencia de las observaciones extremas. La distancia de Cook máxima pasa de 5,4946 en el Modelo 1 a 0,5946 en el Modelo 2.

Las observaciones 532 y 1266 continúan siendo claramente las más influyentes, con valores de 0,5946 y 0,4186, respectivamente. Sin embargo, ambas presentan una reducción sustancial frente a la escala original. Las siguientes observaciones tienen distancias de Cook considerablemente menores: 580 y 252 se ubican alrededor de 0,034, mientras que el resto disminuye progresivamente.

Esta reducción muestra que el uso de logaritmos comprime la escala de los valores extremos y produce una estimación mucho menos sensible a los apartamentos de áreas excepcionales. Aun así, los casos 532 y 1266 siguen mereciendo revisión debido a las combinaciones inusuales entre área y precio.

# Definir el umbral de referencia para la distancia de Cook
umbral_cook_m2_v2 <- 4 / nrow(modelo_vivienda2)

# Identificar las observaciones que superan el umbral
obs_influyentes_m2_v2 <- which(
  dist_cook_m2_v2 > umbral_cook_m2_v2
)

# Construir una tabla compacta con las observaciones influyentes
revision_influyentes_m2_v2 <- data.frame(
  Observacion = obs_influyentes_m2_v2,
  Precio = modelo_vivienda2$preciom[obs_influyentes_m2_v2],
  Area = modelo_vivienda2$areaconst[obs_influyentes_m2_v2],
  Parqueaderos = modelo_vivienda2$parqueaderos[obs_influyentes_m2_v2],
  Banios = modelo_vivienda2$banios[obs_influyentes_m2_v2],
  Habitaciones = modelo_vivienda2$habitaciones[obs_influyentes_m2_v2],
  Estrato = modelo_vivienda2$estrato[obs_influyentes_m2_v2],
  Distancia_Cook = round(
    dist_cook_m2_v2[obs_influyentes_m2_v2],
    5
  )
)

# Ordenar de mayor a menor influencia
revision_influyentes_m2_v2 <- revision_influyentes_m2_v2[
  order(
    revision_influyentes_m2_v2$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla
knitr::kable(
  revision_influyentes_m2_v2,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 2"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 2
Observacion Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
532 532 170 605.00 1 2 2 5 0.5946
1266 1266 299 932.00 1 3 3 5 0.4186
580 580 730 573.00 3 8 5 5 0.0338
252 252 1500 240.00 3 5 6 6 0.0337
1098 1098 1250 213.00 3 4 3 5 0.0201
126 126 250 94.00 3 2 3 6 0.0173
722 722 1250 251.00 4 5 4 5 0.0169
1052 1052 140 120.00 1 2 2 5 0.0165
376 376 231 163.00 2 5 5 5 0.0164
62 62 350 260.00 3 3 3 5 0.0158
1042 1042 350 250.00 2 5 3 5 0.0158
1425 1425 350 174.00 4 3 4 5 0.0152
61 61 350 270.00 3 3 4 5 0.0147
822 822 1750 290.00 3 4 3 6 0.0128
226 226 1700 290.00 3 4 3 6 0.0117
882 882 1200 211.00 2 3 3 6 0.0106
537 537 240 126.00 2 2 3 6 0.0104
932 932 1590 310.00 3 4 3 6 0.0091
430 430 268 145.00 1 2 3 6 0.0091
212 212 704 141.00 2 3 2 5 0.0089
375 375 280 154.00 1 3 3 6 0.0087
141 141 1750 342.00 3 5 4 6 0.0082
698 698 340 236.00 2 4 3 5 0.0079
1051 1051 139 120.00 1 2 3 5 0.0078
119 119 700 138.00 2 5 4 5 0.0076
204 204 180 73.00 1 2 3 6 0.0074
907 907 1580 296.00 4 4 3 6 0.0074
164 164 660 210.00 4 5 3 6 0.0073
142 142 1561 399.00 3 4 3 6 0.0070
1028 1028 350 258.00 2 4 5 5 0.0069
429 429 220 116.00 2 3 3 6 0.0066
821 821 1600 290.00 3 5 4 6 0.0063
946 946 840 185.00 2 2 2 6 0.0063
1034 1034 620 160.00 2 2 3 5 0.0060
494 494 230 80.00 2 2 3 6 0.0059
294 294 630 210.00 2 2 3 5 0.0057
934 934 850 352.00 4 3 3 6 0.0055
122 122 832 213.00 2 2 3 6 0.0054
906 906 1150 222.00 2 4 3 6 0.0054
743 743 206 109.00 2 4 4 5 0.0053
483 483 650 600.00 2 4 5 5 0.0053
749 749 450 267.00 3 3 3 5 0.0053
787 787 600 129.00 1 3 3 5 0.0053
896 896 1350 212.00 3 5 3 6 0.0052
399 399 270 95.00 2 3 4 6 0.0052
1029 1029 240 139.84 2 4 3 5 0.0052
123 123 677 108.00 2 2 3 6 0.0051
329 329 410 295.55 2 4 4 5 0.0051
250 250 1600 345.00 3 6 3 6 0.0050
1436 1436 870 245.00 1 4 3 6 0.0049
683 683 206 80.83 2 4 4 5 0.0048
502 502 245 98.00 2 3 3 6 0.0046
571 571 300 209.00 1 4 5 5 0.0046
310 310 320 115.00 2 3 2 6 0.0041
935 935 710 151.00 3 5 3 5 0.0040
653 653 450 110.00 2 4 5 5 0.0040
305 305 930 145.00 2 3 3 6 0.0039
517 517 290 100.00 2 3 4 6 0.0038
304 304 950 330.00 4 6 4 6 0.0038
544 544 380 175.00 3 4 3 5 0.0037
574 574 280 126.00 2 3 3 6 0.0035
955 955 980 348.00 4 5 3 6 0.0035
1085 1085 670 191.00 2 3 3 5 0.0035
353 353 130 45.00 1 2 2 5 0.0034
325 325 321 217.04 1 4 5 5 0.0033
265 265 760 200.00 2 2 3 6 0.0033
720 720 450 195.00 1 2 4 5 0.0033
1426 1426 165 55.00 1 2 1 5 0.0033
288 288 697 139.00 2 2 2 6 0.0032
570 570 199 109.00 1 2 2 5 0.0032
21 21 160 82.00 1 3 4 5 0.0031
193 193 1240 222.00 3 5 4 6 0.0031
58 58 185 121.00 1 2 3 5 0.0030
1428 1428 179 110.00 1 3 4 5 0.0030
459 459 300 155.00 1 5 4 5 0.0030
443 443 255 100.00 1 2 3 6 0.0030
848 848 600 145.00 2 5 3 5 0.0029
215 215 673 132.00 2 2 2 6 0.0029
4 4 310 166.00 2 4 3 5 0.0029
611 611 355 85.00 2 2 4 5 0.0028
281 281 500 110.00 2 2 3 5 0.0028
239 239 1150 464.00 4 6 5 6 0.0028
921 921 395 120.00 2 5 4 6 0.0028

Interpretación de la revisión de observaciones influyentes del Modelo 2:

La revisión detallada confirma que las observaciones de mayor influencia corresponden principalmente a apartamentos con combinaciones poco frecuentes de precio y área. Los casos 532 (170 millones y 605 m²) y 1266 (299 millones y 932 m²) continúan destacándose frente al resto del mercado analizado.

También aparecen apartamentos de alto valor y algunos registros con áreas considerablemente superiores a la mediana del subconjunto. Sin embargo, las distancias de Cook de estos casos son mucho menores que las de las dos observaciones principales.

El Modelo 2, por tanto, no elimina la presencia de observaciones influyentes, pero reduce de manera sustancial su impacto respecto al Modelo 1. La evidencia no permite concluir automáticamente que estos registros sean erróneos; si se dispusiera de la fuente original, sería recomendable verificar específicamente las observaciones 532 y 1266 antes de una aplicación operativa del modelo.

Dado que todavía persisten heterocedasticidad y no normalidad, se evalúa un tercer modelo mediante Box-Cox para determinar si una transformación estimada directamente a partir de los datos ofrece una mejora adicional.

4.3.3 Modelo 3: transformación Box-Cox del precio

Aunque el Modelo 2 mejora de manera importante frente al Modelo 1, las pruebas formales continúan evidenciando no normalidad y heterocedasticidad. Por esta razón, se evalúa una tercera y última especificación utilizando Box-Cox sobre el precio, conservando log(areaconst) y las demás variables explicativas en la misma forma del Modelo 2. El propósito es determinar si una transformación estimada a partir de los datos produce una mejora adicional suficiente para justificar una mayor complejidad.

Estimación de la transformación Box-Cox:

# Ajustar un modelo base conservando la transformación del área
# encontrada durante el análisis exploratorio.
# La variable respuesta se mantiene inicialmente en su escala original
# para estimar la transformación Box-Cox.

modelo_base_boxcox_v2 <- lm(
  preciom ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda2
)

# Evaluar diferentes valores de lambda mediante Box-Cox
boxcox_modelo3_v2 <- MASS::boxcox(
  modelo_base_boxcox_v2,
  lambda = seq(-2, 2, by = 0.1)
)

# Identificar el valor de lambda que maximiza
# la log-verosimilitud
lambda_modelo3_v2 <- boxcox_modelo3_v2$x[
  which.max(boxcox_modelo3_v2$y)
]

# Mostrar el lambda seleccionado
lambda_modelo3_v2
## [1] -0.1414

Interpretación de la transformación Box-Cox:

La transformación Box-Cox selecciona un valor óptimo de \(\lambda=-0,1414\) para el precio.

Este resultado es especialmente informativo porque un valor de lambda cercano a cero corresponde a una transformación muy próxima al logaritmo. Por tanto, Box-Cox confirma que la transformación logarítmica utilizada en el Modelo 2 ya se encontraba cerca de la forma funcional sugerida por los datos.

El valor negativo implica una transformación ligeramente más fuerte que el logaritmo para comprimir los precios elevados. Sin embargo, al encontrarse relativamente próximo a cero, no se espera una diferencia radical entre los Modelos 2 y 3. La utilidad del Modelo 3 dependerá entonces de si esta modificación logra una mejora clara en los diagnósticos de los residuos.

# Crear una copia de la base para aplicar
# la transformación Box-Cox al precio
modelo_vivienda2_m3 <- modelo_vivienda2

# Aplicar la transformación Box-Cox al precio.
# Cuando lambda es cero o numéricamente muy cercano a cero,
# se utiliza la transformación logarítmica.
if (abs(lambda_modelo3_v2) < 1e-8) {
  
  modelo_vivienda2_m3$precio_boxcox <- log(
    modelo_vivienda2_m3$preciom
  )
  
} else {
  
  modelo_vivienda2_m3$precio_boxcox <- (
    modelo_vivienda2_m3$preciom^lambda_modelo3_v2 - 1
  ) / lambda_modelo3_v2
  
}

# Estimar el Modelo 3 conservando la misma estructura
# de variables explicativas utilizada en el Modelo 2
modelo3_v2 <- lm(
  precio_boxcox ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda2_m3
)

# Mostrar el resumen del Modelo 3
summary(modelo3_v2)
## 
## Call:
## lm(formula = precio_boxcox ~ log(areaconst) + parqueaderos + 
##     banios + habitaciones + estrato, data = modelo_vivienda2_m3)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.6210 -0.0517  0.0069  0.0566  0.2930 
## 
## Coefficients:
##                Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)     2.78877    0.03795   73.49 < 0.0000000000000002 ***
## log(areaconst)  0.21936    0.00997   21.99 < 0.0000000000000002 ***
## parqueaderos    0.05718    0.00477   11.98 < 0.0000000000000002 ***
## banios          0.03111    0.00373    8.35 < 0.0000000000000002 ***
## habitaciones   -0.02065    0.00456   -4.53            0.0000064 ***
## estrato6        0.12920    0.00604   21.38 < 0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.0863 on 1431 degrees of freedom
## Multiple R-squared:   0.8,   Adjusted R-squared:  0.799 
## F-statistic: 1.14e+03 on 5 and 1431 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 3:

El Modelo 3 utiliza el precio transformado mediante Box-Cox con \(\lambda=-0,1414\), manteniendo log(areaconst) y las demás variables en la misma estructura del Modelo 2.

Todos los predictores continúan siendo estadísticamente significativos. log(areaconst), parqueaderos, baños y estrato 6 mantienen coeficientes positivos, mientras que habitaciones conserva un coeficiente negativo. La permanencia de los signos y de la significancia muestra que la estructura sustantiva de las relaciones es estable entre los Modelos 2 y 3.

Debido a que la respuesta se encuentra en una escala Box-Cox, los coeficientes no se interpretan directamente en millones de pesos ni como porcentajes. Su principal utilidad en esta etapa consiste en evaluar si la nueva transformación mejora los supuestos.

El modelo presenta un R² de 0,800 y un R² ajustado de 0,799, con una prueba F global altamente significativa. No obstante, este R² no debe compararse directamente con el del Modelo 2 como criterio único, ya que las respuestas están expresadas mediante transformaciones diferentes.

Validación gráfica de los supuestos del Modelo 3:

# Revisar los gráficos básicos de diagnóstico
# del Modelo 3

par(mfrow = c(2, 2))

plot(modelo3_v2)

# Restablecer la ventana gráfica
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 3:

Los gráficos de diagnóstico del Modelo 3 presentan un comportamiento muy similar al observado en el Modelo 2.

La dispersión de los residuos es mucho menor que en el Modelo 1 y se mantiene relativamente concentrada alrededor de cero. El gráfico Q-Q muestra una aproximación razonable en la zona central, pero persisten desviaciones visibles en las colas. Por su parte, el gráfico Scale-Location continúa mostrando una estructura sistemática en la variabilidad de los residuos, por lo que no se aprecia una corrección completa de la heterocedasticidad.

En el gráfico de residuos frente a leverage siguen destacándose algunas observaciones con influencia potencial, particularmente los registros que ya habían sido señalados en los modelos anteriores.

En términos visuales, Box-Cox no produce una mejora radical respecto al Modelo 2. La especificación continúa siendo claramente mejor que el Modelo 1 en escala original, pero las diferencias entre los Modelos 2 y 3 son relativamente pequeñas.

Pruebas formales de supuestos del Modelo 3:

# Prueba de normalidad de los residuos
shapiro_m3_v2 <- shapiro.test(
  residuals(modelo3_v2)
)

shapiro_m3_v2
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo3_v2)
## W = 0.97, p-value = 0.000000000000002
# Prueba de homocedasticidad
bp_m3_v2 <- lmtest::bptest(
  modelo3_v2
)

bp_m3_v2
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo3_v2
## BP = 170, df = 5, p-value <0.0000000000000002
# Prueba de independencia de los errores
dw_m3_v2 <- lmtest::dwtest(
  modelo3_v2
)

dw_m3_v2
## 
##  Durbin-Watson test
## 
## data:  modelo3_v2
## DW = 1.6, p-value <0.0000000000000002
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 3:

Las pruebas formales confirman que el Modelo 3 tampoco logra satisfacer completamente los supuestos.

  • Shapiro-Wilk: se obtiene aproximadamente W = 0,9739, con un valor p inferior a 0,001. Por tanto, continúa existiendo evidencia de no normalidad. Además, el estadístico es ligeramente inferior al obtenido en el Modelo 2 (0,9757), por lo que Box-Cox no mejora este aspecto.
  • Breusch-Pagan: el estadístico disminuye a aproximadamente 170,18, frente a 198,10 del Modelo 2. Existe, por tanto, una mejora adicional en la heterocedasticidad; sin embargo, el valor p sigue siendo inferior a 0,001 y el supuesto de homocedasticidad continúa incumpliéndose.
  • Durbin-Watson: el estadístico es aproximadamente 1,5501, también con valor p inferior a 0,001. No se observa una mejora frente al Modelo 2 y se mantiene la misma precaución debido al carácter transversal de los datos.

En consecuencia, el Modelo 3 reduce algo más la heterocedasticidad, pero no logra corregirla y tampoco mejora la normalidad ni la independencia. Esto indica que la transformación Box-Cox aporta una mejora parcial, pero no decisiva frente a la transformación logarítmica.

Evaluación de la multicolinealidad del Modelo 3:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF)

vif_m3_v2 <- car::vif(modelo3_v2)

vif_m3_v2
## log(areaconst)   parqueaderos         banios   habitaciones        estrato 
##          2.744          2.076          2.642          1.532          1.512

Interpretación de la multicolinealidad del Modelo 3:

Los valores VIF del Modelo 3 son exactamente los mismos que en el Modelo 2: el máximo es aproximadamente 2,744 y todos permanecen por debajo de 5.

Este resultado es esperable, ya que Box-Cox modifica únicamente la variable respuesta y no altera la estructura de los predictores. En consecuencia, no se evidencia un problema importante de multicolinealidad y este diagnóstico se mantiene estable entre ambos modelos transformados.

Análisis de observaciones influyentes del Modelo 3:

# Calcular la distancia de Cook para cada observación
dist_cook_m3_v2 <- cooks.distance(modelo3_v2)

# Definir el umbral de referencia
umbral_cook_m3_v2 <- 4 / nrow(modelo_vivienda2_m3)

# Graficar las distancias de Cook
plot(
  dist_cook_m3_v2,
  type = "h",
  main = "Distancia de Cook - Modelo 3",
  xlab = "Observación",
  ylab = "Distancia de Cook"
)

# Agregar la línea de referencia
abline(
  h = umbral_cook_m3_v2,
  lty = 2
)

# Mostrar las 10 observaciones
# con mayor distancia de Cook
head(
  sort(dist_cook_m3_v2, decreasing = TRUE),
  10
)
##     532    1266     580     252    1052     126    1098     376      62    1042 
## 0.61169 0.40163 0.03300 0.02335 0.01897 0.01680 0.01633 0.01628 0.01442 0.01424

Interpretación de las observaciones influyentes del Modelo 3:

Las mayores distancias de Cook corresponden nuevamente a las observaciones 532 y 1266, con valores de 0,6117 y 0,4016, respectivamente.

Aunque estas magnitudes son muy inferiores a la distancia máxima del Modelo 1, el valor máximo del Modelo 3 es ligeramente superior al observado en el Modelo 2 (0,5946). Por tanto, Box-Cox no produce una mejora adicional en la sensibilidad frente a las observaciones más influyentes.

Las siguientes distancias de Cook disminuyen rápidamente: la observación 580 presenta aproximadamente 0,033 y la 252 cerca de 0,023. Esto confirma que la influencia se concentra principalmente en unos pocos registros con características muy particulares.

# Identificar las observaciones que superan el umbral
obs_influyentes_m3_v2 <- which(
  dist_cook_m3_v2 > umbral_cook_m3_v2
)

# Construir la tabla de revisión
revision_influyentes_m3_v2 <- data.frame(
  Observacion = obs_influyentes_m3_v2,
  Precio = modelo_vivienda2_m3$preciom[
    obs_influyentes_m3_v2
  ],
  Area = modelo_vivienda2_m3$areaconst[
    obs_influyentes_m3_v2
  ],
  Parqueaderos = modelo_vivienda2_m3$parqueaderos[
    obs_influyentes_m3_v2
  ],
  Banios = modelo_vivienda2_m3$banios[
    obs_influyentes_m3_v2
  ],
  Habitaciones = modelo_vivienda2_m3$habitaciones[
    obs_influyentes_m3_v2
  ],
  Estrato = modelo_vivienda2_m3$estrato[
    obs_influyentes_m3_v2
  ],
  Distancia_Cook = round(
    dist_cook_m3_v2[obs_influyentes_m3_v2],
    5
  )
)

# Ordenar de mayor a menor influencia
revision_influyentes_m3_v2 <- revision_influyentes_m3_v2[
  order(
    revision_influyentes_m3_v2$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla
knitr::kable(
  revision_influyentes_m3_v2,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 3"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 3
Observacion Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
532 532 170 605.00 1 2 2 5 0.6117
1266 1266 299 932.00 1 3 3 5 0.4016
580 580 730 573.00 3 8 5 5 0.0330
252 252 1500 240.00 3 5 6 6 0.0233
1052 1052 140 120.00 1 2 2 5 0.0190
126 126 250 94.00 3 2 3 6 0.0168
1098 1098 1250 213.00 3 4 3 5 0.0163
376 376 231 163.00 2 5 5 5 0.0163
62 62 350 260.00 3 3 3 5 0.0144
1042 1042 350 250.00 2 5 3 5 0.0142
1425 1425 350 174.00 4 3 4 5 0.0137
61 61 350 270.00 3 3 4 5 0.0135
722 722 1250 251.00 4 5 4 5 0.0126
537 537 240 126.00 2 2 3 6 0.0103
1051 1051 139 120.00 1 2 3 5 0.0092
430 430 268 145.00 1 2 3 6 0.0088
212 212 704 141.00 2 3 2 5 0.0086
375 375 280 154.00 1 3 3 6 0.0083
882 882 1200 211.00 2 3 3 6 0.0083
204 204 180 73.00 1 2 3 6 0.0082
822 822 1750 290.00 3 4 3 6 0.0081
119 119 700 138.00 2 5 4 5 0.0074
226 226 1700 290.00 3 4 3 6 0.0073
698 698 340 236.00 2 4 3 5 0.0071
164 164 660 210.00 4 5 3 6 0.0069
429 429 220 116.00 2 3 3 6 0.0065
1028 1028 350 258.00 2 4 5 5 0.0063
934 934 850 352.00 4 3 3 6 0.0061
494 494 230 80.00 2 2 3 6 0.0059
1034 1034 620 160.00 2 2 3 5 0.0059
294 294 630 210.00 2 2 3 5 0.0056
743 743 206 109.00 2 4 4 5 0.0055
932 932 1590 310.00 3 4 3 6 0.0055
946 946 840 185.00 2 2 2 6 0.0055
483 483 650 600.00 2 4 5 5 0.0054
787 787 600 129.00 1 3 3 5 0.0052
683 683 206 80.83 2 4 4 5 0.0051
1029 1029 240 139.84 2 4 3 5 0.0050
353 353 130 45.00 1 2 2 5 0.0050
399 399 270 95.00 2 3 4 6 0.0050
123 123 677 108.00 2 2 3 6 0.0049
141 141 1750 342.00 3 5 4 6 0.0047
122 122 832 213.00 2 2 3 6 0.0046
749 749 450 267.00 3 3 3 5 0.0046
329 329 410 295.55 2 4 4 5 0.0045
502 502 245 98.00 2 3 3 6 0.0045
304 304 950 330.00 4 6 4 6 0.0044
571 571 300 209.00 1 4 5 5 0.0043
239 239 1150 464.00 4 6 5 6 0.0043
955 955 980 348.00 4 5 3 6 0.0042
653 653 450 110.00 2 4 5 5 0.0042
1426 1426 165 55.00 1 2 1 5 0.0042
906 906 1150 222.00 2 4 3 6 0.0041
1436 1436 870 245.00 1 4 3 6 0.0040
935 935 710 151.00 3 5 3 5 0.0040
821 821 1600 290.00 3 5 4 6 0.0039
907 907 1580 296.00 4 4 3 6 0.0039
21 21 160 82.00 1 3 4 5 0.0038
310 310 320 115.00 2 3 2 6 0.0037
517 517 290 100.00 2 3 4 6 0.0036
896 896 1350 212.00 3 5 3 6 0.0036
720 720 450 195.00 1 2 4 5 0.0035
142 142 1561 399.00 3 4 3 6 0.0034
570 570 199 109.00 1 2 2 5 0.0034
1428 1428 179 110.00 1 3 4 5 0.0034
1085 1085 670 191.00 2 3 3 5 0.0034
58 58 185 121.00 1 2 3 5 0.0034
305 305 930 145.00 2 3 3 6 0.0034
574 574 280 126.00 2 3 3 6 0.0034
954 954 980 250.00 4 7 4 6 0.0033
544 544 380 175.00 3 4 3 5 0.0032
1224 1224 130 60.00 1 2 3 5 0.0031
288 288 697 139.00 2 2 2 6 0.0031
848 848 600 145.00 2 5 3 5 0.0031
325 325 321 217.04 1 4 5 5 0.0031
611 611 355 85.00 2 2 4 5 0.0030
443 443 255 100.00 1 2 3 6 0.0029
265 265 760 200.00 2 2 3 6 0.0029
281 281 500 110.00 2 2 3 5 0.0029
215 215 673 132.00 2 2 2 6 0.0028

Interpretación de la revisión de observaciones influyentes del Modelo 3:

La tabla confirma que los registros de mayor influencia son prácticamente los mismos identificados en el Modelo 2. Las observaciones 532 y 1266 continúan asociadas con áreas extremadamente grandes y precios relativamente bajos, mientras que otros casos representan apartamentos de precios elevados, áreas poco frecuentes o combinaciones particulares de características.

La transformación Box-Cox mantiene una reducción muy importante de la influencia respecto al Modelo 1, pero no mejora el comportamiento obtenido con el Modelo 2. De hecho, la distancia de Cook máxima aumenta ligeramente de 0,5946 a 0,6117.

Por esta razón, no se encuentra evidencia suficiente para eliminar observaciones ni para preferir el Modelo 3 únicamente por su manejo de puntos influyentes. La comparación final deberá considerar conjuntamente normalidad, heterocedasticidad, multicolinealidad, influencia y simplicidad de interpretación.

4.3.4 Modelo 4: análisis de sensibilidad sin las observaciones de mayor influencia

Los Modelos 2 y 3 redujeron de forma importante la influencia observada en el modelo en escala original, pero las observaciones 532 y 1266 continuaron destacándose con distancias de Cook considerablemente superiores a las del resto de registros. Además, las pruebas de normalidad y homocedasticidad siguieron mostrando incumplimientos.

Por esta razón, se plantea un cuarto modelo como análisis de sensibilidad. No se asume que las observaciones 532 y 1266 sean errores ni se eliminan de la base original. Únicamente se excluyen temporalmente de una copia de la base de modelación para evaluar cuánto inciden sobre los residuos, la heterocedasticidad y la estabilidad del modelo. Se conserva la misma forma funcional del Modelo 2, debido a que la transformación logarítmica produjo una mejora sustancial y Box-Cox no mostró una ventaja global clara.

# Crear una referencia explícita al número de observación
# utilizado en los diagnósticos de los modelos anteriores.
revision_modelo4_v2 <- modelo_vivienda2 |>
  dplyr::mutate(
    Observacion_modelo = dplyr::row_number()
  ) |>
  dplyr::filter(
    Observacion_modelo %in% c(532, 1266)
  ) |>
  dplyr::select(
    Observacion_modelo,
    id,
    preciom,
    areaconst,
    parqueaderos,
    banios,
    habitaciones,
    estrato
  )

# Mostrar las dos observaciones que se excluirán
# únicamente para el análisis de sensibilidad.
knitr::kable(
  revision_modelo4_v2,
  col.names = c(
    "Observación",
    "ID original",
    "Precio (millones)",
    "Área (m²)",
    "Parqueaderos",
    "Baños",
    "Habitaciones",
    "Estrato"
  ),
  caption = "Observaciones evaluadas en el análisis de sensibilidad del Modelo 4"
)
Observaciones evaluadas en el análisis de sensibilidad del Modelo 4
Observación ID original Precio (millones) Área (m²) Parqueaderos Baños Habitaciones Estrato
532 6472 170 605 1 2 2 5
1266 6121 299 932 1 3 3 5

Interpretación de la revisión previa al Modelo 4:

Las observaciones revisadas corresponden efectivamente a las posiciones 532 y 1266 identificadas previamente mediante la distancia de Cook. La observación 532 corresponde al ID original 6472, con un precio de 170 millones de pesos y un área de 605 m², mientras que la observación 1266 corresponde al ID 6121, con un precio de 299 millones y un área de 932 m². Ambas pertenecen al estrato 5 y presentan una combinación poco frecuente de áreas extremadamente grandes con precios relativamente bajos frente al comportamiento general del subconjunto.

Estas características explican su alta influencia sobre las estimaciones anteriores, especialmente sobre la relación entre área y precio. Sin embargo, no existe evidencia suficiente para afirmar que se trate de errores de registro. Por esta razón, las observaciones no se eliminan de la base original y su exclusión se realiza únicamente de manera temporal para evaluar la sensibilidad del modelo.

# Crear una copia de la base utilizada en el Modelo 2
# y conservar el número de observación para mantener
# trazabilidad con los diagnósticos anteriores.
modelo_vivienda2_m4 <- modelo_vivienda2 |>
  dplyr::mutate(
    Observacion_modelo = dplyr::row_number()
  ) |>
  dplyr::filter(
    !Observacion_modelo %in% c(532, 1266)
  )

# Verificar el número de observaciones que conserva
# el análisis de sensibilidad.
dim(modelo_vivienda2_m4)
## [1] 1435   15
# Estimar el Modelo 4 con la misma forma funcional
# del Modelo 2, pero excluyendo temporalmente las
# dos observaciones de mayor influencia.
modelo4_v2 <- lm(
  log(preciom) ~
    log(areaconst) +
    parqueaderos +
    banios +
    habitaciones +
    estrato,
  data = modelo_vivienda2_m4
)

# Mostrar el resumen del modelo.
summary(modelo4_v2)
## 
## Call:
## lm(formula = log(preciom) ~ log(areaconst) + parqueaderos + banios + 
##     habitaciones + estrato, data = modelo_vivienda2_m4)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.8251 -0.1225  0.0163  0.1281  0.7239 
## 
## Coefficients:
##                Estimate Std. Error t value             Pr(>|t|)    
## (Intercept)     2.79620    0.08968   31.18 < 0.0000000000000002 ***
## log(areaconst)  0.59589    0.02384   25.00 < 0.0000000000000002 ***
## parqueaderos    0.11659    0.01082   10.78 < 0.0000000000000002 ***
## banios          0.06463    0.00838    7.72    0.000000000000023 ***
## habitaciones   -0.06406    0.01025   -6.25    0.000000000537420 ***
## estrato6        0.29252    0.01350   21.66 < 0.0000000000000002 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.192 on 1429 degrees of freedom
## Multiple R-squared:  0.817,  Adjusted R-squared:  0.817 
## F-statistic: 1.28e+03 on 5 and 1429 DF,  p-value: <0.0000000000000002

Interpretación del Modelo 4:

El Modelo 4 conserva 1.435 observaciones y mantiene la misma forma funcional del Modelo 2: log(precio) como variable respuesta, log(área) para el área construida y las demás variables explicativas en su escala original.

Los signos y la significancia de los coeficientes se mantienen estables respecto al Modelo 2. log(areaconst), parqueaderos, baños y estrato 6 continúan presentando asociaciones positivas y altamente significativas con el precio, mientras que habitaciones conserva un coeficiente negativo y significativo.

  • Área construida: el coeficiente de log(areaconst) es 0,5959. Por tanto, un aumento del 1 % en el área se asocia aproximadamente con un incremento del 0,596 % en el precio esperado, manteniendo constantes las demás variables.
  • Parqueaderos: el coeficiente es 0,1166, equivalente aproximadamente a un aumento del 12,4 % en el precio esperado por cada parqueadero adicional.
  • Baños: el coeficiente de 0,0646 representa aproximadamente un incremento del 6,7 % por cada baño adicional.
  • Habitaciones: el coeficiente es -0,0641, lo que corresponde aproximadamente a una disminución del 6,2 % en el precio esperado por cada habitación adicional, manteniendo constante el área y las demás características. La persistencia de este signo en los modelos transformados refuerza su interpretación como un efecto condicionado por la distribución interna del espacio.
  • Estrato 6: frente al estrato 5, el coeficiente de 0,2925 representa un precio esperado aproximadamente 34,0 % superior, manteniendo constantes las demás características.

El modelo alcanza un R² de 0,817 y un R² ajustado igualmente de 0,817. Este ajuste es ligeramente superior al del Modelo 2, aunque la comparación debe realizarse con cautela porque el Modelo 4 utiliza dos observaciones menos. Lo más relevante es que la estructura general de los coeficientes permanece estable, lo que indica que las dos observaciones influyentes afectaban principalmente los diagnósticos y la magnitud de algunos parámetros, pero no generaban por sí solas las relaciones fundamentales identificadas en el modelo.

Validación gráfica de los supuestos del Modelo 4:

# Revisar los gráficos básicos de diagnóstico
# del Modelo 4.
par(mfrow = c(2, 2))
plot(modelo4_v2)

# Restablecer la ventana gráfica.
par(mfrow = c(1, 1))

Interpretación gráfica de los supuestos del Modelo 4:

Los gráficos del Modelo 4 muestran una mejora importante respecto a la especificación original y una reducción de la influencia extrema observada en los Modelos 2 y 3.

  • Residuos frente a valores ajustados: los residuos se concentran de forma más equilibrada alrededor de cero y ya no aparecen los dos casos que dominaban claramente el ajuste. Sin embargo, la línea suavizada conserva una ligera curvatura y la dispersión no es completamente uniforme a lo largo de los valores ajustados.
  • Gráfico Q-Q: la mayor parte de los residuos se aproxima de forma razonable a la línea de referencia, especialmente en la zona central. Persisten desviaciones en las colas, por lo que la aproximación a la normalidad mejora, pero no es perfecta.
  • Scale-Location: la línea suavizada presenta una tendencia ascendente en los valores ajustados más altos, indicando que la variabilidad de los residuos todavía tiende a aumentar en determinados segmentos del mercado.
  • Residuos frente a leverage: desaparecen los niveles de influencia extraordinarios observados anteriormente. Se identifican algunos casos con leverage relativamente mayor, pero ninguno presenta un comportamiento comparable con las observaciones 532 y 1266 de los modelos anteriores.

En conjunto, el análisis gráfico confirma que retirar temporalmente las dos observaciones más influyentes mejora de manera considerable la estabilidad del ajuste, aunque todavía se conserva un patrón de varianza no constante que requiere una revisión más específica.

Pruebas formales de supuestos del Modelo 4:

# Prueba de normalidad de los residuos.
shapiro_m4_v2 <- shapiro.test(
  residuals(modelo4_v2)
)
shapiro_m4_v2
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals(modelo4_v2)
## W = 0.99, p-value = 0.000000003
# Prueba de homocedasticidad.
bp_m4_v2 <- lmtest::bptest(
  modelo4_v2
)
bp_m4_v2
## 
##  studentized Breusch-Pagan test
## 
## data:  modelo4_v2
## BP = 84, df = 5, p-value <0.0000000000000002
# Prueba de independencia de los errores.
# Al tratarse de datos de corte transversal,
# el resultado debe interpretarse con cautela.
dw_m4_v2 <- lmtest::dwtest(
  modelo4_v2
)
dw_m4_v2
## 
##  Durbin-Watson test
## 
## data:  modelo4_v2
## DW = 1.5, p-value <0.0000000000000002
## alternative hypothesis: true autocorrelation is greater than 0

Interpretación de las pruebas formales de supuestos del Modelo 4:

Las pruebas formales muestran una mejora clara del Modelo 4, aunque los supuestos de normalidad y homocedasticidad todavía no se cumplen completamente.

  • Shapiro-Wilk: se obtiene W = 0,9885 con un valor p aproximado de \(3\times10^{-9}\). Formalmente se rechaza la hipótesis de normalidad; sin embargo, el estadístico se encuentra considerablemente más cerca de 1 que en los Modelos 1, 2 y 3, lo que confirma una mejora importante en la aproximación a la normalidad. Dado el tamaño de la muestra, pequeñas desviaciones pueden resultar estadísticamente significativas.
  • Breusch-Pagan: el estadístico disminuye hasta 84,0241, frente a 198,0991 en el Modelo 2 y 170,1841 en el Modelo 3. La reducción es sustancial, pero el valor p continúa siendo inferior a 0,001, por lo que todavía existe evidencia de heterocedasticidad.
  • Durbin-Watson: se obtiene aproximadamente 1,5037, con un valor p inferior a 0,001. La prueba continúa indicando autocorrelación positiva según el orden de las observaciones. Como los datos son de corte transversal y no una serie temporal, este resultado se interpreta con precaución y no se utiliza como criterio principal para seleccionar el modelo.

Por tanto, la exclusión temporal de las dos observaciones de mayor influencia mejora de manera marcada la normalidad aproximada y reduce la heterocedasticidad, pero no logra eliminar completamente el problema de varianza no constante. Esto justifica realizar un diagnóstico adicional para identificar con qué variables se encuentra asociada la heterocedasticidad restante.

Diagnóstico complementario de la heterocedasticidad del Modelo 4:

Dado que la prueba de Breusch-Pagan del Modelo 4 continúa indicando varianza no constante, se realiza un análisis complementario para identificar si la heterocedasticidad restante parece estar asociada de manera particular con alguna de las variables explicativas. Esta etapa se utiliza únicamente con fines de diagnóstico y no implica todavía modificar el modelo ni eliminar nuevas observaciones.

# Construir una base auxiliar para analizar la varianza
# de los residuos del Modelo 4.
diagnostico_hetero_m4 <- modelo_vivienda2_m4 |>
  dplyr::mutate(
    residuo_m4 = residuals(modelo4_v2),
    residuo2_m4 = residuals(modelo4_v2)^2,
    ajustado_m4 = fitted(modelo4_v2)
  )

# Organizar los gráficos en una sola figura.
par(mfrow = c(3, 2))

# Residuos al cuadrado frente al logaritmo del área.
plot(
  log(diagnostico_hetero_m4$areaconst),
  diagnostico_hetero_m4$residuo2_m4,
  main = "Residuos² vs. log(área)",
  xlab = "Logaritmo del área construida",
  ylab = "Residuos²",
  pch = 19
)
lines(
  lowess(
    log(diagnostico_hetero_m4$areaconst),
    diagnostico_hetero_m4$residuo2_m4
  ),
  lwd = 2
)

# Residuos al cuadrado frente a parqueaderos.
plot(
  diagnostico_hetero_m4$parqueaderos,
  diagnostico_hetero_m4$residuo2_m4,
  main = "Residuos² vs. parqueaderos",
  xlab = "Número de parqueaderos",
  ylab = "Residuos²",
  pch = 19
)
lines(
  lowess(
    diagnostico_hetero_m4$parqueaderos,
    diagnostico_hetero_m4$residuo2_m4
  ),
  lwd = 2
)

# Residuos al cuadrado frente a baños.
plot(
  diagnostico_hetero_m4$banios,
  diagnostico_hetero_m4$residuo2_m4,
  main = "Residuos² vs. baños",
  xlab = "Número de baños",
  ylab = "Residuos²",
  pch = 19
)
lines(
  lowess(
    diagnostico_hetero_m4$banios,
    diagnostico_hetero_m4$residuo2_m4
  ),
  lwd = 2
)

# Residuos al cuadrado frente a habitaciones.
plot(
  diagnostico_hetero_m4$habitaciones,
  diagnostico_hetero_m4$residuo2_m4,
  main = "Residuos² vs. habitaciones",
  xlab = "Número de habitaciones",
  ylab = "Residuos²",
  pch = 19
)
lines(
  lowess(
    diagnostico_hetero_m4$habitaciones,
    diagnostico_hetero_m4$residuo2_m4
  ),
  lwd = 2
)

# Comparar la dispersión de los residuos al cuadrado
# entre los estratos 5 y 6.
boxplot(
  residuo2_m4 ~ estrato,
  data = diagnostico_hetero_m4,
  main = "Residuos² según estrato",
  xlab = "Estrato",
  ylab = "Residuos²"
)

# Revisar la relación entre la magnitud de los errores
# y los valores ajustados del modelo.
plot(
  diagnostico_hetero_m4$ajustado_m4,
  diagnostico_hetero_m4$residuo2_m4,
  main = "Residuos² vs. valores ajustados",
  xlab = "Valores ajustados",
  ylab = "Residuos²",
  pch = 19
)
lines(
  lowess(
    diagnostico_hetero_m4$ajustado_m4,
    diagnostico_hetero_m4$residuo2_m4
  ),
  lwd = 2
)

# Restablecer la ventana gráfica.
par(mfrow = c(1, 1))

Interpretación gráfica del origen de la heterocedasticidad:

Los gráficos de residuos al cuadrado permiten observar que la heterocedasticidad restante no se distribuye de la misma manera frente a todas las variables.

La relación más visible aparece frente a log(área). En los apartamentos de menor tamaño los residuos al cuadrado presentan una dispersión relativamente reducida, mientras que al avanzar hacia áreas medias y altas aumenta la presencia de errores de mayor magnitud. Esto sugiere que la incertidumbre del precio crece a medida que se analizan apartamentos de mayor tamaño.

En parqueaderos, baños y habitaciones también se observan diferencias en la dispersión entre categorías, aunque el patrón es menos marcado y estas variables cuentan con pocos valores discretos. El gráfico por estrato muestra distribuciones relativamente similares entre estratos 5 y 6, por lo que no se aprecia visualmente una diferencia clara de varianza atribuible únicamente al estrato.

Finalmente, los residuos al cuadrado frente a los valores ajustados muestran una mayor dispersión en algunos niveles medios y altos del precio predicho. En conjunto, la evidencia gráfica sugiere que la heterocedasticidad restante está relacionada principalmente con el tamaño del apartamento y, de manera más general, con el nivel del precio esperado.

Pruebas de Breusch-Pagan por variable explicativa:

# Aplicar Breusch-Pagan utilizando cada predictor
# como variable explicativa de la varianza.
# El objetivo es identificar con cuál variable
# se encuentra más asociada la heterocedasticidad.

bp_area_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~ log(areaconst),
  data = modelo_vivienda2_m4
)

bp_parqueaderos_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~ parqueaderos,
  data = modelo_vivienda2_m4
)

bp_banios_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~ banios,
  data = modelo_vivienda2_m4
)

bp_habitaciones_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~ habitaciones,
  data = modelo_vivienda2_m4
)

bp_estrato_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~ estrato,
  data = modelo_vivienda2_m4
)

# Organizar los resultados en una tabla comparativa.
tabla_bp_variables_m4 <- data.frame(
  Variable = c(
    "log(Área construida)",
    "Parqueaderos",
    "Baños",
    "Habitaciones",
    "Estrato"
  ),
  BP = c(
    unname(bp_area_m4$statistic),
    unname(bp_parqueaderos_m4$statistic),
    unname(bp_banios_m4$statistic),
    unname(bp_habitaciones_m4$statistic),
    unname(bp_estrato_m4$statistic)
  ),
  `p-valor` = c(
    bp_area_m4$p.value,
    bp_parqueaderos_m4$p.value,
    bp_banios_m4$p.value,
    bp_habitaciones_m4$p.value,
    bp_estrato_m4$p.value
  ),
  check.names = FALSE
)

# Redondear los resultados.
tabla_bp_variables_m4$BP <- round(
  tabla_bp_variables_m4$BP,
  4
)

tabla_bp_variables_m4$`p-valor` <- round(
  tabla_bp_variables_m4$`p-valor`,
  6
)

# Mostrar la tabla.
knitr::kable(
  tabla_bp_variables_m4,
  caption = "Breusch-Pagan del Modelo 4 según variable explicativa"
)
Breusch-Pagan del Modelo 4 según variable explicativa
Variable BP p-valor
log(Área construida) 53.6277 0.0000
Parqueaderos 17.1796 0.0000
Baños 5.7712 0.0163
Habitaciones 5.7270 0.0167
Estrato 0.0008 0.9778

Interpretación de Breusch-Pagan por variable:

Las pruebas de Breusch-Pagan por variable muestran que la heterocedasticidad restante se encuentra asociada principalmente con el área construida.

log(Área construida) presenta el estadístico más alto, con BP = 53,6277 y p < 0,001. Parqueaderos también presenta una asociación significativa con la varianza de los residuos (BP = 17,1796; p < 0,001). Baños y habitaciones registran asociaciones de menor magnitud, aunque sus valores p también son inferiores a 0,05.

En contraste, estrato presenta BP = 0,0008 y p = 0,9778, por lo que no existe evidencia de que la varianza de los errores cambie sistemáticamente entre los estratos 5 y 6.

Estos resultados no implican que deban eliminarse las variables asociadas con la heterocedasticidad. En particular, el área es uno de los principales predictores del precio y su exclusión afectaría el sentido económico del modelo. La prueba indica que la dispersión de los errores cambia con el área, no que el área sea una variable explicativa inadecuada.

Pruebas tipo White para relaciones no lineales de la varianza:

# Complementar Breusch-Pagan incorporando un término cuadrático.
# Este procedimiento permite revisar si la varianza de los errores
# presenta una relación no lineal con cada predictor cuantitativo.

white_area_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~
    log(areaconst) +
    I(log(areaconst)^2),
  data = modelo_vivienda2_m4
)

white_parqueaderos_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~
    parqueaderos +
    I(parqueaderos^2),
  data = modelo_vivienda2_m4
)

white_banios_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~
    banios +
    I(banios^2),
  data = modelo_vivienda2_m4
)

white_habitaciones_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~
    habitaciones +
    I(habitaciones^2),
  data = modelo_vivienda2_m4
)

# Evaluar también si la varianza cambia de forma no lineal
# a lo largo de los valores ajustados del Modelo 4.
white_ajustados_m4 <- lmtest::bptest(
  modelo4_v2,
  varformula = ~
    ajustado_m4 +
    I(ajustado_m4^2),
  data = diagnostico_hetero_m4
)

# Organizar los resultados en una tabla.
tabla_white_m4 <- data.frame(
  Variable = c(
    "log(Área construida)",
    "Parqueaderos",
    "Baños",
    "Habitaciones",
    "Valores ajustados"
  ),
  Estadistico = c(
    unname(white_area_m4$statistic),
    unname(white_parqueaderos_m4$statistic),
    unname(white_banios_m4$statistic),
    unname(white_habitaciones_m4$statistic),
    unname(white_ajustados_m4$statistic)
  ),
  `p-valor` = c(
    white_area_m4$p.value,
    white_parqueaderos_m4$p.value,
    white_banios_m4$p.value,
    white_habitaciones_m4$p.value,
    white_ajustados_m4$p.value
  ),
  check.names = FALSE
)

# Redondear para facilitar la lectura.
tabla_white_m4$Estadistico <- round(
  tabla_white_m4$Estadistico,
  4
)

tabla_white_m4$`p-valor` <- round(
  tabla_white_m4$`p-valor`,
  6
)

# Mostrar la tabla.
knitr::kable(
  tabla_white_m4,
  caption = "Pruebas tipo White para el diagnóstico de heterocedasticidad del Modelo 4"
)
Pruebas tipo White para el diagnóstico de heterocedasticidad del Modelo 4
Variable Estadistico p-valor
log(Área construida) 62.50 0.0000
Parqueaderos 17.34 0.0002
Baños 6.33 0.0422
Habitaciones 10.04 0.0066
Valores ajustados 24.87 0.0000

Interpretación de las pruebas tipo White:

Las pruebas tipo White refuerzan el resultado obtenido mediante Breusch-Pagan. El mayor estadístico corresponde nuevamente a log(Área construida), con un valor de 62,50 y p < 0,001, indicando que la varianza de los errores mantiene una relación significativa con el área incluso al considerar un componente no lineal.

Los valores ajustados presentan también una asociación importante con la varianza (24,87; p < 0,001), seguidos de parqueaderos (17,34; p = 0,0002). Habitaciones (10,04; p = 0,0066) y baños (6,33; p = 0,0422) muestran efectos menores, pero todavía significativos al 5 %.

La coincidencia entre Breusch-Pagan, White y los gráficos indica que la heterocedasticidad no depende únicamente de dos observaciones extremas. Después de retirarlas temporalmente permanece un componente estructural asociado principalmente con el área construida y con el nivel general del precio estimado.

Prueba de Goldfeld-Quandt orientada al área construida:

Dado que las pruebas de Breusch-Pagan y White señalan que la heterocedasticidad restante se encuentra asociada principalmente con el área construida, se aplica la prueba de Goldfeld-Quandt ordenando las observaciones según log(areaconst). Esta prueba permite contrastar si la varianza de los errores aumenta al pasar de apartamentos de menor área a apartamentos de mayor área.

# Aplicar la prueba de Goldfeld-Quandt ordenando
# las observaciones por el logaritmo del área construida.
#
# Se utiliza una alternativa "greater" porque el diagnóstico
# previo sugiere que la dispersión de los errores aumenta
# a medida que crece el área.
#
# Se excluye temporalmente el 20 % central de las observaciones
# para comparar con mayor claridad los grupos de menor y mayor área.
gq_area_m4 <- lmtest::gqtest(
  modelo4_v2,
  order.by = ~ log(areaconst),
  fraction = 0.20,
  alternative = "greater",
  data = modelo_vivienda2_m4
)

# Mostrar el resultado.
gq_area_m4
## 
##  Goldfeld-Quandt test
## 
## data:  modelo4_v2
## GQ = 2, df1 = 568, df2 = 568, p-value <0.0000000000000002
## alternative hypothesis: variance increases from segment 1 to 2

Interpretación de la prueba de Goldfeld-Quandt:

La prueba de Goldfeld-Quandt obtiene GQ = 2,00, con 568 grados de libertad en cada segmento y un valor p inferior a 0,001. Dado que la prueba se ordenó por log(areaconst) y se utilizó como alternativa que la varianza aumenta del primer segmento al segundo, el resultado permite rechazar la hipótesis de varianza constante.

En consecuencia, existe evidencia estadística muy fuerte de que la varianza de los errores es mayor en los apartamentos de mayor área. Este resultado coincide con las pruebas de Breusch-Pagan y White y con la revisión gráfica de los residuos al cuadrado.

La convergencia de estas pruebas permite identificar con mayor precisión el problema: las observaciones 532 y 1266 agravaban fuertemente la heterocedasticidad y la influencia, pero, incluso después de retirarlas temporalmente, permanece una heterocedasticidad estructural vinculada principalmente al área construida. Por tanto, no resulta metodológicamente adecuado continuar eliminando observaciones con el único propósito de obtener pruebas no significativas.

Evaluación de la multicolinealidad del Modelo 4:

# Evaluar la multicolinealidad entre las variables explicativas
# mediante el Factor de Inflación de la Varianza (VIF).
vif_m4_v2 <- car::vif(
  modelo4_v2
)
vif_m4_v2
## log(areaconst)   parqueaderos         banios   habitaciones        estrato 
##          3.035          2.145          2.681          1.553          1.517

Interpretación de la multicolinealidad del Modelo 4:

Los valores VIF del Modelo 4 son 3,035 para log(areaconst), 2,145 para parqueaderos, 2,681 para baños, 1,553 para habitaciones y 1,517 para estrato.

Aunque el VIF máximo aumenta ligeramente frente a los Modelos 2 y 3, todos los valores se mantienen por debajo del umbral de 5 utilizado como referencia. Por tanto, no existe evidencia de multicolinealidad severa.

Este resultado permite descartar la multicolinealidad como explicación principal de los problemas de normalidad y heterocedasticidad observados. Las asociaciones entre área, baños y parqueaderos son esperables en el contexto inmobiliario, pero no alcanzan niveles que justifiquen eliminar predictores únicamente por este motivo.

Análisis de observaciones influyentes del Modelo 4:

# Calcular la distancia de Cook para cada observación.
dist_cook_m4_v2 <- cooks.distance(
  modelo4_v2
)

# Definir el umbral de referencia 4/n.
umbral_cook_m4_v2 <- 4 / nrow(
  modelo_vivienda2_m4
)

# Graficar las distancias de Cook.
plot(
  dist_cook_m4_v2,
  type = "h",
  main = "Distancia de Cook - Modelo 4",
  xlab = "Observación en la base del Modelo 4",
  ylab = "Distancia de Cook"
)

# Agregar la línea de referencia.
abline(
  h = umbral_cook_m4_v2,
  lty = 2
)

# Mostrar las 10 mayores distancias de Cook.
head(
  sort(
    dist_cook_m4_v2,
    decreasing = TRUE
  ),
  10
)
##     579     252    1051      62    1041    1097      61     721     126     376 
## 0.04323 0.03876 0.02190 0.02150 0.02093 0.02047 0.01908 0.01827 0.01695 0.01681

Interpretación de las observaciones influyentes del Modelo 4:

La distancia de Cook del Modelo 4 presenta una reducción muy marcada frente a los modelos anteriores. El valor máximo es aproximadamente 0,0432, mientras que en el Modelo 2 era 0,5946 y en el Modelo 3 alcanzaba 0,6117.

Las mayores distancias corresponden a las observaciones 579 y 252 del Modelo 4, con valores aproximados de 0,0432 y 0,0388, respectivamente. Aunque algunos registros continúan superando el umbral de referencia \(4/n\), ninguno presenta una influencia extraordinaria comparable con las observaciones 532 y 1266.

El resultado confirma que aquellas dos observaciones concentraban una parte importante de la inestabilidad del ajuste. En el Modelo 4 la influencia queda distribuida de forma mucho más equilibrada entre los registros restantes.

# Identificar las observaciones que superan
# el umbral de referencia de distancia de Cook.
obs_influyentes_m4_v2 <- which(
  dist_cook_m4_v2 > umbral_cook_m4_v2
)

# Construir una tabla de revisión y conservar
# la observación original de la base de modelación.
revision_influyentes_m4_v2 <- data.frame(
  Observacion_M4 = obs_influyentes_m4_v2,
  Observacion_original = modelo_vivienda2_m4$Observacion_modelo[
    obs_influyentes_m4_v2
  ],
  ID = modelo_vivienda2_m4$id[
    obs_influyentes_m4_v2
  ],
  Precio = modelo_vivienda2_m4$preciom[
    obs_influyentes_m4_v2
  ],
  Area = modelo_vivienda2_m4$areaconst[
    obs_influyentes_m4_v2
  ],
  Parqueaderos = modelo_vivienda2_m4$parqueaderos[
    obs_influyentes_m4_v2
  ],
  Banios = modelo_vivienda2_m4$banios[
    obs_influyentes_m4_v2
  ],
  Habitaciones = modelo_vivienda2_m4$habitaciones[
    obs_influyentes_m4_v2
  ],
  Estrato = modelo_vivienda2_m4$estrato[
    obs_influyentes_m4_v2
  ],
  Distancia_Cook = round(
    dist_cook_m4_v2[obs_influyentes_m4_v2],
    5
  )
)

# Ordenar de mayor a menor influencia.
revision_influyentes_m4_v2 <- revision_influyentes_m4_v2[
  order(
    revision_influyentes_m4_v2$Distancia_Cook,
    decreasing = TRUE
  ),
]

# Mostrar la tabla.
knitr::kable(
  revision_influyentes_m4_v2,
  caption = "Observaciones que superan el umbral de distancia de Cook - Modelo 4"
)
Observaciones que superan el umbral de distancia de Cook - Modelo 4
Observacion_M4 Observacion_original ID Precio Area Parqueaderos Banios Habitaciones Estrato Distancia_Cook
579 579 580 7182 730 573.00 3 8 5 5 0.0432
252 252 252 6086 1500 240.00 3 5 6 6 0.0388
1051 1051 1052 6177 140 120.00 1 2 2 5 0.0219
62 62 62 6205 350 260.00 3 3 3 5 0.0215
1041 1041 1042 5801 350 250.00 2 5 3 5 0.0209
1097 1097 1098 4942 1250 213.00 3 4 3 5 0.0205
61 61 61 6175 350 270.00 3 3 4 5 0.0191
721 721 722 6073 1250 251.00 4 5 4 5 0.0183
126 126 126 3678 250 94.00 3 2 3 6 0.0170
376 376 376 5119 231 163.00 2 5 5 5 0.0168
1423 1423 1425 4990 350 174.00 4 3 4 5 0.0153
483 483 483 4952 650 600.00 2 4 5 5 0.0149
821 821 822 6512 1750 290.00 3 4 3 6 0.0127
430 430 430 4405 268 145.00 1 2 3 6 0.0121
536 536 537 1141 240 126.00 2 2 3 6 0.0116
226 226 226 6197 1700 290.00 3 4 3 6 0.0115
697 697 698 6242 340 236.00 2 4 3 5 0.0114
375 375 375 5005 280 154.00 1 3 3 6 0.0113
881 881 882 44 1200 211.00 2 3 3 6 0.0106
1050 1050 1051 6066 139 120.00 1 2 3 5 0.0101
1027 1027 1028 2308 350 258.00 2 4 5 5 0.0090
212 212 212 5242 704 141.00 2 3 2 5 0.0088
119 119 119 5941 700 138.00 2 5 4 5 0.0087
933 933 934 5574 850 352.00 4 3 3 6 0.0087
931 931 932 5472 1590 310.00 3 4 3 6 0.0085
748 748 749 7680 450 267.00 3 3 3 5 0.0083
329 329 329 8113 410 295.55 2 4 4 5 0.0081
141 141 141 5952 1750 342.00 3 5 4 6 0.0081
204 204 204 5176 180 73.00 1 2 3 6 0.0076
164 164 164 6576 660 210.00 4 5 3 6 0.0073
906 906 907 3785 1580 296.00 4 4 3 6 0.0070
429 429 429 4297 220 116.00 2 3 3 6 0.0069
820 820 821 6510 1600 290.00 3 5 4 6 0.0064
570 570 571 6584 300 209.00 1 4 5 5 0.0064
494 494 494 5360 230 80.00 2 2 3 6 0.0057
1033 1033 1034 6011 620 160.00 2 2 3 5 0.0057
1028 1028 1029 6973 240 139.84 2 4 3 5 0.0057
652 652 653 4424 450 110.00 2 4 5 5 0.0056
786 786 787 4082 600 129.00 1 3 3 5 0.0055
895 895 896 7346 1350 212.00 3 5 3 6 0.0055
123 123 123 6527 677 108.00 2 2 3 6 0.0054
742 742 743 6103 206 109.00 2 4 4 5 0.0054
142 142 142 6475 1561 399.00 3 4 3 6 0.0053
905 905 906 3592 1150 222.00 2 4 3 6 0.0052
945 945 946 6723 840 185.00 2 2 2 6 0.0051
325 325 325 7578 321 217.04 1 4 5 5 0.0050
399 399 399 4083 270 95.00 2 3 4 6 0.0048
934 934 935 6077 710 151.00 3 5 3 5 0.0048
502 502 502 5525 245 98.00 2 3 3 6 0.0047
954 954 955 5596 980 348.00 4 5 3 6 0.0047
294 294 294 5704 630 210.00 2 2 3 5 0.0046
1031 1031 1032 6932 500 330.00 2 4 4 5 0.0046
310 310 310 3734 320 115.00 2 3 2 6 0.0046
569 569 570 8099 199 109.00 1 2 2 5 0.0045
122 122 122 6526 832 213.00 2 2 3 6 0.0043
250 250 250 5190 1600 345.00 3 6 3 6 0.0042
682 682 683 6548 206 80.83 2 4 4 5 0.0042
543 543 544 6058 380 175.00 3 4 3 5 0.0042
58 58 58 6705 185 121.00 1 2 3 5 0.0042
304 304 304 6275 950 330.00 4 6 4 6 0.0040
305 305 305 6364 930 145.00 2 3 3 6 0.0040
405 405 405 4394 690 486.00 2 4 4 5 0.0039
573 573 574 6850 280 126.00 2 3 3 6 0.0038
610 610 611 3826 355 85.00 2 2 4 5 0.0037
459 459 459 5259 300 155.00 1 5 4 5 0.0036
517 517 517 3726 290 100.00 2 3 4 6 0.0036
4 4 4 8288 310 166.00 2 4 3 5 0.0036
239 239 239 6023 1150 464.00 4 6 5 6 0.0035
443 443 443 4257 255 100.00 1 2 3 6 0.0034
1424 1424 1426 7445 165 55.00 1 2 1 5 0.0034
193 193 193 3975 1240 222.00 3 5 4 6 0.0034
1434 1434 1436 3640 870 245.00 1 4 3 6 0.0034
1426 1426 1428 6596 179 110.00 1 3 4 5 0.0033
426 426 426 4223 240 120.00 1 4 3 5 0.0033
1084 1084 1085 3365 670 191.00 2 3 3 5 0.0032
710 710 711 3440 419 181.00 2 3 3 6 0.0032
21 21 21 7413 160 82.00 1 3 4 5 0.0031
353 353 353 1998 130 45.00 1 2 2 5 0.0031
847 847 848 7455 600 145.00 2 5 3 5 0.0031
279 279 279 3623 350 120.00 2 2 2 6 0.0030
175 175 175 5122 300 120.00 1 3 4 6 0.0030
150 150 150 4477 660 150.00 3 4 3 5 0.0030
677 677 678 6243 300 180.00 1 2 3 5 0.0030
326 326 326 7204 320 185.00 2 2 4 5 0.0029
346 346 346 7211 320 185.00 2 2 4 5 0.0029
347 347 347 7212 320 185.00 2 2 4 5 0.0029
281 281 281 3732 500 110.00 2 2 3 5 0.0029
288 288 288 5246 697 139.00 2 2 2 6 0.0029
1062 1062 1063 4158 450 187.00 2 4 3 6 0.0029
890 890 891 4712 1100 220.00 4 4 4 6 0.0028

Interpretación de la revisión de observaciones influyentes del Modelo 4:

La revisión de las observaciones que superan el umbral \(4/n\) muestra que permanecen varios apartamentos con combinaciones poco frecuentes de precio, área y características físicas. Sin embargo, sus distancias de Cook son sustancialmente menores que las observadas anteriormente.

El Modelo 4 registra 90 observaciones por encima del criterio \(4/n\), cifra superior a la de algunos modelos previos. Este número no debe interpretarse aisladamente como un empeoramiento, ya que con 1.435 registros el umbral \(4/n\) es muy pequeño. El indicador más informativo en este caso es la magnitud: la distancia de Cook máxima disminuye hasta 0,0432, muy por debajo de 0,5946 y 0,6117 de los Modelos 2 y 3.

Por tanto, no aparece una nueva observación que sustituya a los casos 532 y 1266 como punto dominante. La sensibilidad del modelo frente a observaciones individuales se reduce considerablemente.

Comparación final de los modelos:

# Calcular los principales diagnósticos
# para los cuatro modelos.

# Prueba de normalidad.
shapiro_m1_v2 <- shapiro.test(residuals(modelo1_v2))
shapiro_m2_v2 <- shapiro.test(residuals(modelo2_v2))
shapiro_m3_v2 <- shapiro.test(residuals(modelo3_v2))
shapiro_m4_v2 <- shapiro.test(residuals(modelo4_v2))

# Prueba de homocedasticidad.
bp_m1_v2 <- lmtest::bptest(modelo1_v2)
bp_m2_v2 <- lmtest::bptest(modelo2_v2)
bp_m3_v2 <- lmtest::bptest(modelo3_v2)
bp_m4_v2 <- lmtest::bptest(modelo4_v2)

# Prueba de independencia.
dw_m1_v2 <- lmtest::dwtest(modelo1_v2)
dw_m2_v2 <- lmtest::dwtest(modelo2_v2)
dw_m3_v2 <- lmtest::dwtest(modelo3_v2)
dw_m4_v2 <- lmtest::dwtest(modelo4_v2)

# Calcular los valores VIF.
vif_m1_v2 <- car::vif(modelo1_v2)
vif_m2_v2 <- car::vif(modelo2_v2)
vif_m3_v2 <- car::vif(modelo3_v2)
vif_m4_v2 <- car::vif(modelo4_v2)

# Calcular las distancias de Cook.
dist_cook_m1_v2 <- cooks.distance(modelo1_v2)
dist_cook_m2_v2 <- cooks.distance(modelo2_v2)
dist_cook_m3_v2 <- cooks.distance(modelo3_v2)
dist_cook_m4_v2 <- cooks.distance(modelo4_v2)

# Construir una tabla comparativa.
comparacion_modelos_v2 <- data.frame(
  Indicador = c(
    "Número de observaciones",
    "Shapiro-Wilk (W)",
    "p-valor Shapiro-Wilk",
    "Breusch-Pagan (BP)",
    "p-valor Breusch-Pagan",
    "Durbin-Watson (DW)",
    "p-valor Durbin-Watson",
    "VIF máximo",
    "Distancia de Cook máxima",
    "Observaciones Cook > 4/n"
  ),

  Modelo_1 = c(
    stats::nobs(modelo1_v2),
    unname(shapiro_m1_v2$statistic),
    shapiro_m1_v2$p.value,
    unname(bp_m1_v2$statistic),
    bp_m1_v2$p.value,
    unname(dw_m1_v2$statistic),
    dw_m1_v2$p.value,
    max(vif_m1_v2),
    max(dist_cook_m1_v2),
    sum(dist_cook_m1_v2 > 4 / stats::nobs(modelo1_v2))
  ),

  Modelo_2 = c(
    stats::nobs(modelo2_v2),
    unname(shapiro_m2_v2$statistic),
    shapiro_m2_v2$p.value,
    unname(bp_m2_v2$statistic),
    bp_m2_v2$p.value,
    unname(dw_m2_v2$statistic),
    dw_m2_v2$p.value,
    max(vif_m2_v2),
    max(dist_cook_m2_v2),
    sum(dist_cook_m2_v2 > 4 / stats::nobs(modelo2_v2))
  ),

  Modelo_3 = c(
    stats::nobs(modelo3_v2),
    unname(shapiro_m3_v2$statistic),
    shapiro_m3_v2$p.value,
    unname(bp_m3_v2$statistic),
    bp_m3_v2$p.value,
    unname(dw_m3_v2$statistic),
    dw_m3_v2$p.value,
    max(vif_m3_v2),
    max(dist_cook_m3_v2),
    sum(dist_cook_m3_v2 > 4 / stats::nobs(modelo3_v2))
  ),

  Modelo_4 = c(
    stats::nobs(modelo4_v2),
    unname(shapiro_m4_v2$statistic),
    shapiro_m4_v2$p.value,
    unname(bp_m4_v2$statistic),
    bp_m4_v2$p.value,
    unname(dw_m4_v2$statistic),
    dw_m4_v2$p.value,
    max(vif_m4_v2),
    max(dist_cook_m4_v2),
    sum(dist_cook_m4_v2 > 4 / stats::nobs(modelo4_v2))
  )
)

# Redondear los resultados numéricos.
comparacion_modelos_v2[, 2:5] <- round(
  comparacion_modelos_v2[, 2:5],
  5
)

# Mostrar la comparación.
knitr::kable(
  comparacion_modelos_v2,
  caption = "Comparación de diagnósticos entre los Modelos 1, 2, 3 y 4"
)
Comparación de diagnósticos entre los Modelos 1, 2, 3 y 4
Indicador Modelo_1 Modelo_2 Modelo_3 Modelo_4
Número de observaciones 1437.0000 1437.0000 1437.0000 1435.0000
Shapiro-Wilk (W) 0.8112 0.9757 0.9739 0.9885
p-valor Shapiro-Wilk 0.0000 0.0000 0.0000 0.0000
Breusch-Pagan (BP) 441.0383 198.0991 170.1841 84.0241
p-valor Breusch-Pagan 0.0000 0.0000 0.0000 0.0000
Durbin-Watson (DW) 1.7025 1.5594 1.5501 1.5037
p-valor Durbin-Watson 0.0000 0.0000 0.0000 0.0000
VIF máximo 2.4577 2.7438 2.7438 3.0351
Distancia de Cook máxima 5.4946 0.5946 0.6117 0.0432
Observaciones Cook > 4/n 73.0000 83.0000 80.0000 90.0000

Interpretación comparativa de los Modelos 1, 2, 3 y 4:

La comparación de los cuatro modelos permite reconstruir de manera consecutiva las decisiones adoptadas durante la modelación.

El Modelo 1, estimado en escala original, constituye la especificación de referencia. Aunque el modelo es globalmente significativo, presenta los mayores problemas de normalidad, heterocedasticidad e influencia. Shapiro-Wilk alcanza 0,8112, Breusch-Pagan 441,0383 y la distancia de Cook máxima llega a 5,4946. Por esta razón, el análisis exploratorio y los diagnósticos justificaron evaluar transformaciones.

El Modelo 2 incorpora log(precio) y log(área), forma funcional respaldada previamente por la mayor correlación observada entre estas variables. La transformación produce una mejora sustancial: Shapiro-Wilk aumenta a 0,9757, Breusch-Pagan disminuye a 198,0991 y Cook máximo cae a 0,5946. No obstante, las pruebas continúan señalando no normalidad y heterocedasticidad.

El Modelo 3 utiliza una transformación Box-Cox del precio con \(\lambda=-0,1414\). Su objetivo fue evaluar si una transformación estimada directamente a partir de los datos podía corregir los problemas restantes. Breusch-Pagan disminuye adicionalmente a 170,1841, pero Shapiro-Wilk se reduce ligeramente a 0,9739 y Cook máximo aumenta a 0,6117. Además, el valor de lambda se encuentra relativamente cerca de cero, confirmando que la transformación logarítmica del Modelo 2 ya estaba próxima a la forma sugerida por Box-Cox. Por tanto, el Modelo 3 aporta información diagnóstica, pero no representa una mejora global suficiente.

El Modelo 4 conserva la especificación logarítmica del Modelo 2 y excluye temporalmente las observaciones 532 y 1266 únicamente como análisis de sensibilidad. Esta prueba produce la mayor mejora diagnóstica: Shapiro-Wilk aumenta a 0,9885, Breusch-Pagan disminuye a 84,0241 y Cook máximo cae hasta 0,0432. Los coeficientes mantienen los mismos signos y significancia, mostrando que la estructura sustantiva del modelo es estable. Sin embargo, Shapiro-Wilk y Breusch-Pagan continúan siendo significativos y Goldfeld-Quandt confirma que la varianza de los errores aumenta con el área construida.

En cuanto a la multicolinealidad, los cuatro modelos mantienen VIF máximos inferiores a 5. Por tanto, este aspecto no explica los principales incumplimientos observados. La prueba de Durbin-Watson resulta significativa en todas las especificaciones; sin embargo, su interpretación se mantiene bajo cautela por tratarse de datos de corte transversal.

Decisión final para la Vivienda 2: aunque el Modelo 4 presenta los mejores diagnósticos, se mantiene como análisis de sensibilidad y no como modelo operativo definitivo, porque depende de excluir dos registros cuya condición de error no pudo comprobarse. La mejora obtenida demuestra que esos casos tienen una influencia excepcional, pero las pruebas adicionales muestran que la heterocedasticidad restante es también una característica estructural asociada principalmente con el área construida.

Por esta razón, se conserva el Modelo 2 con transformación logarítmica como modelo final para la predicción. Esta elección utiliza la totalidad de la muestra, mantiene una interpretación directa mediante elasticidades y porcentajes, reduce sustancialmente los problemas del Modelo 1 y presenta una estructura de coeficientes que se mantiene estable en el análisis de sensibilidad. Los incumplimientos restantes se documentan como limitaciones del modelo, de acuerdo con el alcance de la actividad, que no exige corregir todos los supuestos sino validarlos e indicar posibles acciones posteriores.

4.4 Predicción del precio para la Vivienda 2

Definido el Modelo 2 como especificación final para la predicción, se estiman los dos escenarios correspondientes a los estratos 5 y 6. El Modelo 4 se conserva como análisis de sensibilidad y no se utiliza para sustituir la predicción principal, dado que depende de la exclusión temporal de dos registros cuya condición de error no pudo comprobarse.

# Crear los dos escenarios solicitados:
# uno para estrato 5 y otro para estrato 6
nueva_vivienda2 <- data.frame(
  areaconst = c(300, 300),
  parqueaderos = c(3, 3),
  banios = c(3, 3),
  habitaciones = c(5, 5),
  estrato = factor(
    c("5", "6"),
    levels = levels(modelo_vivienda2$estrato)
  )
)

# Realizar la predicción con el Modelo 2.
# Los resultados se obtienen inicialmente
# en la escala logarítmica del precio.
prediccion_log_v2 <- predict(
  modelo2_v2,
  newdata = nueva_vivienda2,
  interval = "prediction",
  level = 0.95
)

# Regresar las predicciones a la escala original
# del precio, expresada en millones de pesos.
prediccion_precio_v2 <- exp(
  prediccion_log_v2
)

# Organizar los resultados en una tabla
resultado_prediccion_v2 <- data.frame(
  Estrato = c(5, 6),
  `Precio estimado (millones)` = round(
    prediccion_precio_v2[, "fit"],
    2
  ),
  `Intervalo de predicción 95% - Inferior` = round(
    prediccion_precio_v2[, "lwr"],
    2
  ),
  `Intervalo de predicción 95% - Superior` = round(
    prediccion_precio_v2[, "upr"],
    2
  ),
  `Crédito máximo (millones)` = 850,
  check.names = FALSE
)

# Mostrar la tabla
knitr::kable(
  resultado_prediccion_v2,
  caption = "Predicción del precio para la Vivienda 2"
)
Predicción del precio para la Vivienda 2
Estrato Precio estimado (millones) Intervalo de predicción 95% - Inferior Intervalo de predicción 95% - Superior Crédito máximo (millones)
5 590.0 397.9 874.7 850
6 797.1 537.6 1181.9 850

Interpretación de la predicción para la Vivienda 2:

A partir del Modelo 2 se estima el precio de un apartamento con 300 m² de área construida, 3 parqueaderos, 3 baños y 5 habitaciones, considerando los dos estratos permitidos.

Para el estrato 5, el precio puntual estimado es de aproximadamente 589.99 millones de pesos. Para el estrato 6, la estimación aumenta a aproximadamente 797.12 millones de pesos. En ambos casos, la estimación puntual se encuentra por debajo del crédito máximo preaprobado de 850 millones de pesos, aunque el escenario de estrato 6 se aproxima en mayor medida al límite presupuestal.

El intervalo de predicción del 95 % para estrato 5 se encuentra aproximadamente entre 397.94 y 874.74 millones, mientras que para estrato 6 se ubica entre 537.61 y 1181.92 millones. Estos intervalos son más amplios que las estimaciones puntuales porque representan la incertidumbre asociada con el precio de un apartamento individual, no únicamente con el precio medio esperado.

En términos de viabilidad presupuestal, el modelo indica que ambos estratos son posibles según la estimación puntual, pero el estrato 5 ofrece un margen financiero mayor. La amplitud de los intervalos refuerza la necesidad de complementar la predicción con la búsqueda de ofertas reales dentro del presupuesto disponible.

4.5 Selección de ofertas potenciales

# Filtrar los apartamentos que se encuentran
# dentro del presupuesto máximo de $850 millones
ofertas_v2 <- vivienda2 |>
  dplyr::filter(
    preciom <= 850
  ) |>

  # Calcular qué tan cerca se encuentra cada oferta
  # de las características solicitadas
  dplyr::mutate(
    Coincidencias =
      (parqueaderos == 3) +
      (banios == 3) +
      (habitaciones == 5),

    Diferencia_area = abs(
      areaconst - 300
    )
  )

# Revisar cuántas ofertas cumplen con el presupuesto
nrow(ofertas_v2)
## [1] 1384
# Seleccionar las cinco ofertas que mejor se aproximan
# a las características solicitadas
ofertas_seleccionadas_v2 <- ofertas_v2 |>
  dplyr::arrange(
    dplyr::desc(Coincidencias),
    Diferencia_area,
    preciom
  ) |>
  dplyr::slice_head(
    n = 5
  )

# Mostrar las cinco ofertas seleccionadas
tabla_ofertas_v2 <- ofertas_seleccionadas_v2 |>
  dplyr::select(
    id,
    barrio,
    preciom,
    areaconst,
    parqueaderos,
    banios,
    habitaciones,
    estrato,
    Coincidencias,
    Diferencia_area
  )

knitr::kable(
  tabla_ofertas_v2,
  col.names = c(
    "ID",
    "Barrio",
    "Precio (millones)",
    "Área (m²)",
    "Parqueaderos",
    "Baños",
    "Habitaciones",
    "Estrato",
    "Coincidencias",
    "Diferencia área (m²)"
  ),
  caption = "Ofertas potenciales para la Vivienda 2"
)
Ofertas potenciales para la Vivienda 2
ID Barrio Precio (millones) Área (m²) Parqueaderos Baños Habitaciones Estrato Coincidencias Diferencia área (m²)
6175 capri 350 270 3 3 4 5 2 30
7680 pampa linda 450 267 3 3 3 5 2 33
6205 capri 350 260 3 3 3 5 2 40
8036 seminario 530 256 3 5 5 5 2 44
5423 ciudad jardín 695 227 3 3 3 6 2 73

Interpretación de las ofertas potenciales para la Vivienda 2:

Dentro del subconjunto se identifican 1.384 apartamentos con precios iguales o inferiores a 850 millones de pesos, por lo que la restricción presupuestal por sí sola no limita fuertemente la oferta. El reto principal consiste en encontrar apartamentos que se aproximen simultáneamente a los 300 m², 3 parqueaderos, 3 baños y 5 habitaciones solicitados.

Las cinco alternativas seleccionadas alcanzan dos coincidencias exactas en las variables discretas consideradas; por tanto, no se identifica dentro de este criterio una oferta que reproduzca exactamente parqueaderos, baños y habitaciones al mismo tiempo.

  • Capri, ID 6175: precio de 350 millones, área de 270 m², 3 parqueaderos, 3 baños y 4 habitaciones, estrato 5. Es la oferta más cercana al área requerida, con una diferencia de 30 m², y coincide exactamente en parqueaderos y baños. Su principal diferencia es contar con una habitación menos.
  • Pampa Linda, ID 7680: precio de 450 millones, 267 m², 3 parqueaderos, 3 baños y 3 habitaciones, estrato 5. Presenta una diferencia de 33 m² en el área, pero dispone de dos habitaciones menos que las solicitadas.
  • Capri, ID 6205: precio de 350 millones, 260 m², 3 parqueaderos, 3 baños y 3 habitaciones, estrato 5. Mantiene un amplio margen presupuestal, aunque se aleja en 40 m² del área y en dos habitaciones del requerimiento.
  • Seminario, ID 8036: precio de 530 millones, 256 m², 3 parqueaderos, 5 baños y 5 habitaciones, estrato 5. Esta oferta coincide exactamente en parqueaderos y habitaciones y es la única de las cinco seleccionadas que cumple las 5 habitaciones solicitadas; su diferencia principal corresponde a dos baños adicionales y 44 m² menos de área.
  • Ciudad Jardín, ID 5423: precio de 695 millones, 227 m², 3 parqueaderos, 3 baños y 3 habitaciones, estrato 6. Cumple el presupuesto y coincide en parqueaderos y baños, pero presenta la mayor diferencia de área entre las seleccionadas y dos habitaciones menos.

En consecuencia, la oferta de Capri ID 6175 presenta el mejor equilibrio si se priorizan cercanía al área, baños y parqueaderos. Sin embargo, si las 5 habitaciones constituyen una condición especialmente importante, la alternativa de Seminario ID 8036 merece una consideración prioritaria, ya que cumple exactamente esta característica y los 3 parqueaderos, manteniéndose ampliamente dentro del presupuesto.

# Crear una paleta de colores para identificar
# las cinco ofertas seleccionadas
paleta_ofertas_v2 <- leaflet::colorFactor(
  palette = "Set1",
  domain = ofertas_seleccionadas_v2$id
)

# Construir el mapa interactivo
leaflet::leaflet(
  ofertas_seleccionadas_v2,
  width = "100%",
  height = 400
) |>
  leaflet::addProviderTiles(
    leaflet::providers$CartoDB.Positron
  ) |>
  leaflet::addCircleMarkers(
    lng = ~longitud,
    lat = ~latitud,
    radius = 6,
    color = ~paleta_ofertas_v2(id),
    fillOpacity = 0.85,
    stroke = TRUE,
    weight = 1,
    popup = ~paste0(
      "<b>Barrio:</b> ", barrio,
      "<br><b>Precio:</b> $", preciom, " millones",
      "<br><b>Área:</b> ", areaconst, " m²",
      "<br><b>Parqueaderos:</b> ", parqueaderos,
      "<br><b>Baños:</b> ", banios,
      "<br><b>Habitaciones:</b> ", habitaciones,
      "<br><b>Estrato:</b> ", estrato
    )
  ) |>
  leaflet::addLegend(
    position = "bottomright",
    pal = paleta_ofertas_v2,
    values = ~id,
    title = "ID de la oferta"
  ) |>
  leaflet::fitBounds(
    lng1 = min(
      ofertas_seleccionadas_v2$longitud,
      na.rm = TRUE
    ),
    lat1 = min(
      ofertas_seleccionadas_v2$latitud,
      na.rm = TRUE
    ),
    lng2 = max(
      ofertas_seleccionadas_v2$longitud,
      na.rm = TRUE
    ),
    lat2 = max(
      ofertas_seleccionadas_v2$latitud,
      na.rm = TRUE
    )
  )

Interpretación del mapa de ofertas potenciales:

El mapa permite visualizar la ubicación de las cinco alternativas seleccionadas. En términos generales, los puntos se concentran en el sector sur y suroccidental de la ciudad, de manera coherente con la Zona Sur utilizada para construir el subconjunto.

Las ofertas presentan cierta proximidad espacial, aunque existen diferencias de localización que pueden resultar relevantes para la decisión final. Los apartamentos de Capri, Pampa Linda, Seminario y Ciudad Jardín representan sectores distintos dentro del área analizada y permiten complementar la comparación de precio y características físicas con criterios de accesibilidad, entorno y preferencias de ubicación.

No se observa en estas cinco ofertas una inconsistencia espacial tan evidente como la detectada previamente en algunos registros de la Vivienda 1. No obstante, debido a los problemas de georreferenciación identificados en la base general, las coordenadas deben considerarse como referencia y verificarse antes de una decisión de compra.

En conjunto, el mapa confirma que existen alternativas dentro del presupuesto distribuidas en diferentes sectores de la Zona Sur, por lo que la recomendación puede concentrarse principalmente en el grado de cumplimiento de las características solicitadas.

4.6 Recomendación para la Vivienda 2

Recomendación:

Para la segunda solicitud se conserva el Modelo 2 con transformación logarítmica del precio y del área construida como modelo final de predicción. Aunque el Modelo 4 presentó mejores diagnósticos después de excluir temporalmente las observaciones 532 y 1266, se mantiene únicamente como análisis de sensibilidad, ya que no fue posible demostrar que dichos registros fueran errores y la heterocedasticidad persistió incluso después de retirarlos. Las pruebas de Breusch-Pagan por variable, White y Goldfeld-Quandt mostraron que la varianza restante se encuentra asociada principalmente con el área construida.

Para un apartamento de 300 m², 3 parqueaderos, 3 baños y 5 habitaciones, el Modelo 2 estima aproximadamente 590,0 millones de pesos para estrato 5 y 797,1 millones para estrato 6. Ambas estimaciones puntuales se encuentran por debajo del crédito máximo de 850 millones de pesos. Sin embargo, los intervalos de predicción alcanzan aproximadamente 397,9–874,7 millones en estrato 5 y 537,6–1.181,9 millones en estrato 6, de manera que existe una variabilidad importante en el precio de apartamentos individuales. El estrato 5 ofrece, por tanto, un mayor margen financiero frente al presupuesto.

Entre las ofertas observadas, Capri ID 6175 presenta el mejor equilibrio si se prioriza la cercanía al área requerida: dispone de 270 m², 3 parqueaderos, 3 baños y 4 habitaciones por 350 millones de pesos. Si la condición de 5 habitaciones tiene mayor prioridad, Seminario ID 8036 constituye una alternativa especialmente relevante, con 256 m², 3 parqueaderos, 5 baños y 5 habitaciones por 530 millones.

En consecuencia, se recomienda revisar inicialmente estas dos alternativas y ampliar la búsqueda dentro del estrato 5, donde el modelo y la oferta observada muestran una mayor holgura frente al presupuesto. Antes de una decisión definitiva deben verificarse la localización, el estado del inmueble y la información original de cada oferta.

5 Conclusiones y recomendaciones para C&A

El ejercicio se desarrolló de manera independiente para las dos solicitudes de vivienda. Por tanto, no corresponde seleccionar una vivienda frente a la otra, ya que representan necesidades diferentes de dos empleados. La recomendación general para C&A consiste en presentar para cada caso un precio de referencia, alternativas compatibles con el presupuesto y las principales limitaciones identificadas durante la modelación.

Para la Vivienda 1, correspondiente a una casa en Zona Norte, se seleccionó el Modelo 3 con transformación Box-Cox. Esta especificación fue la que presentó el mejor comportamiento diagnóstico: los residuos resultaron compatibles con normalidad, no se encontró evidencia de heterocedasticidad, la multicolinealidad se mantuvo baja y la influencia de observaciones particulares disminuyó considerablemente. Para una casa de 200 m², 1 parqueadero, 2 baños y 4 habitaciones, se estimó un precio aproximado de 335,2 millones de pesos en estrato 4 y 368,9 millones en estrato 5. Frente al crédito máximo de 350 millones, el estrato 4 representa el escenario inicialmente más compatible con la capacidad de financiación. Entre las ofertas identificadas, La Merced se destaca por la cercanía al área solicitada, mientras que Álamos y Vipasa presentan coincidencias exactas en parqueaderos, baños y habitaciones, aunque con diferencias mayores de área.

Para la Vivienda 2, correspondiente a un apartamento en Zona Sur, se conserva el Modelo 2 con transformación logarítmica como especificación final para la predicción. El Modelo 1 mostró problemas severos de normalidad, heterocedasticidad e influencia; el Modelo 2 mejoró de forma importante estos diagnósticos; y el Modelo 3 con Box-Cox produjo una mejora adicional en heterocedasticidad, pero no una ventaja global suficiente. Posteriormente, el Modelo 4 se utilizó como análisis de sensibilidad al excluir temporalmente las dos observaciones de mayor influencia. Este último redujo de manera marcada la distancia de Cook y el estadístico de Breusch-Pagan, pero las pruebas complementarias demostraron que la heterocedasticidad restante es estructural y se encuentra asociada principalmente con el área construida. Debido a que no fue posible verificar que las dos observaciones excluidas fueran errores, el Modelo 4 no reemplaza al Modelo 2 como especificación operativa.

Con el Modelo 2, el precio estimado para un apartamento de 300 m², 3 parqueaderos, 3 baños y 5 habitaciones es de aproximadamente 590,0 millones de pesos en estrato 5 y 797,1 millones en estrato 6, ambos por debajo del crédito máximo de 850 millones según la estimación puntual. No obstante, los intervalos de predicción son amplios, por lo que el estrato 5 ofrece un margen financiero más favorable. Entre las ofertas seleccionadas, Capri ID 6175 presenta la mayor cercanía al área solicitada y coincide en parqueaderos y baños, mientras que Seminario ID 8036 se destaca por cumplir exactamente con las 5 habitaciones y los 3 parqueaderos.

En ambos casos, las predicciones deben interpretarse como valores de referencia y no como precios exactos de mercado. La revisión de ofertas reales es indispensable porque existen características no incluidas en los modelos —como estado del inmueble, antigüedad, acabados, características del edificio o condiciones particulares de la ubicación— que pueden generar diferencias importantes de precio.

También se identificaron limitaciones relacionadas con la calidad de la información. En la Vivienda 1 se observaron posibles inconsistencias de georreferenciación, mientras que en la Vivienda 2 aparecieron dos registros con combinaciones extraordinarias de área y precio. Estos casos fueron estudiados mediante diagnósticos de influencia y análisis de sensibilidad, evitando eliminarlos automáticamente sin evidencia de error.

En conclusión, las dos solicitudes presentan alternativas potencialmente compatibles con sus respectivos presupuestos, aunque con diferentes niveles de incertidumbre. Para la Vivienda 1 se recomienda priorizar inicialmente el segmento de estrato 4 y revisar las ofertas más cercanas al perfil físico solicitado. Para la Vivienda 2 se recomienda priorizar inicialmente el estrato 5 y revisar especialmente las alternativas de Capri ID 6175 y Seminario ID 8036. En todos los casos, la decisión final debe complementar el resultado estadístico con la validación de las características reales, la ubicación y el estado de cada inmueble.

6 Referencias

6.1 Materiales de la asignatura

  • Actividad 2. (s. f.). Guía de la actividad del curso Modelos Estadísticos para la Toma de Decisiones.

  • Atípicos e influyentes: Punto atípico e influyente. (s. f.). Material de apoyo del curso Modelos Estadísticos para la Toma de Decisiones.

  • Modelo: Revisión de supuestos. (s. f.). Material de apoyo del curso Modelos Estadísticos para la Toma de Decisiones.

  • Predicción e intervalos: Intervalo de confianza. (s. f.). Material de apoyo del curso Modelos Estadísticos para la Toma de Decisiones.

  • Transformaciones. (s. f.). Material de apoyo del curso Modelos Estadísticos para la Toma de Decisiones.

6.2 Fuente de información

La base de datos de viviendas utilizada en el análisis fue suministrada como parte de la Actividad 2 de la asignatura. La información contiene características físicas, económicas y de localización de los inmuebles, entre ellas precio, área construida, número de habitaciones, baños, parqueaderos, estrato, tipo de vivienda, barrio, zona y coordenadas geográficas.

Para el desarrollo del ejercicio se trabajó exclusivamente con la información disponible en esta base. Las posibles inconsistencias identificadas durante el análisis, especialmente en algunos registros de georreferenciación y en combinaciones particulares de precio y área, fueron documentadas y evaluadas mediante los procedimientos estadísticos descritos en el informe.

6.3 Software y paquetes utilizados

El procesamiento, análisis estadístico y elaboración del informe se realizaron en R y R Markdown. Entre los principales paquetes utilizados se encuentran dplyr, ggplot2, plotly, leaflet, car, lmtest, MASS, knitr y kableExtra.

  • R Core Team. (s. f.). R: A language and environment for statistical computing. R Foundation for Statistical Computing.

  • Venables, W. N., & Ripley, B. D. (2002). Modern Applied Statistics with S (4th ed.). Springer.
    Paquete MASS, utilizado para la transformación Box-Cox.

  • Zeileis, A., & Hothorn, T. (2002). Diagnostic checking in regression relationships. R News, 2(3), 7–10.
    Paquete lmtest, utilizado para pruebas como Breusch-Pagan, Durbin-Watson y Goldfeld-Quandt.