library(readxl)
library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(knitr)
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.4.3
## 
## Adjuntando el paquete: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
library(RecordLinkage)
## Warning: package 'RecordLinkage' was built under R version 4.4.3
## Cargando paquete requerido: DBI
## Cargando paquete requerido: RSQLite
## Warning: package 'RSQLite' was built under R version 4.4.3
## Cargando paquete requerido: ff
## Warning: package 'ff' was built under R version 4.4.3
## Cargando paquete requerido: bit
## 
## Adjuntando el paquete: 'bit'
## The following object is masked from 'package:dplyr':
## 
##     symdiff
## The following object is masked from 'package:base':
## 
##     xor
## Attaching package ff
## - getOption("fftempdir")=="C:/Users/usuario/AppData/Local/Temp/Rtmpcdhk0d/ff"
## - getOption("ffextension")=="ff"
## - getOption("ffdrop")==TRUE
## - getOption("fffinonexit")==TRUE
## - getOption("ffpagesize")==65536
## - getOption("ffcaching")=="mmnoflush"  -- consider "ffeachflush" if your system stalls on large writes
## - getOption("ffbatchbytes")==16777216 -- consider a different value for tuning your system
## - getOption("ffmaxbytes")==536870912 -- consider a different value for tuning your system
## 
## Adjuntando el paquete: 'ff'
## The following objects are masked from 'package:utils':
## 
##     write.csv, write.csv2
## The following objects are masked from 'package:base':
## 
##     is.factor, is.ordered
## RecordLinkage library
## [c] IMBEI Mainz
## 
## Adjuntando el paquete: 'RecordLinkage'
## The following object is masked from 'package:bit':
## 
##     clone
## The following object is masked from 'package:base':
## 
##     isFALSE
library(leaflet)
## Warning: package 'leaflet' was built under R version 4.4.3
library(htmltools)
library(readxl)
datos <- read_excel("C:/Users/usuario/Downloads/Datos_Vivienda.xlsx")
View(datos)

Actividad en clase 9

id = 1:dim(datos)[1]
datos= data.frame(id,datos) ## Esre código genera una nueva columna llamada id, con los numeros desde el 1 asta el numero de filas de la tabla de datos, y luego agrega un numero a cada dato.

require(RecordLinkage)
# filtro 
#busca coicidencias de nombres similares : ej "villa del prado" 

pos = which(jarowinkler("ciudad jardin", datos$Barrio)>0.98)
datos_subdatos=datos[pos,]
head(datos_subdatos)
##    id     Zona piso Estrato precio_millon Area_contruida parqueaderos Banos
## 4   4 Zona Sur   NA       6          1280            346            4     6
## 7   7 Zona Sur    2       6           870            490            3     6
## 17 17 Zona Sur   NA       6           650            255            2     5
## 23 23 Zona Sur    1       6           850            300            4     6
## 24 24 Zona Sur   12       6           580            145            2     5
## 36 36 Zona Sur    3       6           595            146            2     4
##    Habitaciones        Tipo        Barrio cordenada_longitud Cordenada_latitud
## 4             5 Apartamento ciudad jardin          -76.46400           3.43300
## 7             5        Casa ciudad jardin          -76.46438           3.43463
## 17            5        Casa ciudad jardin          -76.46541           3.43312
## 23            4        Casa ciudad jardin          -76.46691           3.42334
## 24            3 Apartamento ciudad jardin          -76.46691           3.42334
## 36            4 Apartamento ciudad jardin          -76.46851           3.42544
library(dplyr)
names(datos_subdatos)
##  [1] "id"                 "Zona"               "piso"              
##  [4] "Estrato"            "precio_millon"      "Area_contruida"    
##  [7] "parqueaderos"       "Banos"              "Habitaciones"      
## [10] "Tipo"               "Barrio"             "cordenada_longitud"
## [13] "Cordenada_latitud"

Indicadores de centralidad

## Se calcula el promedio del precio, el area construida, las habitaciones,

## registros totales para el barrio ciudad jardin 
length(pos)
## [1] 540

Se puede observar que hay 540 casas en el barrio Ciudad Jardin

Analisis exploratorio

require(leaflet)
#мара 2

#Etiqueta enriquecida (Tabel) muestra información detallada del punto, incluyendo:

#ID del inmueble.
#precio en millones.
#Área construida.
#Barrio.
#Latitud y longitud.
#Añade un fondo de mapa base → addtiles()

