Pregunta de investigación: ¿El precio anunciado de las casas en Pance está más relacionado con el espacio disponible, la dotación de baños o la capacidad de parqueo?
El mercado de casas de Pance combina extensiones construidas importantes y diferentes configuraciones de comodidad. Un mayor espacio no necesariamente se traduce en el mismo aumento monetario para todas las propiedades: los baños y la posibilidad de estacionar varios vehículos pueden ofrecer información adicional.
La variable dependiente es
precio_millon, expresada en
millones de pesos colombianos. Se propone una regresión
lineal sobre precios anunciados, no sobre ventas
efectivas. La posible usuaria del análisis es una inmobiliaria que
necesita construir rangos de referencia para asesorar a propietarios de
casas de alta gama. La interpretación será de asociación estadística, no
de causalidad.
Hipótesis general: algunas características físicas de las viviendas del mismo barrio se asocian con variaciones del precio publicado, pero esas relaciones pueden perder utilidad ante observaciones extremas o elementos no medidos como calidad de acabados, ubicación microterritorial y estado del inmueble.
Esta fase se ejecuta en R a partir del Excel original. El criterio de inclusión es barrio Pance y tipo casas; se descartan observaciones con precio, área u otras variables indispensables faltantes o imposibles y, después, duplicados exactos en las columnas originales. No se eliminan automáticamente las viviendas caras o grandes por ser atípicas.
La variable parqueaderos puede faltar; se exige que esté registrada para asegurar una muestra común a todos los modelos. No se exige piso porque muchas casas no tienen ese dato y no forma parte de las hipótesis.
if (!file.exists("Datos_Vivienda.xlsx")) stop("Falta Datos_Vivienda.xlsx: descomprime TODO el ZIP y abre el proyecto .Rproj de esta carpeta.")
if (!requireNamespace("readxl",quietly=TRUE)) stop("Instala readxl: install.packages('readxl')")
base_original <- as.data.frame(readxl::read_excel("Datos_Vivienda.xlsx", sheet="Datos Vivienda"))
base_original$id_original <- seq_len(nrow(base_original))+1L
columnas_base <- setdiff(names(base_original),"id_original")
for (v in c("precio_millon","Area_contruida","Banos","Habitaciones","parqueaderos","piso","Estrato")) {
base_original[[v]] <- suppressWarnings(as.numeric(as.character(base_original[[v]])))
}
candidatos <- base_original[tolower(trimws(base_original$Barrio))=="pance" &
tolower(trimws(base_original$Tipo))=="casa",,drop=FALSE]
filas_validas <- with(candidatos,
is.finite(precio_millon) & precio_millon>0 &
is.finite(Area_contruida) & Area_contruida>0 &
is.finite(Banos) & Banos>=1 &
is.finite(Habitaciones) & Habitaciones>=1 &
is.finite(parqueaderos) & parqueaderos>=0)
validos <- candidatos[filas_validas,,drop=FALSE]
repetidos <- duplicated(validos[,columnas_base,drop=FALSE])
datos <- validos[!repetidos,,drop=FALSE]
datos$garaje_amplio <- as.integer(datos$parqueaderos>=4)
datos$fold <- as.integer((datos$id_original*73+17) %% 5)+1L
stopifnot(nrow(datos)>30L)
knitr::kable(data.frame(
Etapa=c("Base completa","Casas en Pance","Registros válidos","Anuncios finales sin duplicados"),
Registros=c(nrow(base_original),nrow(candidatos),nrow(validos),nrow(datos))),
caption="Trazabilidad del filtro aplicado en R")
| Etapa | Registros |
|---|---|
| Base completa | 8319 |
| Casas en Pance | 206 |
| Registros válidos | 200 |
| Anuncios finales sin duplicados | 200 |
La muestra analítica final contiene 200 anuncios, frente a 206 registros originalmente filtrados por barrio y tipo. La pérdida de 6 registros se explica por requisitos de completitud, valores inválidos y/o duplicados exactos. No es una muestra aleatoria representativa de todas las ventas del barrio.
relevantes <- c("precio_millon","Area_contruida","Banos","Habitaciones")
relevantes <- c(relevantes, if ("piso" %in% names(datos) && "estrato_alto" %in% names(datos)) c("piso","Estrato") else "parqueaderos")
faltantes_candidatos <- data.frame(Variable=relevantes,
N_faltantes=sapply(candidatos[relevantes],function(x)sum(!is.finite(x))))
knitr::kable(faltantes_candidatos,caption="Calidad original de las variables indispensables")
| Variable | N_faltantes | |
|---|---|---|
| precio_millon | precio_millon | 0 |
| Area_contruida | Area_contruida | 0 |
| Banos | Banos | 0 |
| Habitaciones | Habitaciones | 0 |
| parqueaderos | parqueaderos | 6 |
cat("**Lectura de calidad.** Las filas se retiraron únicamente por la ausencia o invalidez de las variables necesarias para comparar los modelos en idénticas observaciones. La exclusión de anuncios incompletos puede inducir sesgo si estos anuncios corresponden a segmentos particulares del mercado.\n\n")
## **Lectura de calidad.** Las filas se retiraron únicamente por la ausencia o invalidez de las variables necesarias para comparar los modelos en idénticas observaciones. La exclusión de anuncios incompletos puede inducir sesgo si estos anuncios corresponden a segmentos particulares del mercado.
Para cada variable se presentan tendencia central, dispersión y rango. La unidad de precio siempre es millones de COP y la unidad de área es m².
vars_numericas <- c("precio_millon","Area_contruida","Banos","Habitaciones")
vars_numericas <- c(vars_numericas, if ("estrato_alto" %in% names(datos)) c("piso","Estrato") else "parqueaderos")
resumen_descriptivo <- do.call(rbind,lapply(vars_numericas,function(v){
x <- datos[[v]]
data.frame(Variable=v,N=length(x),Min=min(x),P25=unname(quantile(x,.25)),
Media=mean(x),Mediana=median(x),P75=unname(quantile(x,.75)),
Max=max(x),Desv=sd(x))
}))
resumen_redondeado <- resumen_descriptivo
resumen_redondeado[-1] <- lapply(resumen_redondeado[-1],round,2)
knitr::kable(resumen_redondeado, caption="Estadísticos de las viviendas seleccionadas")
| Variable | N | Min | P25 | Media | Mediana | P75 | Max | Desv |
|---|---|---|---|---|---|---|---|---|
| precio_millon | 200 | 460 | 840 | 1118.14 | 1100.0 | 1350 | 1900 | 372.92 |
| Area_contruida | 200 | 128 | 274 | 403.64 | 348.5 | 461 | 1500 | 223.54 |
| Banos | 200 | 2 | 4 | 5.14 | 5.0 | 6 | 7 | 1.00 |
| Habitaciones | 200 | 3 | 4 | 4.20 | 4.0 | 5 | 7 | 0.82 |
| parqueaderos | 200 | 1 | 2 | 3.75 | 4.0 | 4 | 10 | 1.66 |
Interpretación de tendencia central: el precio medio anunciado es de 1.118,14 millones, frente a una mediana de 1.100,00 millones. La distancia entre ambas resume la posible asimetría del mercado. El 50 % central de los precios se sitúa aproximadamente entre 840,00 y 1.350,00 millones; no deben confundirse estos valores con precios de venta negociados.
par(mfrow=c(1,2),mar=c(4,4,3,1))
hist(datos$precio_millon,breaks="FD",col="#D8E5F0",border="white",
main="Precios anunciados",xlab="Millones de COP")
hist(datos$Area_contruida,breaks="FD",col="#D3E9DE",border="white",
main="Áreas construidas",xlab="Metros cuadrados")
par(mfrow=c(1,1))
Interpretación de histogramas: el primero muestra si el precio se concentra alrededor de un rango o si existe una cola de inmuebles caros. El segundo permite comprobar si las áreas típicas son homogéneas o si unos pocos inmuebles muy grandes pueden dominar la pendiente de una recta. El mercado de casas de Pance combina extensiones construidas importantes y diferentes configuraciones de comodidad. Un mayor espacio no necesariamente se traduce en el mismo aumento monetario para todas las propiedades: los baños y la posibilidad de estacionar varios vehículos pueden ofrecer información adicional.
par(mfrow=c(1,2),mar=c(4,4,3,1))
boxplot(datos$precio_millon,horizontal=TRUE,col="#BDD1E4",main="Precio",
xlab="Millones COP")
boxplot(datos$Area_contruida,horizontal=TRUE,col="#B8DFC8",main="Área",
xlab="m²")
par(mfrow=c(1,1))
fence <- function(x) {
q <- quantile(x,c(.25,.75)); c(inferior=q[1]-1.5*IQR(x),superior=q[2]+1.5*IQR(x))
}
p_at <- fence(datos$precio_millon)
a_at <- fence(datos$Area_contruida)
conteo_p <- sum(datos$precio_millon<p_at[1]|datos$precio_millon>p_at[2])
conteo_a <- sum(datos$Area_contruida<a_at[1]|datos$Area_contruida>a_at[2])
knitr::kable(data.frame(Variable=c("Precio","Área"),
Limite_inferior=c(p_at[1],a_at[1]),Limite_superior=c(p_at[2],a_at[2]),
Fuera_de_limites=c(conteo_p,conteo_a)),digits=2,caption="Alertas de atípicos por 1,5 × IQR")
| Variable | Limite_inferior | Limite_superior | Fuera_de_limites |
|---|---|---|---|
| Precio | 75.0 | 2115.0 | 0 |
| Área | -6.5 | 741.5 | 13 |
Interpretación del boxplot y atípicos: se marcaron 0 precios y 13 áreas fuera de los límites IQR. Son alertas, no una prueba de error de digitación; una vivienda grande puede ser legítima. Se conservan y se examina su impacto por el diagnóstico de influencia y la validación cruzada. En particular, el área máxima observada es 1.500,00 m².
Advertencia específica de Pance: las casas tienen tamaños y dotaciones heterogéneos, de modo que el modelo puede subestimar una casa especialmente equipada o sobreestimar otra más sencilla. Los metros cuadrados no reflejan por sí solos la calidad de construcción ni el tamaño de lote.
Las asociaciones de Pearson evalúan relaciones lineales; no prueban causalidad. En cada diagrama, la recta roja es el ajuste lineal simple estimado con las observaciones del barrio.
variables_simple <- c("Area_contruida","Banos","parqueaderos")
correlaciones <- data.frame(Predictor=variables_simple,
Correlacion_Pearson=sapply(variables_simple,function(x)cor(datos$precio_millon,datos[[x]])))
knitr::kable(correlaciones,digits=3,caption="Correlaciones de Pearson con el precio")
| Predictor | Correlacion_Pearson | |
|---|---|---|
| Area_contruida | Area_contruida | 0.526 |
| Banos | Banos | 0.415 |
| parqueaderos | parqueaderos | 0.467 |
par(mfrow=c(1,3),mar=c(4,4,3,1))
for (v in variables_simple) {
plot(jitter(datos[[v]]),datos$precio_millon,pch=19,cex=.55,
col=rgb(.10,.25,.40,.28), xlab=v,ylab="Precio (millones COP)",main=paste("Precio vs",v))
abline(lm(reformulate(v,"precio_millon"),data=datos),col="#BF5151",lwd=2)
}
par(mfrow=c(1,1))
Lectura de los tres diagramas: una nube ascendente sugiere asociación positiva, pero una gran dispersión vertical indica que inmuebles similares pueden tener precios muy distintos. En predictores discretos (baños, habitaciones, piso o parqueaderos) aparecen columnas de puntos; se agregó una pequeña separación visual para apreciar la concentración, sin modificar los datos usados en la regresión. Las correlaciones se interpretan junto al modelo y no de forma aislada.
Los tres modelos mantienen la misma Y y usan predictores distintos. Cada coeficiente expresa una diferencia promedio asociada, no un cambio que necesariamente ocurrirá si se modifica físicamente un inmueble.
s1 <- lm(precio_millon ~ Area_contruida, data=datos)
s2 <- lm(precio_millon ~ Banos, data=datos)
s3 <- lm(precio_millon ~ parqueaderos, data=datos)
modelos_simples <- list("Modelo simple 1"=s1,"Modelo simple 2"=s2,"Modelo simple 3"=s3)
mapa <- c("Area_contruida"="área construida (m²)","Banos"="baños","Habitaciones"="habitaciones","parqueaderos"="parqueaderos","garaje_amplio"="parqueaderos amplios (1=4 o más)")
for (nm in names(modelos_simples)) {
cat("\n\n### ",nm,"\n\n",sep="")
print(summary(modelos_simples[[nm]]))
lectura_coef(modelos_simples[[nm]],nm,mapa)
}
Call: lm(formula = precio_millon ~ Area_contruida, data = datos)
Residuals: Min 1Q Median 3Q Max -761.30 -242.77 -54.77 183.08 842.07
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 764.0511 46.5031 16.430 < 2e-16
Area_contruida 0.8772 0.1008 8.699 1.29e-15 — Signif.
codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’
1
Residual standard error: 318 on 198 degrees of freedom Multiple R-squared: 0.2765, Adjusted R-squared: 0.2729 F-statistic: 75.67 on 1 and 198 DF, p-value: 1.29e-15
Interpretación completa de Modelo simple 1.
Intercepto: 764,05 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
área construida (m²): manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 0,88 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
Ajuste: R² = 27,65 % y R² ajustado = 27,29 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
Call: lm(formula = precio_millon ~ Banos, data = datos)
Residuals: Min 1Q Median 3Q Max -678.00 -248.52 -41.75 225.54 958.25
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 320.08 126.64 2.528 0.0123 *
Banos 155.42 24.21 6.419 9.94e-10 *** — Signif. codes: 0 ‘’
0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1
Residual standard error: 340.1 on 198 degrees of freedom Multiple R-squared: 0.1722, Adjusted R-squared: 0.1681 F-statistic: 41.2 on 1 and 198 DF, p-value: 9.938e-10
Interpretación completa de Modelo simple 2.
Intercepto: 320,08 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
baños: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 155,42 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
Ajuste: R² = 17,22 % y R² ajustado = 16,81 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
Call: lm(formula = precio_millon ~ parqueaderos, data = datos)
Residuals: Min 1Q Median 3Q Max -603.58 -264.49 -48.94 213.99 964.97
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 725.75 57.73 12.571 < 2e-16 parqueaderos
104.64 14.08 7.434 3.11e-12 — Signif. codes: 0
‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1
Residual standard error: 330.6 on 198 degrees of freedom Multiple R-squared: 0.2182, Adjusted R-squared: 0.2142 F-statistic: 55.26 on 1 and 198 DF, p-value: 3.112e-12
Interpretación completa de Modelo simple 3.
Intercepto: 725,75 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
parqueaderos: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 104,64 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
Ajuste: R² = 21,82 % y R² ajustado = 21,42 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
for (nm in names(modelos_simples)) {
cat("\n\n### Diagnóstico: ",nm,"\n\n",sep="")
mostrar_diagnostico(modelos_simples[[nm]],nm)
}
Interpretación diagnóstica — Modelo simple 1. Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,0066: hay señales de varianza no constante, lo que limita la confianza en errores estándar clásicos. Observaciones con Cook > 4/n: 8. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
Interpretación diagnóstica — Modelo simple 2. Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,5380: no se detecta heterocedasticidad con esta prueba, aunque conviene revisar el gráfico de residuos. Observaciones con Cook > 4/n: 8. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
Interpretación diagnóstica — Modelo simple 3. Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,6977: no se detecta heterocedasticidad con esta prueba, aunque conviene revisar el gráfico de residuos. Observaciones con Cook > 4/n: 13. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
Los cuatro paneles usados en cada modelo son: residuos frente a valores ajustados (linealidad y varianza), Q-Q normal (forma de los errores), Scale-Location (dispersión de errores) y residuos frente a leverage (puntos influyentes). Se debe revisar el conjunto de evidencias: una sola prueba no confirma todos los supuestos.
Comparamos la especificación original con precio ~ log(área) y log(precio) ~ log(área). La primera conserva el precio en millones de pesos y interpreta cambios porcentuales de área. La segunda modela elasticidad precio-área. En los modelos con logaritmo del precio, no se compara directamente el R² con el de Y original; se retransfieren predicciones para evaluar MAE en millones de COP.
log_x_simple <- lm(precio_millon ~ log(Area_contruida),data=datos)
log_yx_simple <- lm(log(precio_millon) ~ log(Area_contruida),data=datos)
print(summary(log_x_simple))
Call: lm(formula = precio_millon ~ log(Area_contruida), data = datos)
Residuals: Min 1Q Median 3Q Max -759.51 -194.79 -39.25 131.37 815.32
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) -1864.99 246.87 -7.555 1.52e-12
log(Area_contruida) 507.33 41.84 12.124 < 2e-16 —
Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’
0.1 ’ ’ 1
Residual standard error: 283.2 on 198 degrees of freedom Multiple R-squared: 0.4261, Adjusted R-squared: 0.4232 F-statistic: 147 on 1 and 198 DF, p-value: < 2.2e-16
lectura_coef(log_x_simple,"precio ~ log(área)",mapa)
Interpretación completa de precio ~ log(área).
Intercepto: -1.864,99 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
Logaritmo del área: un aumento aproximado del 1 % en el área se asocia con 5,05 millones de pesos de cambio en el precio anunciado, manteniendo las otras variables constantes; hay evidencia estadística de una asociación (p < 0,05).
Ajuste: R² = 42,61 % y R² ajustado = 42,32 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
print(summary(log_yx_simple))
Call: lm(formula = log(precio_millon) ~ log(Area_contruida), data = datos)
Residuals: Min 1Q Median 3Q Max -0.70059 -0.18289 -0.00836 0.16589 0.62160
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.99071 0.21836 18.28 <2e-16
log(Area_contruida) 0.50520 0.03701 13.65 <2e-16 —
Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’
0.1 ’ ’ 1
Residual standard error: 0.2505 on 198 degrees of freedom Multiple R-squared: 0.4848, Adjusted R-squared: 0.4822 F-statistic: 186.3 on 1 and 198 DF, p-value: < 2.2e-16
cat("**Elasticidad log-log:** el coeficiente del área es ",
formatear(coef(log_yx_simple)["log(Area_contruida)"]),
". Esto representa aproximadamente ese porcentaje de variación del precio anunciado ante un 1 % de diferencia en área, sin atribuir causalidad.\n\n",sep="")
Elasticidad log-log: el coeficiente del área es 0,51. Esto representa aproximadamente ese porcentaje de variación del precio anunciado ante un 1 % de diferencia en área, sin atribuir causalidad.
mostrar_diagnostico(log_x_simple,"precio ~ log(área)")
Interpretación diagnóstica — precio ~ log(área). Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = < 0,001: hay señales de varianza no constante, lo que limita la confianza en errores estándar clásicos. Observaciones con Cook > 4/n: 8. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
mostrar_diagnostico(log_yx_simple,"log(precio) ~ log(área)")
Interpretación diagnóstica — log(precio) ~ log(área). Shapiro-Wilk p = 0,0577: no se detecta evidencia suficiente contra la normalidad; eso no demuestra normalidad perfecta. Breusch-Pagan auxiliar p = 0,0084: hay señales de varianza no constante, lo que limita la confianza en errores estándar clásicos. Observaciones con Cook > 4/n: 10. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
Modelo múltiple 1: precio ~ Area_contruida + Banos + Habitaciones. Evalúa qué características conservan asociación con el precio cuando se mantienen las otras constantes.
Modelo múltiple 2: precio ~ Area_contruida + Banos +
Habitaciones + garaje_amplio. Incorpora explícitamente una variable
dummy: garaje_amplio. Se asigna 1 si la
casa anuncia cuatro o más parqueaderos y 0 si anuncia entre uno y
tres.
La dummy compara casas con capacidad amplia de estacionamiento frente a las de menor capacidad, manteniendo constantes las demás características. Es una diferencia asociada, no el efecto causal de construir un garaje.
m1 <- lm(precio_millon ~ Area_contruida + Banos + Habitaciones,data=datos)
m2 <- lm(precio_millon ~ Area_contruida + Banos + Habitaciones + garaje_amplio,data=datos)
print(summary(m1))
Call: lm(formula = precio_millon ~ Area_contruida + Banos + Habitaciones, data = datos)
Residuals: Min 1Q Median 3Q Max -662.45 -228.22 -69.49 188.08 873.05
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 336.1241 129.2067 2.601 0.00999 ** Area_contruida 0.7294
0.1013 7.200 1.26e-11 Banos 114.3151 26.1942 4.364 2.06e-05
Habitaciones -23.6703 30.4447 -0.777 0.43781
— Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05
‘.’ 0.1 ’ ’ 1
Residual standard error: 303.3 on 196 degrees of freedom Multiple R-squared: 0.3484, Adjusted R-squared: 0.3384 F-statistic: 34.93 on 3 and 196 DF, p-value: < 2.2e-16
lectura_coef(m1,"Modelo múltiple 1",mapa)
Interpretación completa de Modelo múltiple 1.
Intercepto: 336,12 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
área construida (m²): manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 0,73 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
baños: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 114,32 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
habitaciones: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 23,67 millones de pesos menos en el precio anunciado; no existe evidencia estadística suficiente al 5 %. No conviene afirmar que existe un efecto real con este resultado.
Ajuste: R² = 34,84 % y R² ajustado = 33,84 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
print(summary(m2))
Call: lm(formula = precio_millon ~ Area_contruida + Banos + Habitaciones + garaje_amplio, data = datos)
Residuals: Min 1Q Median 3Q Max -673.83 -220.96 -75.61 145.88 827.99
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 337.6440 125.3424 2.694 0.007681 ** Area_contruida 0.6298
0.1020 6.174 3.79e-09 Banos 105.2034 25.5334 4.120 5.59e-05
Habitaciones -25.6007 29.5388 -0.867 0.387181
garaje_amplio 162.7460 44.6695 3.643 0.000345 *** — Signif. codes: 0
‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1
Residual standard error: 294.2 on 195 degrees of freedom Multiple R-squared: 0.3899, Adjusted R-squared: 0.3774 F-statistic: 31.16 on 4 and 195 DF, p-value: < 2.2e-16
lectura_coef(m2,"Modelo múltiple 2 (con dummy)",mapa)
Interpretación completa de Modelo múltiple 2 (con dummy).
Intercepto: 337,64 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
área construida (m²): manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 0,63 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
baños: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 105,20 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
habitaciones: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 25,60 millones de pesos menos en el precio anunciado; no existe evidencia estadística suficiente al 5 %. No conviene afirmar que existe un efecto real con este resultado.
parqueaderos amplios (1=4 o más): manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 162,75 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
Ajuste: R² = 38,99 % y R² ajustado = 37,74 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
knitr::kable(data.frame(Modelo=c("Múltiple 1","Múltiple 2"),
R2=c(summary(m1)$r.squared,summary(m2)$r.squared),
R2_ajustado=c(summary(m1)$adj.r.squared,summary(m2)$adj.r.squared),
AIC=c(AIC(m1),AIC(m2))),digits=3,
caption="Comparación de ajuste y complejidad (misma Y y mismas filas)")
| Modelo | R2 | R2_ajustado | AIC |
|---|---|---|---|
| Múltiple 1 | 0.348 | 0.338 | 2859.453 |
| Múltiple 2 | 0.390 | 0.377 | 2848.282 |
Interpretación del contraste: una mejoría en R² al añadir predictores es esperable; por eso debe revisarse también el R² ajustado, el AIC y, sobre todo, el MAE fuera de muestra. Los coeficientes que pierdan significancia al incluir otras variables pueden reflejar correlación entre características, no ausencia absoluta de relación.
mostrar_diagnostico(m1,"Múltiple 1")
Interpretación diagnóstica — Múltiple 1. Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,3248: no se detecta heterocedasticidad con esta prueba, aunque conviene revisar el gráfico de residuos. Observaciones con Cook > 4/n: 12. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
mostrar_diagnostico(m2,"Múltiple 2")
Interpretación diagnóstica — Múltiple 2. Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,1651: no se detecta heterocedasticidad con esta prueba, aunque conviene revisar el gráfico de residuos. Observaciones con Cook > 4/n: 12. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
cat("\n\n**VIF: Múltiple 1** (inflación de varianza por asociación entre predictores).\n\n")
VIF: Múltiple 1 (inflación de varianza por asociación entre predictores).
print(knitr::kable(calcular_vif(m1)))
| Variable | VIF |
|---|---|
| Area_contruida | 1.11 |
| Banos | 1.47 |
| Habitaciones | 1.35 |
cat("\n\n**VIF: Múltiple 2**.\n\n")
VIF: Múltiple 2.
print(knitr::kable(calcular_vif(m2)))
| Variable | VIF |
|---|---|
| Area_contruida | 1.20 |
| Banos | 1.49 |
| Habitaciones | 1.35 |
| garaje_amplio | 1.13 |
Lectura de VIF: valores cercanos a 1 implican poca colinealidad. Como regla exploratoria, cifras superiores a 5 ameritan revisar la estabilidad de los coeficientes. El VIF no mide calidad predictiva y, si un coeficiente es inestable, no debe interpretarse como un efecto aislado preciso.
Se contrasta el modelo múltiple con logaritmo del área como predictor y otro con logaritmo del precio como respuesta. Se revisan sus residuos y se calcula MAE en las unidades originales de la vivienda.
m_logx <- lm(precio_millon ~ log(Area_contruida) + Banos + Habitaciones + garaje_amplio,data=datos)
m_logy <- lm(log(precio_millon) ~ log(Area_contruida) + Banos + Habitaciones + garaje_amplio,data=datos)
print(summary(m_logx))
Call: lm(formula = precio_millon ~ log(Area_contruida) + Banos + Habitaciones + garaje_amplio, data = datos)
Residuals: Min 1Q Median 3Q Max -700.38 -178.01 -56.85 131.53 768.43
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) -1612.41 257.12 -6.271 2.26e-09
log(Area_contruida) 410.39 47.26 8.683 1.54e-15 Banos
80.14 24.13 3.322 0.00107 ** Habitaciones -36.57 27.40 -1.335
0.18357
garaje_amplio 103.53 42.80 2.419 0.01648 *
— Signif. codes: 0 ‘’ 0.001 ’’ 0.01 ’’ 0.05
‘.’ 0.1 ’ ’ 1
Residual standard error: 273.2 on 195 degrees of freedom Multiple R-squared: 0.474, Adjusted R-squared: 0.4633 F-statistic: 43.94 on 4 and 195 DF, p-value: < 2.2e-16
lectura_coef(m_logx,"Múltiple con log(área)",mapa)
Interpretación completa de Múltiple con log(área).
Intercepto: -1.612,41 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
Logaritmo del área: un aumento aproximado del 1 % en el área se asocia con 4,08 millones de pesos de cambio en el precio anunciado, manteniendo las otras variables constantes; hay evidencia estadística de una asociación (p < 0,05).
baños: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 80,14 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
habitaciones: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 36,57 millones de pesos menos en el precio anunciado; no existe evidencia estadística suficiente al 5 %. No conviene afirmar que existe un efecto real con este resultado.
parqueaderos amplios (1=4 o más): manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 103,53 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
Ajuste: R² = 47,40 % y R² ajustado = 46,33 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
print(summary(m_logy))
Call: lm(formula = log(precio_millon) ~ log(Area_contruida) + Banos + Habitaciones + garaje_amplio, data = datos)
Residuals: Min 1Q Median 3Q Max -0.64526 -0.17429 -0.02702 0.14317 0.59628
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 4.25829 0.22469 18.952 < 2e-16
log(Area_contruida) 0.40694 0.04130 9.853 < 2e-16
Banos 0.07357 0.02108 3.490 0.000598 * Habitaciones -0.03194
0.02395 -1.334 0.183858
garaje_amplio 0.11577 0.03740 3.095 0.002255 — Signif. codes:
0 ‘’ 0.001 ’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1
Residual standard error: 0.2387 on 195 degrees of freedom Multiple R-squared: 0.5392, Adjusted R-squared: 0.5297 F-statistic: 57.04 on 4 and 195 DF, p-value: < 2.2e-16
cat("**Modelo log-log múltiple:** log(precio) es la respuesta. El coeficiente de log(área) es una elasticidad condicional; los coeficientes de otras variables aproximan variaciones relativas del precio. Los R² no se comparan directamente con los modelos cuya respuesta sigue en millones.\n\n")
Modelo log-log múltiple: log(precio) es la respuesta. El coeficiente de log(área) es una elasticidad condicional; los coeficientes de otras variables aproximan variaciones relativas del precio. Los R² no se comparan directamente con los modelos cuya respuesta sigue en millones.
knitr::kable(data.frame(Especificacion=c("Múltiple 2 original","Múltiple con log(área)","Múltiple con log(precio) y log(área)"),
Shapiro_p=c(pruebas(m2)$Shapiro_p,pruebas(m_logx)$Shapiro_p,pruebas(m_logy)$Shapiro_p),
BP_p=c(pruebas(m2)$BP_p,pruebas(m_logx)$BP_p,pruebas(m_logy)$BP_p)),
digits=4,caption="Contraste de supuestos antes y después de las transformaciones")
| Especificacion | Shapiro_p | BP_p |
|---|---|---|
| Múltiple 2 original | 0.0000 | 0.1651 |
| Múltiple con log(área) | 0.0000 | 0.0015 |
| Múltiple con log(precio) y log(área) | 0.0018 | 0.1426 |
mostrar_diagnostico(m_logx,"Múltiple con log(área)")
Interpretación diagnóstica — Múltiple con log(área). Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,0015: hay señales de varianza no constante, lo que limita la confianza en errores estándar clásicos. Observaciones con Cook > 4/n: 9. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
mostrar_diagnostico(m_logy,"Múltiple con log(precio) y log(área)")
Interpretación diagnóstica — Múltiple con log(precio) y log(área). Shapiro-Wilk p = 0,0018: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,1426: no se detecta heterocedasticidad con esta prueba, aunque conviene revisar el gráfico de residuos. Observaciones con Cook > 4/n: 12. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
Interpretación de las transformaciones: preferimos un cambio funcional solo cuando mejora la forma de los residuos y/o reduce el MAE medido en millones de pesos. La normalidad perfecta no es requisito para predecir; sí importa comprender si los errores aumentan con el nivel de precio o si unas pocas observaciones dominan el ajuste.
Se parte de un modelo completo con variables disponibles y se aplica
step() en ambas direcciones, considerando AIC. El
procedimiento busca un balance de ajuste y complejidad, no
identifica variables causalmente necesarias. En validación
cruzada se repite la selección usando exclusivamente el conjunto de
entrenamiento, para evitar utilizar información de la prueba.
formula_completa <- precio_millon ~ Area_contruida + Banos + Habitaciones + parqueaderos + garaje_amplio
modelo_completo <- lm(formula_completa,data=datos)
paso <- step(modelo_completo,
scope=list(lower=~1,upper=formula_completa),
direction="both",trace=TRUE)
Start: AIC=2271.45 precio_millon ~ Area_contruida + Banos + Habitaciones + parqueaderos + garaje_amplio
Df Sum of Sq RSS AIC
Step: AIC=2269.49 precio_millon ~ Area_contruida + Banos + Habitaciones + parqueaderos
Df Sum of Sq RSS AIC
Step: AIC=2268.32 precio_millon ~ Area_contruida + Banos + parqueaderos
Df Sum of Sq RSS AIC
print(formula(paso))
precio_millon ~ Area_contruida + Banos + parqueaderos
print(summary(paso))
Call: lm(formula = precio_millon ~ Area_contruida + Banos + parqueaderos, data = datos)
Residuals: Min 1Q Median 3Q Max -731.40 -203.29 -80.46 172.17 818.72
Coefficients: Estimate Std. Error t value Pr(>|t|)
(Intercept) 211.46794 108.25436 1.953 0.052191 .
Area_contruida 0.60614 0.09948 6.093 5.77e-09 Banos
82.53273 21.99866 3.752 0.000231 parqueaderos 63.52254
13.25165 4.794 3.23e-06 *** — Signif. codes: 0 ‘’ 0.001
’’ 0.01 ’’ 0.05 ‘.’ 0.1 ’ ’ 1
Residual standard error: 287.4 on 196 degrees of freedom Multiple R-squared: 0.415, Adjusted R-squared: 0.406 F-statistic: 46.34 on 3 and 196 DF, p-value: < 2.2e-16
lectura_coef(paso,"Modelo seleccionado por Stepwise",mapa)
Interpretación completa de Modelo seleccionado por Stepwise.
Intercepto: 211,47 millones de pesos es la predicción cuando todos los predictores valen cero. Si ese perfil no existe en la muestra, el intercepto es principalmente un punto de referencia matemático.
área construida (m²): manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 0,61 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
baños: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 82,53 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
parqueaderos: manteniendo constantes los otros predictores, una unidad adicional (o el paso de 0 a 1 si es dummy) se asocia con 63,52 millones de pesos más en el precio anunciado; hay evidencia estadística de una asociación (p < 0,05). La relación es estadísticamente detectable.
Ajuste: R² = 41,50 % y R² ajustado = 40,60 %. La porción restante de la dispersión del precio sigue sin explicar. Un R² mayor no demuestra causalidad ni garantiza mejor predicción fuera de la muestra.
cat("**Lectura de la selección:** las variables que permanecen son: ",
paste(names(coef(paso))[-1],collapse=", "),
". Su AIC final es ",formatear(AIC(paso)),
" frente a ",formatear(AIC(modelo_completo)),
" del modelo completo. Un AIC menor favorece parsimonia SOLO cuando los modelos usan la misma respuesta y las mismas filas.\n\n",sep="")
Lectura de la selección: las variables que permanecen son: Area_contruida, Banos, parqueaderos. Su AIC final es 2.837,90 frente a 2.841,02 del modelo completo. Un AIC menor favorece parsimonia SOLO cuando los modelos usan la misma respuesta y las mismas filas.
mostrar_diagnostico(paso,"Stepwise seleccionado")
Interpretación diagnóstica — Stepwise seleccionado. Shapiro-Wilk p = < 0,001: se rechaza la normalidad estricta de los residuos; revisar especialmente colas y Q-Q plot. Breusch-Pagan auxiliar p = 0,2751: no se detecta heterocedasticidad con esta prueba, aunque conviene revisar el gráfico de residuos. Observaciones con Cook > 4/n: 12. Son señales para revisión; no se eliminan automáticamente. La independencia de los anuncios y la ausencia de variables omitidas no se prueban solo con estos gráficos.
Usamos cinco pliegues reproducibles y las
mismas particiones para todos los modelos. Cada vez se entrena
en cuatro pliegues y se predice el quinto. Para modelos con
log(precio), se convierte la predicción a millones de pesos
mediante exponencial y factor de smearing calculado
exclusivamente sobre el entrenamiento. La comparación se realiza con
MAE (error absoluto medio) y RMSE
(penaliza más los errores muy grandes).
# Los pliegues quedaron definidos antes del modelado a partir del ID del Excel.
formulas_evaluar <- list(
"Simple 1"=formula(s1),"Simple 2"=formula(s2),"Simple 3"=formula(s3),
"Múltiple 1"=formula(m1),"Múltiple 2"=formula(m2),
"Stepwise AIC (ajustado en cada pliegue)"=formula_completa,
"Simple: precio ~ log(área)"=formula(log_x_simple),
"Simple: log(precio) ~ log(área)"=formula(log_yx_simple),
"Múltiple: precio ~ log(área)"=formula(m_logx),
"Múltiple: log(precio) ~ log(área)"=formula(m_logy))
lista_cv <- lapply(names(formulas_evaluar),function(nm) {
res <- comparar_cv(formulas_evaluar[[nm]],datos,
es_log_y=grepl("log[(]precio_millon[)]",paste(deparse(formulas_evaluar[[nm]]),collapse="")),
paso_a_paso=grepl("Stepwise",nm))
data.frame(Modelo=nm,MAE_millones=res[["MAE"]],RMSE_millones=res[["RMSE"]])
})
tabla_cv <- do.call(rbind,lista_cv)
# Baseline, sin usar el precio de las filas evaluadas.
precios_reales <- numeric(0); base_estimado <- numeric(0)
for (k in 1:5) {
prueba <- datos[datos$fold==k,,drop=FALSE]
train <- datos[datos$fold!=k,,drop=FALSE]
precios_reales <- c(precios_reales,prueba$precio_millon)
base_estimado <- c(base_estimado,rep(median(train$precio_millon),nrow(prueba)))
}
mae_base <- mean(abs(precios_reales-base_estimado))
tabla_cv <- rbind(tabla_cv,data.frame(Modelo="Referencia: mediana del entrenamiento",
MAE_millones=mae_base,RMSE_millones=sqrt(mean((precios_reales-base_estimado)^2))))
tabla_cv <- tabla_cv[order(tabla_cv$MAE_millones),]
knitr::kable(tabla_cv,digits=2,caption="Comparación predictiva en COP millones (menor es mejor)")
| Modelo | MAE_millones | RMSE_millones | |
|---|---|---|---|
| 9 | Múltiple: precio ~ log(área) | 222.22 | 280.06 |
| 7 | Simple: precio ~ log(área) | 225.46 | 289.11 |
| 10 | Múltiple: log(precio) ~ log(área) | 232.77 | 297.23 |
| 6 | Stepwise AIC (ajustado en cada pliegue) | 234.70 | 291.85 |
| 8 | Simple: log(precio) ~ log(área) | 239.94 | 315.26 |
| 5 | Múltiple 2 | 242.21 | 299.43 |
| 4 | Múltiple 1 | 251.57 | 309.59 |
| 1 | Simple 1 | 262.34 | 324.41 |
| 2 | Simple 2 | 274.81 | 342.96 |
| 3 | Simple 3 | 279.78 | 333.29 |
| 11 | Referencia: mediana del entrenamiento | 325.18 | 386.99 |
mejor_nombre <- tabla_cv$Modelo[tabla_cv$Modelo!="Referencia: mediana del entrenamiento"][1]
mejor_error <- tabla_cv$MAE_millones[tabla_cv$Modelo==mejor_nombre]
cat("\n\n**Interpretación del MAE:** el menor error entre los modelos estudiados corresponde a **",
mejor_nombre,"**, con **",formatear(mejor_error)," millones COP** de diferencia absoluta promedio entre precio anunciado y estimado. ",
"La referencia sin predictores tiene MAE **",formatear(mae_base)," millones**. ",
"Esto NO significa que cada predicción falle exactamente ese monto; el error individual puede ser mucho mayor. ",
"El RMSE permite identificar modelos más vulnerables a anuncios extremos.\n\n",sep="")
Interpretación del MAE: el menor error entre los modelos estudiados corresponde a Múltiple: precio ~ log(área), con 222,22 millones COP de diferencia absoluta promedio entre precio anunciado y estimado. La referencia sin predictores tiene MAE 325,18 millones. Esto NO significa que cada predicción falle exactamente ese monto; el error individual puede ser mucho mayor. El RMSE permite identificar modelos más vulnerables a anuncios extremos.
predict()Se plantean dos perfiles plausibles para Pance, sin sustituir una tasación profesional ni suponer una compra real. Se proyecta con el modelo Stepwise y con el modelo múltiple que usa logaritmo del área (para observar cómo cambia la estimación con distinta forma funcional).
escenarios <- data.frame(Area_contruida=c(350,250),Banos=c(5,4),Habitaciones=c(4,3),parqueaderos=c(4,2),garaje_amplio=c(1,0))
print(knitr::kable(escenarios,caption="Dos perfiles hipotéticos usados en predict()"))
| Area_contruida | Banos | Habitaciones | parqueaderos | garaje_amplio |
|---|---|---|---|---|
| 350 | 5 | 4 | 4 | 1 |
| 250 | 4 | 3 | 2 | 0 |
pronostico_step <- as.data.frame(predict(paso,newdata=escenarios,
interval="prediction",level=.95))
pronostico_logx <- as.data.frame(predict(m_logx,newdata=escenarios,
interval="prediction",level=.95))
tabla_pred <- data.frame(Perfil=c("Escenario 1","Escenario 2"),
Step_fit=pronostico_step$fit,Step_inferior=pronostico_step$lwr,Step_superior=pronostico_step$upr,
LogArea_fit=pronostico_logx$fit,LogArea_inferior=pronostico_logx$lwr,
LogArea_superior=pronostico_logx$upr)
print(knitr::kable(tabla_pred,digits=2,caption="Predicciones e intervalos para un nuevo anuncio (millones COP)"))
| Perfil | Step_fit | Step_inferior | Step_superior | LogArea_fit | LogArea_inferior | LogArea_superior |
|---|---|---|---|---|---|---|
| Escenario 1 | 1090.37 | 521.96 | 1658.78 | 1149.55 | 608.03 | 1691.07 |
| Escenario 2 | 820.18 | 249.27 | 1391.09 | 864.37 | 319.84 | 1408.89 |
cat("\n\n**Interpretación:** para el primer perfil, el modelo Stepwise estima ",
formatear(pronostico_step$fit[1])," millones COP y un intervalo de predicción del 95 % entre ",
formatear(pronostico_step$lwr[1])," y ",formatear(pronostico_step$upr[1])," millones. ",
"Para el segundo perfil estima ",formatear(pronostico_step$fit[2])," millones. ",
"Este es un rango para un nuevo anuncio individual bajo los supuestos del modelo, no una garantía de venta. ",
"La alternativa log(área) estima ",formatear(pronostico_logx$fit[1]),
" millones para el primer caso; las diferencias muestran sensibilidad a la especificación.\n\n",sep="")
Interpretación: para el primer perfil, el modelo Stepwise estima 1.090,37 millones COP y un intervalo de predicción del 95 % entre 521,96 y 1.658,78 millones. Para el segundo perfil estima 820,18 millones. Este es un rango para un nuevo anuncio individual bajo los supuestos del modelo, no una garantía de venta. La alternativa log(área) estima 1.149,55 millones para el primer caso; las diferencias muestran sensibilidad a la especificación.
Respuesta a la pregunta del trabajo. La base filtrada permite identificar relaciones entre características físicas y precios de oferta, pero la utilidad práctica depende de la magnitud de los errores fuera de muestra. El modelo de menor MAE es Múltiple: precio ~ log(área) con 222,22 millones de COP de error absoluto promedio, frente a 325,18 millones de la referencia por mediana.
Lectura empresarial. En Pance importa más que una fórmula identifique el rango de negociación que acertar un precio exacto: aun con modelos estadísticamente significativos, la dispersión puede ser costosa para una decisión comercial.
Limitaciones que afectan la decisión. El precio anunciado no equivale al precio final de una negociación. Además, las casas de lujo pueden tener acabados y lotes muy distintos, aspectos que no se observan en la base. Se desconoce si los anuncios representan propiedades independientes y no hay observación directa de estado de conservación, acabados, negociaciones efectivas ni fecha de publicación. Un valor de p pequeño no demuestra que modificar una característica cause un incremento de precio.
Recomendación. Usar los modelos únicamente como punto de partida para estimar rangos de precio anunciado y cotejar con visitas, comparables recientes y juicio profesional. No recomendar un precio final de cierre, una inversión o una decisión de crédito basándose en esta regresión por sí sola.
Base Datos_Vivienda.xlsx proporcionada en clase. La
estructura sigue los dos ejemplos docentes adjuntos: filtro por
barrio/tipo, estadística descriptiva y gráficos, modelos
lm(), interpretación de coeficientes, diagnóstico
plot(lm), transformaciones logarítmicas, dummy,
step(), predict() y MAE con evaluación externa
al entrenamiento.