leaflet() %>% addCircleMarkers(lng = datos_subdatos$cordenada_longitud, lat = datos_subdatos$Cordenada_latitud, radius
= 1, color = "orange", label = paste0( 'ID',datos_subdatos$ID, 'Precio:', datos_subdatos$precio_millon,'Area:',
datos_subdatos$Area_contruida, 'Barrio:', datos_subdatos$Barrio,' Lat: ' ,datos_subdatos$Cordenada_latitud, 'Long:',datos_subdatos$cordenada_longitud)) %>% addTiles()

El mapa permite observar el lugar en el que se encuentran las casas del barrio Ciudad Jardin

Promedio de precios de las viviendas del barrio Ciudad Jardin

## Indicadores de centralidad y variabilidad para la variable "precio"
promedio_precio=mean (datos_subdatos$precio_millon,na.rm = TRUE)
mediana_precio=median(datos_subdatos$precio_millon,na.rm = TRUE)
minimo_precio=min(datos_subdatos$precio_millon,na.rm = TRUE)
maximo_precio= max(datos_subdatos$precio_millon,na.rm  = TRUE)
desvest_precio=sd(datos_subdatos$precio_millon, na.rm = TRUE)
indic_precio=data.frame(promedio_precio,mediana_precio, minimo_precio, maximo_precio, desvest_precio)
indic_precio
##   promedio_precio mediana_precio minimo_precio maximo_precio desvest_precio
## 1        753.4148            680           180          1900       375.4101

Se puede observar que en promedio, las viviendas de este barrio cuestan alrededor de los 753 millones de pesos, con una desviación de 375,41 millones. La casa más barata en el barrio es de 180 millones, y la más cara es de 1900 millones

library(plotly)
## Warning: package 'plotly' was built under R version 4.4.3
## 
## Adjuntando el paquete: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
g1=ggplot(data = datos_subdatos, mapping = aes(x=precio_millon))+ geom_histogram(fill="orange")+theme_bw()
ggplotly(g1)
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Se puede observar que una hay una alta concentración de viviendas con precios entre 296 y 830 millones, especialmente alrededor de los 474 millones, es decir, en este caso, la barra más alta.Esto indica que la mayoría de las propiedades ofertadas en el barrio están en ese rango de precio

Analisis bivariado

library(ggplot2)
library(plotly)

# Crear gráfico interactivo con correlación
ggplotly(
  ggplot(datos_subdatos, aes(x = Area_contruida, y = precio_millon)) +
    geom_point(color = "orange", alpha = 0.8, size = 2) +  # Puntos con color y transparencia
    geom_smooth(method = "loess", color = "grey", se = TRUE) +  # Línea de tendencia
    labs(
      title = paste("Figura 5. Relación entre Área Construida y Precio\nCoef. de correlación:",
                    round(cor(datos_subdatos$precio_millon, datos_subdatos$Area_contruida, use = "complete.obs"), 2)),
      x = "Área Construida (m²)",
      y = "Precio (Millones)",
      caption = "Fuente: Datos de Vivienda"
    ) +
    theme_minimal() +
    theme(
      plot.title = element_text(size = 14, face = "bold", hjust = 0.5),
      axis.title = element_text(size = 12),
      axis.text = element_text(size = 10)
    )
)
## `geom_smooth()` using formula = 'y ~ x'

La gráfica permite evidenciar la relación entre el precio de la vivienda y el área construida. Se observa un coeficiente de correlación alto, en este caso, de 0.73, es decir, que el área construida puede ser un factor determinante para la determinación del precio de la vivienda en el barrio

Modelo de regresion multiple

mod2 = lm(precio_millon~Area_contruida + Habitaciones + Banos , data =  datos_subdatos)
summary (mod2)
## 
## Call:
## lm(formula = precio_millon ~ Area_contruida + Habitaciones + 
##     Banos, data = datos_subdatos)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -771.17 -134.47  -49.06   85.52 1042.74 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    145.15593   39.72259   3.654 0.000283 ***
## Area_contruida   1.16000    0.07523  15.420  < 2e-16 ***
## Habitaciones    -7.83047   14.39232  -0.544 0.586618    
## Banos           81.86612   11.07142   7.394 5.51e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 240.4 on 536 degrees of freedom
## Multiple R-squared:  0.5922, Adjusted R-squared:  0.5899 
## F-statistic: 259.4 on 3 and 536 DF,  p-value: < 2.2e-16

Como se puede observar las variables predictoras área construida y baños son altamente significativos en el modelo para prededir el precio de la vivienda.

Evaluación del modelo

R² = 0.5922 El modelo explica aproximadamente el 59.22% % de la variabilidad en el precio, lo cual es aceptable.

p-value < 2.2e-16 El modelo es estadísticamente significativo

Conclusión:Este modelo muestra que el impacto del número de baños y el área construida en el precio es significativo

Seleccion de Variables

mod_multiple2=step(mod2)
## Start:  AIC=5924.95
## precio_millon ~ Area_contruida + Habitaciones + Banos
## 
##                  Df Sum of Sq      RSS    AIC
## - Habitaciones    1     17110 30997888 5923.2
## <none>                        30980778 5924.9
## - Banos           1   3160309 34141087 5975.4
## - Area_contruida  1  13743852 44724629 6121.2
## 
## Step:  AIC=5923.24
## precio_millon ~ Area_contruida + Banos
## 
##                  Df Sum of Sq      RSS    AIC
## <none>                        30997888 5923.2
## - Banos           1   4343974 35341862 5992.1
## - Area_contruida  1  14077285 45075173 6123.4
summary(mod2)
## 
## Call:
## lm(formula = precio_millon ~ Area_contruida + Habitaciones + 
##     Banos, data = datos_subdatos)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -771.17 -134.47  -49.06   85.52 1042.74 
## 
## Coefficients:
##                 Estimate Std. Error t value Pr(>|t|)    
## (Intercept)    145.15593   39.72259   3.654 0.000283 ***
## Area_contruida   1.16000    0.07523  15.420  < 2e-16 ***
## Habitaciones    -7.83047   14.39232  -0.544 0.586618    
## Banos           81.86612   11.07142   7.394 5.51e-13 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 240.4 on 536 degrees of freedom
## Multiple R-squared:  0.5922, Adjusted R-squared:  0.5899 
## F-statistic: 259.4 on 3 and 536 DF,  p-value: < 2.2e-16

Se observa que solo dos de las variables seleccionadas influyen de manera fuerte en la determianción del precio dela vivienda, y en este caso, es necesario eliminar la variable Habitaciones.

Validacion de supuestos

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

1. Residuos vs Ajustados (arriba izquierda)

Se observa una ligera curvatura descendente en los extremos, lo que sugiere una posible no linealidad o la omisión de algún efecto no capturado por el modelo. La dispersión parece más alta en los valores intermedios de los valores ajustados, lo que podría ser un indicio de heterocedasticidad, aunque menos pronunciada que en el caso anterior.

2. Q-Q Plot (arriba derecha)

Los residuos siguen en su mayoría la línea diagonal, pero hay desviaciones evidentes en ambas colas, lo que indica que los residuos extremos no siguen una distribución normal. Esto podría afectar la validez de los supuestos del modelo respecto a la normalidad de errores.

3. Scale-Location (abajo izquierda)

La línea roja muestra un leve patrón ascendente, indicando nuevamente que la varianza de los errores puede no ser constante (heterocedasticidad). Aunque no es muy fuerte, sí sugiere que sería útil verificar si una transformación de variables puede mejorar el ajuste.

4. Residuos vs Leverage (abajo derecha)

Hay unas pocas observaciones con valores de leverage moderados y residuos estandarizados altos, como las observaciones 5881, 5843 y 4590, pero ninguna excede el umbral crítico de Cook’s distance (>1). Esto sugiere que no hay observaciones extremadamente influyentes, aunque esas identificadas podrían revisarse para ver si están afectando el modelo de forma desproporcionada.

Conclusión general

El modelo parece relativamente adecuado, pero hay indicios de leve heterocedasticidad y no normalidad en los residuos extremos. Sería recomendable explorar transformaciones (como logaritmos o raíces cuadradas de las variables dependientes o independientes) para mejorar el cumplimiento de los supuestos. Además, es conveniente revisar las observaciones con alto leverage y residuos grandes para asegurarse de que no estén distorsionando el ajuste

Tranformacion del modelo

mod3=lm(log(precio_millon)~log(Area_contruida)+Habitaciones+Banos,data = datos_subdatos)
summary (mod3)
## 
## Call:
## lm(formula = log(precio_millon) ~ log(Area_contruida) + Habitaciones + 
##     Banos, data = datos_subdatos)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.82723 -0.15763 -0.02034  0.14305  0.88660 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)          3.16311    0.10695  29.574  < 2e-16 ***
## log(Area_contruida)  0.59362    0.02531  23.453  < 2e-16 ***
## Habitaciones        -0.03305    0.01488  -2.221   0.0267 *  
## Banos                0.07006    0.01213   5.778 1.29e-08 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2479 on 536 degrees of freedom
## Multiple R-squared:  0.7407, Adjusted R-squared:  0.7392 
## F-statistic: 510.3 on 3 and 536 DF,  p-value: < 2.2e-16

Se puede observar que en el modelo, la variable habitaciones es poco significativa, por lo que se va a eliminar

Modelo final

Transformacion del modelo

mod_fin=lm(log(precio_millon)~log(Area_contruida)+Banos,data = datos_subdatos)
summary (mod_fin)
## 
## Call:
## lm(formula = log(precio_millon) ~ log(Area_contruida) + Banos, 
##     data = datos_subdatos)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.80832 -0.16147 -0.01848  0.14251  0.89773 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)          3.15728    0.10731  29.421  < 2e-16 ***
## log(Area_contruida)  0.58217    0.02487  23.407  < 2e-16 ***
## Banos                0.05630    0.01046   5.381 1.11e-07 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.2488 on 537 degrees of freedom
## Multiple R-squared:  0.7383, Adjusted R-squared:  0.7373 
## F-statistic: 757.5 on 2 and 537 DF,  p-value: < 2.2e-16
par(mfrow=c(2,2))
plot(mod_fin)

1. Residuos vs Ajustados (arriba izquierda)

La gráfica muestra que los residuos están relativamente centrados alrededor de cero, sin una curvatura evidente. Esto sugiere que el supuesto de linealidad se cumple razonablemente bien. Sin embargo, hay algo de dispersión irregular (ligero embudo), lo que podría sugerir una leve heterocedasticidad, aunque no muy marcada.

2. Q-Q Plot (arriba derecha)

Los residuos siguen bastante bien la línea diagonal, con ligeras desviaciones solo en las colas. Esto indica que la normalidad de los errores se cumple en gran parte, salvo por algunos valores extremos. No es una preocupación mayor, pero podría mejorarse con una transformación si es necesario un cumplimiento estricto.

3. Scale-Location (abajo izquierda)

La línea roja es prácticamente plana, lo que sugiere que la varianza de los residuos es bastante constante a lo largo de los valores ajustados. Esto indica buen cumplimiento del supuesto de homocedasticidad, mejor que en los casos anteriores.

4. Residuos vs Leverage (abajo derecha)

Las observaciones identificadas (como las 8460, 4590) tienen cierto nivel de leverage, pero ninguna supera los umbrales críticos de Cook’s distance. Esto implica que no hay puntos influyentes extremos, aunque sería útil revisar esas observaciones por si aportan información relevante.

Conclusión general

Este modelo parece ser el mejor ajustado de los tres evaluados. Los residuos se distribuyen razonablemente bien, hay poca evidencia de heterocedasticidad y la normalidad de los errores es aceptable. Aunque hay algunas observaciones con mayor leverage, no hay señales de influencia extrema. En general, no se requiere una transformación urgente, aunque seguir monitoreando las observaciones atípicas puede ser útil.

Conclusiones generales

El modelo parece estar mejor ajustado que antes, ya que se evidencia mayor linealidad, normalidad y varianza constante

Pronostico hipotetico

¿Que pasa al predecir con este modelo transformado, por ejemplo cual seria el precio de una vivienda con 100 m2 de area construida y 5 Baños?

y_log=predict(mod_fin,list(Area_contruida=100, Banos=5))
exp(y_log)
##        1 
## 454.7816

El precio de una vivienda que tenga 100 m2 de área construida y 5 baños es aproximadamente de 454 millones

x_log=predict(mod_fin,list(Area_contruida=100, Banos=6))
exp(x_log)
##        1 
## 481.1227

El precio de una vivienda que tenga 100 m2 de área construida y 6 baños es aproximadamente de 454 millones

Se puede observar que al aumentar en una unidad el numero de baños, el precio de la vivienda se incrementa en 27 millones

¿Para qué sirve este pronóstico y como se monetizaría?

Este pronóstico nos sirve para identificar que el número de baños es un factor influyente para determinar el precio de la vivienda en el barrio Ciudad Jardin. En este caso, si una constructora conoce esta información, podría empeñarse en construir casas con mayor número de baños para poder cobrar más por ellas.