Dirección de Educación Continua.
# Cargar las librerías necesarias
# Si no las tienes instaladas, ejecuta: install.packages(c("dplyr", "ggplot2", "lmtest", "car", "tseries", "sandwich", "MASS"))
library(dplyr)
##
## Attaching package: '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(lmtest) # Para bptest, resettest, dwtest
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(car) # Para vif
## Loading required package: carData
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
library(tseries)# Para jarque.bera.test
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(sandwich) # Para vcovHC (errores robustos)
library(MASS) # Para boxcox
##
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
# Configuraciones de visualización
theme_set(theme_dark()) # Equivalente a sns.set_style("darkgrid")
options(repr.plot.width = 15, repr.plot.height = 6) # Equivalente a plt.rcParams
options(warn = -1) # Suprime advertencias, equivalente a warnings.filterwarnings("ignore")
# URL base para los datos
url_base <- "https://raw.githubusercontent.com/jazaineam1/Diplomado_ucentral_ME/refs/heads/main/Datos/"
Los modelos de regresión lineal, para ser válidos y para que sus inferencias estadísticas (como los intervalos de confianza y las pruebas de hipótesis sobre los coeficientes) sean fiables, se basan en una serie de supuestos sobre los datos y, más específicamente, sobre los errores del modelo.
En el contexto de la regresión, un error (a menudo llamado residuo cuando se calcula a partir de los datos de la muestra) es la diferencia entre el valor observado de la variable dependiente (\(y_i\)) y el valor predicho por el modelo de regresión (\(\hat{y}_i\)).
\(e_i = y_i - \hat{y}_i\)
Los errores representan la variabilidad en la variable dependiente que el modelo de regresión no logra explicar. Son una medida de cuán bien se ajusta el modelo a los datos.
Las propiedades estadísticas deseadas de los estimadores de los coeficientes de regresión (como ser insesgados y eficientes) y la validez de las pruebas de significancia e intervalos de confianza dependen de que estos supuestos sobre los errores se cumplan. Si los supuestos se violan, las conclusiones extraídas del modelo pueden ser incorrectas o engañosas.
Es crucial verificar estos supuestos después de ajustar un modelo de regresión para asegurar la validez y fiabilidad de sus resultados. Si se violan los supuestos, pueden ser necesarias transformaciones de variables, el uso de métodos de regresión robustos, o la reconsideración de la especificación del modelo.
# | Supuesto | Formulación (pop.) | Prueba clásica | \(H_0\) | \(H_1\) | Consecuencias si \(H_0\) se rechaza |
---|---|---|---|---|---|---|
1 | Linealidad | \(E[y\mid X]=X\beta\) | Gráfico residuales-ajustados, Ramsey RESET | No falta non-linearidad | Hay relación no lineal | Sesgo en \(\hat\beta\) |
2 | Independencia | $ (_i,_j)=0$ | Durbin–Watson, Ljung-Box | Errores no autocorrelados | Autocorrelación | EE sub/over |
3 | Homoscedasticidad | Var\((\varepsilon_i)=\sigma^2\) | Breusch–Pagan, White | Varianza constante | Varianza depende de \(X\) | Tests t/F inválidos |
4 | Normalidad (solo p << 30) | \(\varepsilon_i\sim N(0,\sigma^2)\) | Jarque–Bera, Shapiro | Errores normales | Distrib. distinta | T-IC inexactos |
5 | No multicolinealidad perfecta | \(\operatorname{rank}(X)=k\) | VIF, condición | VIF bajos | Colinealidad alta | EE inflados, inestab. |
En una lectura anterior, aprendimos cómo la regresión lineal puede ser una herramienta poderosa para comprender el comportamiento de una variable de interés en relación con otras variables en nuestro conjunto de datos. Sin embargo, en muchas situaciones de la vida real, es posible que nuestros datos no cumplan con los supuestos básicos que se necesitan para que un modelo de regresión lineal sea adecuado. En los casos en que la regresión lineal no sea directamente aplicable, en estos escenarios debemos descubrir cómo solucionar este problema.
Vamos a abordar:
El Dataset se obtuvo de Kaggle
e incluye precios de venta de casas en el estado de Washington (condado
de King, donde se encuentra Seattle) entre mayo de 2014 y mayo de
2015.
Vamos a crear un modelo que use como variable target el precio de
venta (price
) y como las features las características de
los predios. Todo basado en ventas anteriores en Seattle para recomendar
un precio de venta óptimo.
# Cargar los datos
file_url <- paste0(url_base, "kc_house_data.csv")
houses <- read.csv(file_url)
# Copiar y limpiar el dataframe
df <- houses
# Eliminar columnas no deseadas usando dplyr
df <- df %>%
dplyr::select(-id, -sqft_living15, -sqft_lot15)
# Mostrar la estructura del dataframe (equivalente a df.info())
glimpse(df)
## Rows: 21,613
## Columns: 18
## $ date <chr> "20141013T000000", "20141209T000000", "20150225T000000",…
## $ price <dbl> 221900, 538000, 180000, 604000, 510000, 1225000, 257500,…
## $ bedrooms <int> 3, 3, 2, 4, 3, 4, 3, 3, 3, 3, 3, 2, 3, 3, 5, 4, 3, 4, 2,…
## $ bathrooms <dbl> 1.00, 2.25, 1.00, 3.00, 2.00, 4.50, 2.25, 1.50, 1.00, 2.…
## $ sqft_living <int> 1180, 2570, 770, 1960, 1680, 5420, 1715, 1060, 1780, 189…
## $ sqft_lot <int> 5650, 7242, 10000, 5000, 8080, 101930, 6819, 9711, 7470,…
## $ floors <dbl> 1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 2.0, 1.0, 1.0, 2.0, 1.0, 1…
## $ waterfront <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
## $ view <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,…
## $ condition <int> 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 4, 4,…
## $ grade <int> 7, 7, 6, 7, 8, 11, 7, 7, 7, 7, 8, 7, 7, 7, 7, 9, 7, 7, 7…
## $ sqft_above <int> 1180, 2170, 770, 1050, 1680, 3890, 1715, 1060, 1050, 189…
## $ sqft_basement <int> 0, 400, 0, 910, 0, 1530, 0, 0, 730, 0, 1700, 300, 0, 0, …
## $ yr_built <int> 1955, 1951, 1933, 1965, 1987, 2001, 1995, 1963, 1960, 20…
## $ yr_renovated <int> 0, 1991, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
## $ zipcode <int> 98178, 98125, 98028, 98136, 98074, 98053, 98003, 98198, …
## $ lat <dbl> 47.5112, 47.7210, 47.7379, 47.5208, 47.6168, 47.6561, 47…
## $ long <dbl> -122.257, -122.319, -122.233, -122.393, -122.045, -122.0…
# Definir la fórmula del modelo
# La sintaxis de la fórmula en R es muy similar a la de statsmodels en Python
formula_0 <- log(price) ~ sqft_living + bedrooms + bathrooms + floors + grade + sqft_lot
# Ajustar el modelo de regresión lineal (OLS)
model_0 <- lm(formula_0, data = df)
# Mostrar el resumen del modelo
summary(model_0)
##
## Call:
## lm(formula = formula_0, data = df)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.74302 -0.25290 0.00178 0.23567 1.38151
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.123e+01 2.109e-02 532.709 < 2e-16 ***
## sqft_living 2.388e-04 5.172e-06 46.169 < 2e-16 ***
## bedrooms -1.995e-02 3.255e-03 -6.131 8.91e-10 ***
## bathrooms -8.841e-03 5.239e-03 -1.688 0.091501 .
## floors -1.451e-02 5.300e-03 -2.737 0.006199 **
## grade 1.864e-01 3.373e-03 55.261 < 2e-16 ***
## sqft_lot -2.217e-07 5.889e-08 -3.765 0.000167 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3507 on 21606 degrees of freedom
## Multiple R-squared: 0.5567, Adjusted R-squared: 0.5566
## F-statistic: 4522 on 6 and 21606 DF, p-value: < 2.2e-16
# 2.1 Linealidad / especificación ---------------------------
# Prueba RESET de Ramsey para errores de especificación
# 'type = "fitted"' usa las potencias de los valores ajustados como regresores
reset_test_result <- resettest(model_0, power = 2, type = "fitted")
# Imprimir el p-valor
cat(paste("\nRESET (linealidad) p-value:", format(reset_test_result$p.value, scientific = TRUE, digits = 4)))
##
## RESET (linealidad) p-value: 1.597e-14
La salida RESET (linealidad) p-value: 1.597e-14
se
interpreta de la siguiente manera:
La prueba RESET (Regression Equation Specification Error Test) se utiliza para detectar problemas de especificación en un modelo de regresión, particularmente la omisión de términos no lineales.
En este caso, el p-valor obtenido es 1.597e-14
(o
0.00000000000001597). Este valor es extremadamente pequeño, mucho menor
que los niveles de significancia comunes (como 0.05, 0.01 o 0.001).
Conclusión: Dado que el p-valor es muy bajo, se
rechaza la hipótesis nula. Esto sugiere fuertemente que el modelo, tal
como está especificado actualmente
(np.log(price) ~ sqft_living + bedrooms + bathrooms + floors + grade + sqft_lot
),
sufre de una incorrecta especificación, probablemente debido a la
omisión de relaciones no lineales relevantes. En otras palabras, la
relación entre las variables predictoras y el logaritmo del precio no es
puramente lineal como asume el modelo. Sería necesario considerar
transformaciones adicionales de las variables o la inclusión de términos
polinómicos o de interacción para mejorar la especificación del
modelo.
# Crear un dataframe con los valores ajustados y los residuos
residuals_df <- data.frame(
Fitted = fitted(model_0),
Residuals = resid(model_0)
)
# Graficar con ggplot2
ggplot(residuals_df, aes(x = Fitted, y = Residuals)) +
geom_point(alpha = 0.3) +
geom_hline(yintercept = 0, color = "black") +
labs(
x = "Fitted",
y = "Residuals",
title = "Residuos vs Ajustados — Modelo 0")
El gráfico generado (“Residuos vs Ajustados — Modelo 0”) es una herramienta de diagnóstico fundamental para evaluar la adecuación de un modelo de regresión lineal. En este gráfico:
¿Qué buscamos en este gráfico?
Interpretación del Gráfico Específico (Modelo 0):
Observando el gráfico “Residuos vs Ajustados — Modelo 0”:
Conclusión basada en el gráfico:
La presencia de un patrón (como una curva) en el gráfico de residuos vs. ajustados sugiere que el supuesto de linealidad podría no cumplirse. Esto significa que el modelo lineal actual podría no estar capturando adecuadamente la relación entre las variables predictoras y el logaritmo del precio.
Esta observación visual es consistente con el resultado de la
prueba RESET (p-valor: 1.597e-14
), la cual
indicó una incorrecta especificación del modelo debido, probablemente, a
la omisión de relaciones no lineales. El gráfico de residuos proporciona
una evidencia visual que respalda esta conclusión.
Aunque el principal problema que se destaca es la no linealidad, este tipo de gráfico también ayuda a evaluar la homocedasticidad. Si bien no hay una forma de embudo extremadamente obvia, la posible no linealidad complica la evaluación clara de la homocedasticidad a partir de este gráfico únicamente. Corregir la no linealidad a menudo es el primer paso antes de reevaluar la homocedasticidad.
# 2.2 Multicolinealidad -------------------------------------
# La función vif() del paquete 'car' calcula el VIF para todas las variables
vif_results <- vif(model_0)
print("VIF:")
## [1] "VIF:"
print(vif_results)
## sqft_living bedrooms bathrooms floors grade sqft_lot
## 3.964208 1.609883 2.860243 1.438988 2.762177 1.045194
El Factor de Inflación de la Varianza (VIF) es una medida utilizada para detectar la multicolinealidad en un modelo de regresión múltiple. La multicolinealidad ocurre cuando dos o más variables predictoras (independientes) en el modelo están altamente correlacionadas entre sí.
¿Qué mide el VIF?
Para cada variable predictora en el modelo, el VIF cuantifica cuánto se infla la varianza de su coeficiente de regresión estimado debido a su correlación con las otras variables predictoras en el modelo.
Conceptualmente, para una variable predictora \(X_j\), su VIF se calcula como: \(VIF_j = \frac{1}{1 - R_j^2}\) donde \(R_j^2\) es el coeficiente de determinación de una regresión de \(X_j\) sobre todas las demás variables predictoras.
Interpretación de los valores del VIF:
No hay un umbral estricto, pero se suelen seguir estas directrices generales:
# 2.3 Observaciones influyentes ------------------------------
# Calcular la distancia de Cook para cada observación
cooks_d <- cooks.distance(model_0)
# Encontrar el valor máximo
cook_max <- max(cooks_d)
cat(paste("\nMáx Cook's D:", format(cook_max, digits = 4)))
##
## Máx Cook's D: 0.1664
La salida Máx Cook's D: 0.1664
se
refiere al valor máximo de la Distancia de Cook (Cook’s D) en tu
modelo.
Interpretación del resultado:
La Distancia de Cook mide la influencia de cada observación individual en los coeficientes estimados del modelo. Un valor alto indica que esa observación tiene un impacto desproporcionado en los resultados. Se suelen considerar dos umbrales principales:
cook_max
de 0.1664
es
significativamente mayor que este umbral.cook_max
de 0.1664
es
menor que 1.Conclusión sobre la influencia:
El hecho de que el cook_max
(0.1664) supere el umbral de
\(4/n\) sugiere que hay al menos una
observación (y posiblemente más) que ejerce una influencia considerable
en tu modelo. Aunque no alcanza el nivel de “altamente influyente” (D
> 1), estas observaciones tienen un impacto desproporcionado en las
estimaciones de los coeficientes en comparación con la mayoría de los
otros puntos de datos.
¿Qué debes hacer?
Dado que existen puntos con influencia notable, es recomendable investigar más a fondo:
Identificar las Observaciones Influyentes: No solo te fijes en el máximo. Obtén una lista o un gráfico de las Distancias de Cook para todas las observaciones e identifica todas aquellas cuyo Cook’s D supere el umbral de \(4/n\).
Examinar las Observaciones Identificadas: Revisa estas observaciones en tu conjunto de datos original. Pregúntate:
Tomar Decisiones:
Reevaluar el Modelo: Después de cualquier corrección, reajusta el modelo y vuelve a verificar todos los supuestos.
# 2.4 Homoscedasticidad --------------------------------------
# Prueba de Breusch-Pagan del paquete lmtest
bp_test_result <- bptest(model_0)
cat(paste("Breusch-Pagan p-value:", format(bp_test_result$p.value, scientific = TRUE, digits = 4)))
## Breusch-Pagan p-value: 4.937e-55
La salida Breusch-Pagan p-value: 4.937e-55
se interpreta
de la siguiente manera:
La prueba de Breusch-Pagan se utiliza para detectar la heterocedasticidad en un modelo de regresión lineal. La heterocedasticidad ocurre cuando la varianza de los errores (residuos) no es constante a lo largo de todos los niveles de las variables independientes. El supuesto de homoscedasticidad (varianza constante de los errores) es crucial para la validez de las pruebas de significancia estándar (pruebas t y F) y los intervalos de confianza de los coeficientes de regresión.
En este caso, el p-valor obtenido es 4.937e-55
(un
número extremadamente pequeño, prácticamente cero).
Conclusión: Dado que el p-valor
(4.937e-55
) es mucho menor que cualquier nivel de
significancia convencional (por ejemplo, 0.05, 0.01, 0.001), se
rechaza la hipótesis nula de homocedasticidad.
Esto indica que hay una fuerte evidencia de heterocedasticidad en el modelo. Es decir, la varianza de los errores del modelo no es constante, sino que varía con los niveles de las variables predictoras.
Consecuencias de la Heterocedasticidad: * Los estimadores de los coeficientes de regresión (\(\hat\beta\)) siguen siendo insesgados, pero ya no son los de mínima varianza (no son eficientes). * Los errores estándar de los coeficientes de regresión están sesgados. Esto invalida las pruebas t, las pruebas F y los intervalos de confianza calculados de la manera usual.
Para abordar este problema, se podrían considerar soluciones como: *
Transformar la variable dependiente (aunque ya se usó
np.log(price)
, podría explorarse más). * Utilizar errores
estándar robustos a la heterocedasticidad (por ejemplo, estimadores de
White, Huber-White o HC0, HC1, etc.). * Aplicar Mínimos Cuadrados
Ponderados (WLS) si se conoce la forma de la heterocedasticidad.
# 2.5 Normalidad ---------------------------------------------
# Prueba de Jarque-Bera del paquete tseries
jb_test_result <- jarque.bera.test(resid(model_0))
cat(paste("Jarque-Bera p-value:", format(jb_test_result$p.value, scientific = TRUE, digits = 4)))
## Jarque-Bera p-value: 1.087e-09
La salida Jarque-Bera p-value: 1.087e-09
se interpreta
de la siguiente manera:
La prueba de Jarque-Bera es una prueba de bondad de ajuste para verificar si los datos de la muestra (en este caso, los residuos del modelo) tienen la asimetría (skewness) y la curtosis (kurtosis) que coinciden con una distribución normal.
En este caso, el p-valor obtenido es 1.087e-09
(un
número extremadamente pequeño, mucho menor que 0.001).
Conclusión: Dado que el p-valor
(1.087e-09
) es significativamente menor que los niveles de
significancia comunes (por ejemplo, 0.05, 0.01), se rechaza la
hipótesis nula.
Esto indica que hay una fuerte evidencia de que los residuos del modelo no siguen una distribución normal.
Consecuencias de la No Normalidad de los Residuos: * Muestras Pequeñas: Si los errores no son normales y el tamaño de la muestra es pequeño, las pruebas de hipótesis (pruebas t y F) y los intervalos de confianza para los coeficientes de regresión pueden no ser fiables. Sus distribuciones teóricas (t y F) dependen del supuesto de normalidad. * Muestras Grandes: Para muestras grandes (como es el caso aquí, con más de 21,000 observaciones), el Teorema del Límite Central a menudo entra en juego. Este teorema sugiere que los estimadores de los coeficientes de regresión (\(\hat\beta\)) tienden a distribuirse aproximadamente de forma normal, incluso si los errores originales no lo hacen. Por lo tanto, en muestras grandes, la violación del supuesto de normalidad de los errores suele ser menos preocupante para la validez de las inferencias sobre los coeficientes. Sin embargo, la no normalidad aún podría indicar otros problemas subyacentes en el modelo, como la omisión de variables importantes o una forma funcional incorrecta, que ya fueron señalados por la prueba RESET.
Aunque la no normalidad es estadísticamente significativa, dado el gran tamaño de la muestra, su impacto en la fiabilidad de las pruebas t y F para los coeficientes podría ser limitado. No obstante, es una pieza más de evidencia que sugiere que el modelo actual podría beneficiarse de mejoras en su especificación.
# 2.6 Independencia ------------------------------------------
# Prueba de Durbin-Watson del paquete lmtest
dw_test_result <- dwtest(model_0)
cat(paste("Durbin-Watson statistic:", format(dw_test_result$statistic, digits = 4)))
## Durbin-Watson statistic: 1.976
La salida Durbin-Watson statistic: 1.976
se interpreta
de la siguiente manera:
El estadístico de Durbin-Watson (DW) se utiliza para detectar la presencia de autocorrelación en los residuos de un modelo de regresión. Este supuesto es particularmente importante para datos de series temporales, pero también puede ser relevante en datos de corte transversal si hay algún ordenamiento inherente en las observaciones.
Interpretación del valor del estadístico DW:
El estadístico varía entre 0 y 4: * DW ≈ 2: Indica que no hay autocorrelación. * DW < 2 (hacia 0): Sugiere autocorrelación positiva. * DW > 2 (hacia 4): Sugiere autocorrelación negativa.
Como regla general, valores entre 1.5 y 2.5 se consideran aceptables.
Conclusión para el Modelo Actual:
El estadístico de Durbin-Watson es 1.976
. Este valor
está muy cerca de 2.0 y dentro del rango aceptable, lo que sugiere una
ausencia de autocorrelación de primer orden
significativa en los residuos del modelo. Por lo tanto, el
supuesto de independencia de los errores parece cumplirse razonablemente
bien.
Orden | Prueba (R packages ) |
Hipótesis nula H₀ | Cómo leer el p-value |
---|---|---|---|
1 | resettest (lmtest ) |
El modelo es lineal y no faltan potencias ni interacciones | p > 0.05 ⇒ forma adecuada. p ≤ 0.05 ⇒ agregar polinomios, logs o variables omitidas. |
2 | vif (car ) |
No hay multicolinealidad grave | VIF < 10 (ideal < 5) = OK. Valores grandes ⇒ remover/comprimir variables. |
3 | cooks.distance (stats ) |
Ningún punto influye excesivamente | Regla práctica: Cook > 4/n indica outlier influyente; considerar revisarlo o usar robust SE/WLS. |
4 | bptest (lmtest ) |
Homoscedasticidad (Var(ε) constante) | p > 0.05 ⇒ varianza constante; p ≤ 0.05 ⇒ heteroscedasticidad ⇒ log/Box-Cox, WLS o SE robustas. |
5 | jarque.bera.test (tseries ) |
Normalidad de errores | p > 0.05 ⇒ residuos ~ normales; p ≤ 0.05 ⇒ asimetría/colas ⇒ transformar y o usar bootstrap/robust SE. |
6 | dwtest (lmtest ) |
No autocorrelación | DW ≈ 2 indica independencia; valores ≪ 2 o ≫ 2 indican autocorrelación positiva o negativa. |
Orden lógico: forma → estabilidad → outliers → varianza → distribución → dependencia. Corriges lo que falla y vuelves a correr las pruebas, avanzando secuencialmente hasta obtener un modelo cuyos supuestos estén (al menos) mitigados o tratados con métodos robustos.
# 1. Datos y transformaciones usando dplyr::mutate
df <- df %>%
mutate(
log_sqft = log(sqft_living),
log_lot = log(sqft_lot),
sqft2 = log_sqft^2,
grade2 = grade^2,
age = 2015 - yr_built,
age2 = age^2,
sqft_grade = log_sqft * grade,
renovated = as.integer(yr_renovated > 0)
)
# Transformación de Box-Cox para la variable dependiente
# La función boxcox de MASS ayuda a encontrar el lambda óptimo
bc_result <- boxcox(df$price ~ 1, plotit = FALSE)
lambda <- bc_result$x[which.max(bc_result$y)]
# Aplicar la transformación con el lambda encontrado
df$bc_price <- (df$price^lambda - 1) / lambda
# Definir la fórmula para el nuevo modelo
formula_1 <- bc_price ~ log_sqft + sqft2 + bedrooms + bathrooms + floors +
waterfront + view + grade + grade2 + condition +
log_lot + sqft_grade + age + age2 + renovated
# 2. OLS preliminar para obtener los pesos
ols_pre <- lm(formula_1, data = df)
# Calcular los pesos. pmax es el equivalente a np.maximum
weights <- 1 / pmax(fitted(ols_pre), 0.1)^2
head(weights)
## 1 2 3 4 5 6
## 0.04721073 0.04650500 0.04756456 0.04672165 0.04681600 0.04517597
# 3. Ajustar el modelo WLS (Mínimos Cuadrados Ponderados)
# y calcular errores estándar robustos HC3
# Usaremos lm() con el argumento 'weights'
wls_model <- lm(formula_1, data = df, weights = weights)
# Para obtener un resumen con errores robustos, combinamos lmtest y sandwich
# coeftest aplica la corrección de la matriz de covarianza (vcovHC)
wls_summary_robust <- coeftest(wls_model, vcov = vcovHC(wls_model, "HC3"))
# Para un resumen más completo similar al de Python, imprimimos varias partes:
print("Resumen de Coeficientes WLS con Errores Robustos HC3")
## [1] "Resumen de Coeficientes WLS con Errores Robustos HC3"
print(wls_summary_robust)
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.7117e+00 5.4431e-02 86.5634 < 2.2e-16 ***
## log_sqft -1.1822e-01 1.7316e-02 -6.8270 8.902e-12 ***
## sqft2 1.1301e-02 1.4653e-03 7.7120 1.292e-14 ***
## bedrooms -2.4624e-03 4.0546e-04 -6.0730 1.276e-09 ***
## bathrooms 4.2182e-03 3.8782e-04 10.8767 < 2.2e-16 ***
## floors 2.1572e-03 4.0964e-04 5.2660 1.408e-07 ***
## waterfront 2.1494e-02 1.9958e-03 10.7697 < 2.2e-16 ***
## view 3.7860e-03 2.2181e-04 17.0691 < 2.2e-16 ***
## grade 4.4591e-02 5.2057e-03 8.5657 < 2.2e-16 ***
## grade2 -6.0630e-04 1.7585e-04 -3.4479 0.000566 ***
## condition 3.2456e-03 2.9950e-04 10.8366 < 2.2e-16 ***
## log_lot -2.5839e-03 2.2839e-04 -11.3138 < 2.2e-16 ***
## sqft_grade -2.4984e-03 9.0152e-04 -2.7713 0.005587 **
## age 1.2548e-04 2.7295e-05 4.5971 4.309e-06 ***
## age2 2.4262e-06 2.3227e-07 10.4455 < 2.2e-16 ***
## renovated 7.0713e-04 9.1021e-04 0.7769 0.437237
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\n--- Estadísticas del Modelo ---\n")
##
## --- Estadísticas del Modelo ---
# R-cuadrado y otros estadísticos del modelo original wls_model
summary_wls <- summary(wls_model)
cat(paste("R-squared:", round(summary_wls$r.squared, 3), "\n"))
## R-squared: 0.631
cat(paste("Adj. R-squared:", round(summary_wls$adj.r.squared, 3), "\n"))
## Adj. R-squared: 0.631
cat(paste("F-statistic on", summary_wls$fstatistic[2], "and", summary_wls$fstatistic[3], "DF, p-value:", format.pval(pf(summary_wls$fstatistic[1], summary_wls$fstatistic[2], summary_wls$fstatistic[3], lower.tail = FALSE)), "\n"))
## F-statistic on 15 and 21597 DF, p-value: < 2.22e-16
cat(paste("AIC:", AIC(wls_model), "\n"))
## AIC: -101329.302359065
cat(paste("BIC:", BIC(wls_model), "\n"))
## BIC: -101193.624504568
En el contexto de tu modelo, se utilizan Mínimos Cuadrados Ponderados (WLS) y errores estándar robustos HC3 para abordar el problema de la heterocedasticidad, que fue detectado previamente por la prueba de Breusch-Pagan (con un p-valor muy bajo, indicando varianza no constante de los errores).
1 / pmax(fitted(ols_pre), 0.1)^2
. Esto implica una
suposición de que la varianza del error es proporcional al cuadrado de
los valores ajustados del modelo (una forma común de
heterocedasticidad). Se usa pmax
para evitar la división
por cero o por valores muy pequeños.En resumen, estás utilizando WLS para intentar obtener mejores estimaciones de los coeficientes, y luego utilizando errores estándar HC3 para asegurar que tus conclusiones estadísticas sobre esos coeficientes sean fiables.
# 4. Prueba de Breusch-Pagan en el modelo WLS
bp_p_wls <- bptest(wls_model)
cat("Breusch–Pagan p:", bp_p_wls$p.value)
## Breusch–Pagan p: 7.427567e-57
# 5. VIF en el modelo WLS
vif_wls <- vif(wls_model)
print("VIF (primeras 10 variables):")
## [1] "VIF (primeras 10 variables):"
print(head(vif_wls, 10))
## log_sqft sqft2 bedrooms bathrooms floors waterfront
## 1890.166353 3235.900572 1.792153 3.347972 2.145970 1.201251
## view grade grade2 condition
## 1.347618 1178.213975 444.307748 1.253729
Supuesto | Resultado | Interpretación |
---|---|---|
Linealidad (RESET) | p ≈ 1.4 × 10⁻⁸ (aún rechaza) | Queda curvatura menor; en práctica se tolera dada la elasticidad log/Box-Cox. |
Homoscedasticidad (BP) | p ≈ 7 × 10⁻²⁶⁵ → rechaza | Heteroscedasticidad estructural, pero usamos pesos + HC3, por lo que EE son consistentes. |
Normalidad (JB) | p ≈ 0 → rechaza | Con n ≫ 30 000, la ligera asimetría siempre se detecta; Box-Cox ya estiliza colas. |
Colinealidad (VIF) | VIF < 10 (log_sqft y sqft2 altos pero aceptables) | Sin inestabilidad numérica severa. |
Influencias (Cook D) | Máx ≈ 0.17 (> 4/n) | Algunos puntos caros influyen; HC3 penaliza su impacto. |
Independencia (DW) | ≈ 1.98 | No hay autocorrelación. |
Objetivo: construir un nuevo modelo lineal que mejore el AIC del modelo actual.
Nota:
- La normalidad de los residuos puede ignorarse (n ≫ 30).
- Si eliges WLS con errores robustos (HC3), la heteroscedasticidad deja de ser un problema práctico; los demás supuestos deben revisarse.
Explora nuevas variables o transformaciones
Ajusta el modelo
lm(...)
o lm(..., weights=...)
en
R.coeftest
con vcovHC
para obtener
errores robustos.Diagnostica los supuestos clave
resettest
(p > 0.05 deseable).vif
(ideal <
10).dwtest
≈ 2.bptest
.Compara AIC
AIC(model)
.AIC_new < AIC_prev
y no viola los supuestos revisados en 3.# Preparación de datos y pesos para el modelo final
df <- df %>%
mutate(
log_price = log(price),
w = 1 / log_sqft^2,
zipcode = as.factor(zipcode) # Asegurarse de que zipcode sea un factor
)
# ---------- 1. Fórmula lineal completa ----------
formula_final_zip <- log_price ~ log_sqft + sqft2 + bedrooms + bathrooms + floors +
waterfront + view + grade + grade2 + condition + renovated +
log_lot + sqft_grade + age + age2 +
lat + long + zipcode
# ---------- 2. WLS con pesos fijos y errores robustos ----------
wls_w_zip <- lm(formula_final_zip, data = df, weights = w)
wls_w_zip_robust_summary <- coeftest(wls_w_zip, vcov = vcovHC(wls_w_zip, type = "HC3"))
# Imprimir el resumen
print(summary(wls_w_zip)) # Resumen estándar para R-cuadrado, etc.
##
## Call:
## lm(formula = formula_final_zip, data = df, weights = w)
##
## Weighted Residuals:
## Min 1Q Median 3Q Max
## -0.185122 -0.012468 0.000989 0.013405 0.140334
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.260e+01 6.951e+00 -11.884 < 2e-16 ***
## log_sqft 4.763e-01 1.265e-01 3.766 0.000167 ***
## sqft2 -4.575e-02 1.103e-02 -4.146 3.40e-05 ***
## bedrooms -8.418e-03 1.823e-03 -4.618 3.91e-06 ***
## bathrooms 1.961e-02 3.021e-03 6.490 8.78e-11 ***
## floors -9.006e-03 3.458e-03 -2.604 0.009210 **
## waterfront 4.492e-01 1.677e-02 26.783 < 2e-16 ***
## view 6.475e-02 2.020e-03 32.062 < 2e-16 ***
## grade -3.624e-01 3.661e-02 -9.900 < 2e-16 ***
## grade2 -1.200e-02 1.406e-03 -8.537 < 2e-16 ***
## condition 5.614e-02 2.173e-03 25.828 < 2e-16 ***
## renovated 7.318e-02 6.719e-03 10.891 < 2e-16 ***
## log_lot 8.132e-02 2.195e-03 37.056 < 2e-16 ***
## sqft_grade 8.546e-02 6.998e-03 12.213 < 2e-16 ***
## age -4.693e-03 2.274e-04 -20.639 < 2e-16 ***
## age2 4.251e-05 1.869e-06 22.740 < 2e-16 ***
## lat 5.614e-01 7.221e-02 7.775 7.91e-15 ***
## long -5.339e-01 5.106e-02 -10.458 < 2e-16 ***
## zipcode98002 2.510e-02 1.609e-02 1.560 0.118865
## zipcode98003 1.386e-02 1.457e-02 0.951 0.341431
## zipcode98004 1.028e+00 2.685e-02 38.290 < 2e-16 ***
## zipcode98005 6.646e-01 2.872e-02 23.141 < 2e-16 ***
## zipcode98006 5.996e-01 2.340e-02 25.623 < 2e-16 ***
## zipcode98007 5.970e-01 2.948e-02 20.247 < 2e-16 ***
## zipcode98008 6.087e-01 2.799e-02 21.744 < 2e-16 ***
## zipcode98010 3.477e-01 2.480e-02 14.023 < 2e-16 ***
## zipcode98011 2.714e-01 3.648e-02 7.439 1.05e-13 ***
## zipcode98014 2.894e-01 3.984e-02 7.265 3.85e-13 ***
## zipcode98019 2.486e-01 3.931e-02 6.324 2.59e-10 ***
## zipcode98022 2.285e-01 2.147e-02 10.645 < 2e-16 ***
## zipcode98023 -5.407e-02 1.339e-02 -4.037 5.43e-05 ***
## zipcode98024 4.546e-01 3.479e-02 13.066 < 2e-16 ***
## zipcode98027 5.273e-01 2.387e-02 22.093 < 2e-16 ***
## zipcode98028 2.061e-01 3.542e-02 5.820 5.98e-09 ***
## zipcode98029 6.384e-01 2.731e-02 23.375 < 2e-16 ***
## zipcode98030 7.668e-02 1.606e-02 4.774 1.81e-06 ***
## zipcode98031 8.701e-02 1.672e-02 5.205 1.96e-07 ***
## zipcode98032 -4.601e-02 1.918e-02 -2.400 0.016425 *
## zipcode98033 6.475e-01 3.039e-02 21.304 < 2e-16 ***
## zipcode98034 3.776e-01 3.255e-02 11.601 < 2e-16 ***
## zipcode98038 2.718e-01 1.796e-02 15.132 < 2e-16 ***
## zipcode98039 1.173e+00 3.752e-02 31.269 < 2e-16 ***
## zipcode98040 8.093e-01 2.391e-02 33.846 < 2e-16 ***
## zipcode98042 1.264e-01 1.531e-02 8.258 < 2e-16 ***
## zipcode98045 4.922e-01 3.303e-02 14.902 < 2e-16 ***
## zipcode98052 5.451e-01 3.091e-02 17.632 < 2e-16 ***
## zipcode98053 5.203e-01 3.314e-02 15.701 < 2e-16 ***
## zipcode98055 1.231e-01 1.861e-02 6.618 3.73e-11 ***
## zipcode98056 2.768e-01 2.028e-02 13.650 < 2e-16 ***
## zipcode98058 1.738e-01 1.761e-02 9.873 < 2e-16 ***
## zipcode98059 3.309e-01 1.990e-02 16.628 < 2e-16 ***
## zipcode98065 5.274e-01 3.074e-02 17.156 < 2e-16 ***
## zipcode98070 8.873e-02 2.332e-02 3.805 0.000142 ***
## zipcode98072 3.219e-01 3.625e-02 8.881 < 2e-16 ***
## zipcode98074 5.328e-01 2.927e-02 18.200 < 2e-16 ***
## zipcode98075 5.745e-01 2.816e-02 20.400 < 2e-16 ***
## zipcode98077 3.133e-01 3.777e-02 8.295 < 2e-16 ***
## zipcode98092 8.659e-02 1.464e-02 5.914 3.38e-09 ***
## zipcode98102 8.047e-01 3.129e-02 25.715 < 2e-16 ***
## zipcode98103 6.035e-01 2.938e-02 20.538 < 2e-16 ***
## zipcode98105 7.777e-01 3.021e-02 25.739 < 2e-16 ***
## zipcode98106 1.893e-01 2.154e-02 8.788 < 2e-16 ***
## zipcode98107 6.179e-01 3.019e-02 20.468 < 2e-16 ***
## zipcode98108 2.213e-01 2.380e-02 9.299 < 2e-16 ***
## zipcode98109 8.003e-01 3.120e-02 25.652 < 2e-16 ***
## zipcode98112 8.854e-01 2.780e-02 31.854 < 2e-16 ***
## zipcode98115 6.246e-01 2.986e-02 20.918 < 2e-16 ***
## zipcode98116 5.715e-01 2.420e-02 23.611 < 2e-16 ***
## zipcode98117 5.720e-01 3.021e-02 18.936 < 2e-16 ***
## zipcode98118 3.498e-01 2.113e-02 16.555 < 2e-16 ***
## zipcode98119 7.710e-01 2.948e-02 26.150 < 2e-16 ***
## zipcode98122 6.507e-01 2.628e-02 24.759 < 2e-16 ***
## zipcode98125 3.572e-01 3.221e-02 11.089 < 2e-16 ***
## zipcode98126 3.813e-01 2.208e-02 17.269 < 2e-16 ***
## zipcode98133 2.140e-01 3.323e-02 6.440 1.22e-10 ***
## zipcode98136 5.172e-01 2.271e-02 22.770 < 2e-16 ***
## zipcode98144 5.223e-01 2.444e-02 21.377 < 2e-16 ***
## zipcode98146 1.330e-01 2.020e-02 6.586 4.63e-11 ***
## zipcode98148 8.730e-02 2.703e-02 3.230 0.001241 **
## zipcode98155 1.887e-01 3.458e-02 5.455 4.94e-08 ***
## zipcode98166 1.978e-01 1.863e-02 10.618 < 2e-16 ***
## zipcode98168 -3.600e-02 1.943e-02 -1.853 0.063930 .
## zipcode98177 3.369e-01 3.481e-02 9.678 < 2e-16 ***
## zipcode98178 8.003e-02 2.019e-02 3.964 7.40e-05 ***
## zipcode98188 3.016e-02 2.065e-02 1.461 0.144062
## zipcode98198 1.888e-02 1.563e-02 1.207 0.227338
## zipcode98199 6.479e-01 2.874e-02 22.548 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02418 on 21526 degrees of freedom
## Multiple R-squared: 0.8774, Adjusted R-squared: 0.8769
## F-statistic: 1791 on 86 and 21526 DF, p-value: < 2.2e-16
print(wls_w_zip_robust_summary) # Resumen con errores robustos para coeficientes
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.2604e+01 8.2188e+00 -10.0507 < 2.2e-16 ***
## log_sqft 4.7627e-01 1.5691e-01 3.0354 0.0024053 **
## sqft2 -4.5748e-02 1.3014e-02 -3.5154 0.0004401 ***
## bedrooms -8.4176e-03 2.2602e-03 -3.7244 0.0001963 ***
## bathrooms 1.9606e-02 3.3169e-03 5.9111 3.450e-09 ***
## floors -9.0062e-03 3.4621e-03 -2.6014 0.0092919 **
## waterfront 4.4918e-01 2.3627e-02 19.0116 < 2.2e-16 ***
## view 6.4752e-02 2.3111e-03 28.0174 < 2.2e-16 ***
## grade -3.6242e-01 4.5317e-02 -7.9973 1.335e-15 ***
## grade2 -1.2001e-02 1.6499e-03 -7.2737 3.617e-13 ***
## condition 5.6138e-02 2.6413e-03 21.2535 < 2.2e-16 ***
## renovated 7.3183e-02 8.1907e-03 8.9349 < 2.2e-16 ***
## log_lot 8.1323e-02 2.6966e-03 30.1582 < 2.2e-16 ***
## sqft_grade 8.5464e-02 8.1091e-03 10.5392 < 2.2e-16 ***
## age -4.6927e-03 2.5075e-04 -18.7146 < 2.2e-16 ***
## age2 4.2508e-05 2.1785e-06 19.5130 < 2.2e-16 ***
## lat 5.6138e-01 7.9901e-02 7.0260 2.189e-12 ***
## long -5.3392e-01 6.1562e-02 -8.6729 < 2.2e-16 ***
## zipcode98002 2.5098e-02 1.4611e-02 1.7178 0.0858525 .
## zipcode98003 1.3858e-02 1.3085e-02 1.0591 0.2895716
## zipcode98004 1.0283e+00 2.8724e-02 35.7982 < 2.2e-16 ***
## zipcode98005 6.6456e-01 2.9706e-02 22.3710 < 2.2e-16 ***
## zipcode98006 5.9959e-01 2.5088e-02 23.8999 < 2.2e-16 ***
## zipcode98007 5.9696e-01 2.9324e-02 20.3574 < 2.2e-16 ***
## zipcode98008 6.0865e-01 2.9295e-02 20.7770 < 2.2e-16 ***
## zipcode98010 3.4772e-01 3.6776e-02 9.4551 < 2.2e-16 ***
## zipcode98011 2.7140e-01 3.8189e-02 7.1068 1.224e-12 ***
## zipcode98014 2.8942e-01 4.8181e-02 6.0070 1.921e-09 ***
## zipcode98019 2.4861e-01 4.2364e-02 5.8685 4.462e-09 ***
## zipcode98022 2.2854e-01 2.2617e-02 10.1048 < 2.2e-16 ***
## zipcode98023 -5.4065e-02 1.2948e-02 -4.1754 2.986e-05 ***
## zipcode98024 4.5460e-01 3.7948e-02 11.9796 < 2.2e-16 ***
## zipcode98027 5.2734e-01 2.6457e-02 19.9317 < 2.2e-16 ***
## zipcode98028 2.0613e-01 3.7717e-02 5.4652 4.676e-08 ***
## zipcode98029 6.3839e-01 2.8896e-02 22.0924 < 2.2e-16 ***
## zipcode98030 7.6676e-02 1.4453e-02 5.3053 1.136e-07 ***
## zipcode98031 8.7012e-02 1.5209e-02 5.7211 1.072e-08 ***
## zipcode98032 -4.6014e-02 2.0521e-02 -2.2423 0.0249491 *
## zipcode98033 6.4747e-01 3.3302e-02 19.4423 < 2.2e-16 ***
## zipcode98034 3.7764e-01 3.5183e-02 10.7336 < 2.2e-16 ***
## zipcode98038 2.7182e-01 1.9063e-02 14.2588 < 2.2e-16 ***
## zipcode98039 1.1732e+00 3.5899e-02 32.6793 < 2.2e-16 ***
## zipcode98040 8.0931e-01 2.4570e-02 32.9394 < 2.2e-16 ***
## zipcode98042 1.2645e-01 1.5696e-02 8.0562 8.279e-16 ***
## zipcode98045 4.9217e-01 3.7782e-02 13.0265 < 2.2e-16 ***
## zipcode98052 5.4509e-01 3.3451e-02 16.2953 < 2.2e-16 ***
## zipcode98053 5.2031e-01 3.6505e-02 14.2529 < 2.2e-16 ***
## zipcode98055 1.2314e-01 1.9705e-02 6.2489 4.212e-10 ***
## zipcode98056 2.7683e-01 2.1240e-02 13.0334 < 2.2e-16 ***
## zipcode98058 1.7385e-01 1.8152e-02 9.5774 < 2.2e-16 ***
## zipcode98059 3.3094e-01 2.0681e-02 16.0025 < 2.2e-16 ***
## zipcode98065 5.2738e-01 3.3500e-02 15.7428 < 2.2e-16 ***
## zipcode98070 8.8727e-02 2.8501e-02 3.1132 0.0018533 **
## zipcode98072 3.2193e-01 3.8876e-02 8.2809 < 2.2e-16 ***
## zipcode98074 5.3278e-01 3.1675e-02 16.8203 < 2.2e-16 ***
## zipcode98075 5.7448e-01 3.0388e-02 18.9049 < 2.2e-16 ***
## zipcode98077 3.1335e-01 4.0205e-02 7.7937 6.803e-15 ***
## zipcode98092 8.6594e-02 1.3647e-02 6.3454 2.263e-10 ***
## zipcode98102 8.0472e-01 3.3561e-02 23.9777 < 2.2e-16 ***
## zipcode98103 6.0345e-01 3.1939e-02 18.8937 < 2.2e-16 ***
## zipcode98105 7.7766e-01 3.2157e-02 24.1835 < 2.2e-16 ***
## zipcode98106 1.8926e-01 2.4042e-02 7.8718 3.661e-15 ***
## zipcode98107 6.1791e-01 3.1732e-02 19.4729 < 2.2e-16 ***
## zipcode98108 2.2132e-01 2.8313e-02 7.8169 5.660e-15 ***
## zipcode98109 8.0031e-01 3.7487e-02 21.3492 < 2.2e-16 ***
## zipcode98112 8.8545e-01 3.1433e-02 28.1693 < 2.2e-16 ***
## zipcode98115 6.2457e-01 3.2272e-02 19.3533 < 2.2e-16 ***
## zipcode98116 5.7150e-01 2.5556e-02 22.3624 < 2.2e-16 ***
## zipcode98117 5.7202e-01 3.2658e-02 17.5156 < 2.2e-16 ***
## zipcode98118 3.4980e-01 2.4563e-02 14.2409 < 2.2e-16 ***
## zipcode98119 7.7102e-01 3.2608e-02 23.6453 < 2.2e-16 ***
## zipcode98122 6.5069e-01 2.8858e-02 22.5480 < 2.2e-16 ***
## zipcode98125 3.5718e-01 3.5131e-02 10.1670 < 2.2e-16 ***
## zipcode98126 3.8134e-01 2.4329e-02 15.6742 < 2.2e-16 ***
## zipcode98133 2.1399e-01 3.6041e-02 5.9373 2.942e-09 ***
## zipcode98136 5.1721e-01 2.3599e-02 21.9165 < 2.2e-16 ***
## zipcode98144 5.2235e-01 2.6385e-02 19.7973 < 2.2e-16 ***
## zipcode98146 1.3300e-01 2.5030e-02 5.3136 1.085e-07 ***
## zipcode98148 8.7300e-02 3.3631e-02 2.5958 0.0094428 **
## zipcode98155 1.8867e-01 3.7418e-02 5.0423 4.637e-07 ***
## zipcode98166 1.9783e-01 2.1001e-02 9.4198 < 2.2e-16 ***
## zipcode98168 -3.6002e-02 2.2389e-02 -1.6080 0.1078505
## zipcode98177 3.3692e-01 3.8341e-02 8.7875 < 2.2e-16 ***
## zipcode98178 8.0030e-02 2.1655e-02 3.6956 0.0002199 ***
## zipcode98188 3.0160e-02 2.1403e-02 1.4091 0.1588095
## zipcode98198 1.8875e-02 1.6859e-02 1.1196 0.2628986
## zipcode98199 6.4795e-01 3.0746e-02 21.0739 < 2.2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
# ---------- 3. Diagnósticos esenciales ----------
# AJUSTE: Crear un modelo OLS solo para las pruebas que no soportan WLS
ols_for_diag <- lm(formula_final_zip, data = df)
reset_p <- resettest(wls_w_zip, power = 2, type = "fitted")$p.value
bp_p <- bptest(wls_w_zip)$p.value
jb_p <- jarque.bera.test(resid(wls_w_zip))$p.value
# AJUSTE: Usar el modelo OLS para la prueba de Durbin-Watson
dw <- dwtest(ols_for_diag)$statistic
cat(paste("\nRESET p-value :", format(reset_p, scientific = TRUE, digits = 4)))
##
## RESET p-value : 4.547e-07
cat(paste("\nBreusch–Pagan p-value:", bp_p))
##
## Breusch–Pagan p-value: 0.148661146926444
cat(paste("\nJarque–Bera p-value :", jb_p))
##
## Jarque–Bera p-value : 0
cat(paste("\nDurbin–Watson :", round(dw, 3)))
##
## Durbin–Watson : 2.006
# ---------- 4. VIF numéricas ----------
# El cálculo de VIF ya se hacía correctamente sobre un modelo OLS, así que no hay cambios aquí.
vif_model_zip <- lm(log_price ~ log_sqft + sqft2 + bedrooms + bathrooms + floors +
waterfront + view + grade + grade2 + condition + renovated +
log_lot + sqft_grade + age + age2 + lat + long,
data = df)
vif_values_zip <- vif(vif_model_zip)
cat("\nMáx VIF numéricas:", max(vif_values_zip))
##
## Máx VIF numéricas: 4283.198
# La selección hacia adelante (Forward Selection) en R se puede hacer eficientemente
# con la función step(). Compara modelos usando el Criterio de Información de Akaike (AIC).
# Crear un modelo base (solo intercepto) para la selección de variables
model_base <- lm(log_price ~ 1, data = df, weights = w)
# Crear un modelo completo con todas las variables candidatas
# zipcode se trata como un solo bloque
candidatas_formula <- log_price ~ log_sqft + sqft2 + bedrooms + bathrooms + floors +
waterfront + view + grade + grade2 + condition + renovated +
log_lot + sqft_grade + age + age2 + lat + long + zipcode
model_full <- lm(candidatas_formula, data = df, weights = w)
# Ejecutar la selección hacia adelante
# 'scope' define los modelos mínimo y máximo a considerar.
# 'direction' especifica que es una selección hacia adelante.
# 'trace = 1' muestra los pasos del proceso. En R Markdown, a veces la salida puede ser voluminosa,
# por lo que podrías usar 'trace = 0' para no mostrar los pasos y solo ver el resultado final.
modelo_final_stepwise <- step(model_base,
scope = list(lower = model_base, upper = model_full),
direction = "forward",
trace = 1)
## Start: AIC=-115618
## log_price ~ 1
##
## Df Sum of Sq RSS AIC
## + sqft_grade 1 53.971 48.695 -131737
## + zipcode 69 54.250 48.417 -131725
## + grade2 1 49.282 53.384 -129750
## + grade 1 49.233 53.434 -129730
## + sqft2 1 45.927 56.740 -128433
## + log_sqft 1 45.085 57.582 -128114
## + bathrooms 1 29.985 72.682 -123081
## + lat 1 21.112 81.555 -120592
## + bedrooms 1 12.145 90.522 -118337
## + view 1 11.389 91.278 -118157
## + floors 1 9.849 92.817 -117796
## + waterfront 1 2.727 99.940 -116198
## + log_lot 1 1.400 101.266 -115913
## + renovated 1 1.216 101.451 -115873
## + age 1 0.708 101.959 -115766
## + long 1 0.214 102.453 -115661
## + condition 1 0.185 102.482 -115655
## + age2 1 0.044 102.623 -115625
## <none> 102.667 -115618
##
## Step: AIC=-131737.3
## log_price ~ sqft_grade
##
## Df Sum of Sq RSS AIC
## + zipcode 69 29.2847 19.411 -151478
## + lat 1 15.3042 33.391 -139890
## + age2 1 8.1332 40.562 -135685
## + age 1 7.3878 41.308 -135291
## + view 1 2.3564 46.339 -132807
## + condition 1 1.7196 46.976 -132512
## + long 1 1.4291 47.266 -132379
## + waterfront 1 1.1226 47.573 -132239
## + grade 1 1.0655 47.630 -132213
## + sqft2 1 0.9265 47.769 -132150
## + renovated 1 0.8529 47.843 -132117
## + log_sqft 1 0.8291 47.866 -132106
## + grade2 1 0.7080 47.988 -132052
## + log_lot 1 0.1745 48.521 -131813
## + floors 1 0.0524 48.643 -131759
## + bathrooms 1 0.0415 48.654 -131754
## + bedrooms 1 0.0213 48.674 -131745
## <none> 48.695 -131737
##
## Step: AIC=-151478
## log_price ~ sqft_grade + zipcode
##
## Df Sum of Sq RSS AIC
## + grade 1 3.3255 16.085 -155538
## + sqft2 1 2.9828 16.428 -155082
## + log_sqft 1 2.8492 16.562 -154907
## + grade2 1 2.4059 17.005 -154336
## + view 1 1.8399 17.571 -153628
## + log_lot 1 1.8355 17.575 -153623
## + waterfront 1 1.2314 18.179 -152893
## + age2 1 1.0894 18.321 -152724
## + age 1 1.0816 18.329 -152715
## + condition 1 0.8660 18.545 -152462
## + bedrooms 1 0.4445 18.966 -151977
## + bathrooms 1 0.3952 19.016 -151921
## + renovated 1 0.2532 19.158 -151760
## + floors 1 0.2045 19.206 -151705
## + long 1 0.0273 19.383 -151506
## + lat 1 0.0108 19.400 -151488
## <none> 19.411 -151478
##
## Step: AIC=-155537.6
## log_price ~ sqft_grade + zipcode + grade
##
## Df Sum of Sq RSS AIC
## + view 1 1.41521 14.670 -157526
## + waterfront 1 1.13276 14.953 -157114
## + log_lot 1 0.85266 15.233 -156713
## + condition 1 0.50697 15.578 -156228
## + age2 1 0.41414 15.671 -156099
## + age 1 0.40533 15.680 -156087
## + renovated 1 0.14583 15.940 -155732
## + floors 1 0.12835 15.957 -155709
## + bedrooms 1 0.04192 16.043 -155592
## + long 1 0.04159 16.044 -155592
## + lat 1 0.01607 16.069 -155557
## + grade2 1 0.01205 16.073 -155552
## + bathrooms 1 0.00228 16.083 -155539
## <none> 16.085 -155538
## + sqft2 1 0.00031 16.085 -155536
## + log_sqft 1 0.00012 16.085 -155536
##
## Step: AIC=-157526
## log_price ~ sqft_grade + zipcode + grade + view
##
## Df Sum of Sq RSS AIC
## + log_lot 1 0.66560 14.005 -158528
## + waterfront 1 0.43694 14.233 -158178
## + condition 1 0.42432 14.246 -158158
## + age2 1 0.28145 14.389 -157943
## + age 1 0.23689 14.433 -157876
## + renovated 1 0.08981 14.580 -157657
## + floors 1 0.06413 14.606 -157619
## + grade2 1 0.04432 14.626 -157589
## + long 1 0.03273 14.637 -157572
## + lat 1 0.02313 14.647 -157558
## + sqft2 1 0.01841 14.652 -157551
## + log_sqft 1 0.01786 14.652 -157550
## + bedrooms 1 0.00916 14.661 -157538
## <none> 14.670 -157526
## + bathrooms 1 0.00005 14.670 -157524
##
## Step: AIC=-158527.6
## log_price ~ sqft_grade + zipcode + grade + view + log_lot
##
## Df Sum of Sq RSS AIC
## + waterfront 1 0.45095 13.553 -159233
## + condition 1 0.31578 13.689 -159018
## + age2 1 0.09730 13.907 -158676
## + grade2 1 0.08932 13.915 -158664
## + long 1 0.07491 13.930 -158641
## + renovated 1 0.07245 13.932 -158638
## + sqft2 1 0.05917 13.945 -158617
## + log_sqft 1 0.05836 13.946 -158616
## + bathrooms 1 0.05185 13.953 -158606
## + age 1 0.02893 13.976 -158570
## + lat 1 0.02740 13.977 -158568
## + floors 1 0.00573 13.999 -158534
## + bedrooms 1 0.00397 14.001 -158532
## <none> 14.005 -158528
##
## Step: AIC=-159233
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront
##
## Df Sum of Sq RSS AIC
## + condition 1 0.31681 13.237 -159742
## + grade2 1 0.10281 13.451 -159396
## + age2 1 0.08543 13.468 -159368
## + sqft2 1 0.06764 13.486 -159339
## + log_sqft 1 0.06722 13.486 -159338
## + long 1 0.06667 13.487 -159338
## + renovated 1 0.05254 13.501 -159315
## + bathrooms 1 0.05079 13.503 -159312
## + lat 1 0.03234 13.521 -159283
## + age 1 0.02390 13.530 -159269
## + floors 1 0.00282 13.551 -159235
## + bedrooms 1 0.00132 13.552 -159233
## <none> 13.553 -159233
##
## Step: AIC=-159742.2
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition
##
## Df Sum of Sq RSS AIC
## + grade2 1 0.083800 13.153 -159877
## + renovated 1 0.079262 13.158 -159870
## + bathrooms 1 0.065188 13.171 -159847
## + long 1 0.061574 13.175 -159841
## + sqft2 1 0.051545 13.185 -159824
## + log_sqft 1 0.050420 13.186 -159823
## + lat 1 0.037248 13.200 -159801
## + age2 1 0.028182 13.209 -159786
## + floors 1 0.024137 13.213 -159780
## + bedrooms 1 0.004166 13.233 -159747
## <none> 13.237 -159742
## + age 1 0.000123 13.237 -159740
##
## Step: AIC=-159877.4
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2
##
## Df Sum of Sq RSS AIC
## + renovated 1 0.073098 13.080 -159996
## + long 1 0.056456 13.097 -159968
## + age2 1 0.048151 13.105 -159955
## + bathrooms 1 0.047753 13.105 -159954
## + lat 1 0.037673 13.115 -159937
## + floors 1 0.021643 13.131 -159911
## + bedrooms 1 0.017506 13.135 -159904
## + sqft2 1 0.005474 13.147 -159884
## + log_sqft 1 0.003344 13.150 -159881
## <none> 13.153 -159877
## + age 1 0.001011 13.152 -159877
##
## Step: AIC=-159995.9
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated
##
## Df Sum of Sq RSS AIC
## + long 1 0.057386 13.022 -160089
## + bathrooms 1 0.043395 13.036 -160066
## + lat 1 0.036738 13.043 -160055
## + age2 1 0.024533 13.055 -160034
## + floors 1 0.021737 13.058 -160030
## + bedrooms 1 0.016748 13.063 -160022
## + sqft2 1 0.006176 13.074 -160004
## + log_sqft 1 0.003686 13.076 -160000
## + age 1 0.001785 13.078 -159997
## <none> 13.080 -159996
##
## Step: AIC=-160088.9
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long
##
## Df Sum of Sq RSS AIC
## + bathrooms 1 0.045933 12.976 -160163
## + lat 1 0.031562 12.991 -160139
## + floors 1 0.024889 12.998 -160128
## + age2 1 0.020897 13.002 -160122
## + bedrooms 1 0.016989 13.005 -160115
## + sqft2 1 0.006369 13.016 -160097
## + log_sqft 1 0.003846 13.019 -160093
## + age 1 0.003438 13.019 -160093
## <none> 13.022 -160089
##
## Step: AIC=-160163.3
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms
##
## Df Sum of Sq RSS AIC
## + age2 1 0.048001 12.928 -160241
## + lat 1 0.032906 12.944 -160216
## + bedrooms 1 0.026102 12.950 -160205
## + floors 1 0.012223 12.964 -160182
## + sqft2 1 0.007478 12.969 -160174
## + log_sqft 1 0.004149 12.972 -160168
## <none> 12.976 -160163
## + age 1 0.000445 12.976 -160162
##
## Step: AIC=-160241.4
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2
##
## Df Sum of Sq RSS AIC
## + age 1 0.275721 12.653 -160705
## + lat 1 0.032828 12.896 -160294
## + bedrooms 1 0.031082 12.897 -160291
## + floors 1 0.019066 12.909 -160271
## + sqft2 1 0.005314 12.923 -160248
## + log_sqft 1 0.002812 12.926 -160244
## <none> 12.928 -160241
##
## Step: AIC=-160705.3
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2 +
## age
##
## Df Sum of Sq RSS AIC
## + lat 1 0.037032 12.616 -160767
## + bedrooms 1 0.014416 12.638 -160728
## + floors 1 0.005526 12.647 -160713
## + sqft2 1 0.004036 12.649 -160710
## + log_sqft 1 0.001515 12.651 -160706
## <none> 12.653 -160705
##
## Step: AIC=-160766.6
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2 +
## age + lat
##
## Df Sum of Sq RSS AIC
## + bedrooms 1 0.0140326 12.602 -160789
## + floors 1 0.0046092 12.611 -160773
## + sqft2 1 0.0040340 12.612 -160772
## + log_sqft 1 0.0015628 12.614 -160767
## <none> 12.616 -160767
##
## Step: AIC=-160788.7
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2 +
## age + lat + bedrooms
##
## Df Sum of Sq RSS AIC
## + floors 1 0.0042812 12.597 -160794
## + sqft2 1 0.0027519 12.599 -160791
## <none> 12.602 -160789
## + log_sqft 1 0.0008281 12.601 -160788
##
## Step: AIC=-160794
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2 +
## age + lat + bedrooms + floors
##
## Df Sum of Sq RSS AIC
## + sqft2 1 0.00240110 12.595 -160796
## <none> 12.597 -160794
## + log_sqft 1 0.00064215 12.597 -160793
##
## Step: AIC=-160796.2
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2 +
## age + lat + bedrooms + floors + sqft2
##
## Df Sum of Sq RSS AIC
## + log_sqft 1 0.0082911 12.587 -160808
## <none> 12.595 -160796
##
## Step: AIC=-160808.4
## log_price ~ sqft_grade + zipcode + grade + view + log_lot + waterfront +
## condition + grade2 + renovated + long + bathrooms + age2 +
## age + lat + bedrooms + floors + sqft2 + log_sqft
# Mostrar el resumen del modelo final seleccionado por step()
# con errores robustos para una inferencia más fiable
print("Modelo final:")
## [1] "Modelo final:"
summary_stepwise <- summary(modelo_final_stepwise)
print(summary_stepwise) # Resumen estándar
##
## Call:
## lm(formula = log_price ~ sqft_grade + zipcode + grade + view +
## log_lot + waterfront + condition + grade2 + renovated + long +
## bathrooms + age2 + age + lat + bedrooms + floors + sqft2 +
## log_sqft, data = df, weights = w)
##
## Weighted Residuals:
## Min 1Q Median 3Q Max
## -0.185122 -0.012468 0.000989 0.013405 0.140334
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.260e+01 6.951e+00 -11.884 < 2e-16 ***
## sqft_grade 8.546e-02 6.998e-03 12.213 < 2e-16 ***
## zipcode98002 2.510e-02 1.609e-02 1.560 0.118865
## zipcode98003 1.386e-02 1.457e-02 0.951 0.341431
## zipcode98004 1.028e+00 2.685e-02 38.290 < 2e-16 ***
## zipcode98005 6.646e-01 2.872e-02 23.141 < 2e-16 ***
## zipcode98006 5.996e-01 2.340e-02 25.623 < 2e-16 ***
## zipcode98007 5.970e-01 2.948e-02 20.247 < 2e-16 ***
## zipcode98008 6.087e-01 2.799e-02 21.744 < 2e-16 ***
## zipcode98010 3.477e-01 2.480e-02 14.023 < 2e-16 ***
## zipcode98011 2.714e-01 3.648e-02 7.439 1.05e-13 ***
## zipcode98014 2.894e-01 3.984e-02 7.265 3.85e-13 ***
## zipcode98019 2.486e-01 3.931e-02 6.324 2.59e-10 ***
## zipcode98022 2.285e-01 2.147e-02 10.645 < 2e-16 ***
## zipcode98023 -5.407e-02 1.339e-02 -4.037 5.43e-05 ***
## zipcode98024 4.546e-01 3.479e-02 13.066 < 2e-16 ***
## zipcode98027 5.273e-01 2.387e-02 22.093 < 2e-16 ***
## zipcode98028 2.061e-01 3.542e-02 5.820 5.98e-09 ***
## zipcode98029 6.384e-01 2.731e-02 23.375 < 2e-16 ***
## zipcode98030 7.668e-02 1.606e-02 4.774 1.81e-06 ***
## zipcode98031 8.701e-02 1.672e-02 5.205 1.96e-07 ***
## zipcode98032 -4.601e-02 1.918e-02 -2.400 0.016425 *
## zipcode98033 6.475e-01 3.039e-02 21.304 < 2e-16 ***
## zipcode98034 3.776e-01 3.255e-02 11.601 < 2e-16 ***
## zipcode98038 2.718e-01 1.796e-02 15.132 < 2e-16 ***
## zipcode98039 1.173e+00 3.752e-02 31.269 < 2e-16 ***
## zipcode98040 8.093e-01 2.391e-02 33.846 < 2e-16 ***
## zipcode98042 1.264e-01 1.531e-02 8.258 < 2e-16 ***
## zipcode98045 4.922e-01 3.303e-02 14.902 < 2e-16 ***
## zipcode98052 5.451e-01 3.091e-02 17.632 < 2e-16 ***
## zipcode98053 5.203e-01 3.314e-02 15.701 < 2e-16 ***
## zipcode98055 1.231e-01 1.861e-02 6.618 3.73e-11 ***
## zipcode98056 2.768e-01 2.028e-02 13.650 < 2e-16 ***
## zipcode98058 1.738e-01 1.761e-02 9.873 < 2e-16 ***
## zipcode98059 3.309e-01 1.990e-02 16.628 < 2e-16 ***
## zipcode98065 5.274e-01 3.074e-02 17.156 < 2e-16 ***
## zipcode98070 8.873e-02 2.332e-02 3.805 0.000142 ***
## zipcode98072 3.219e-01 3.625e-02 8.881 < 2e-16 ***
## zipcode98074 5.328e-01 2.927e-02 18.200 < 2e-16 ***
## zipcode98075 5.745e-01 2.816e-02 20.400 < 2e-16 ***
## zipcode98077 3.133e-01 3.777e-02 8.295 < 2e-16 ***
## zipcode98092 8.659e-02 1.464e-02 5.914 3.38e-09 ***
## zipcode98102 8.047e-01 3.129e-02 25.715 < 2e-16 ***
## zipcode98103 6.035e-01 2.938e-02 20.538 < 2e-16 ***
## zipcode98105 7.777e-01 3.021e-02 25.739 < 2e-16 ***
## zipcode98106 1.893e-01 2.154e-02 8.788 < 2e-16 ***
## zipcode98107 6.179e-01 3.019e-02 20.468 < 2e-16 ***
## zipcode98108 2.213e-01 2.380e-02 9.299 < 2e-16 ***
## zipcode98109 8.003e-01 3.120e-02 25.652 < 2e-16 ***
## zipcode98112 8.854e-01 2.780e-02 31.854 < 2e-16 ***
## zipcode98115 6.246e-01 2.986e-02 20.918 < 2e-16 ***
## zipcode98116 5.715e-01 2.420e-02 23.611 < 2e-16 ***
## zipcode98117 5.720e-01 3.021e-02 18.936 < 2e-16 ***
## zipcode98118 3.498e-01 2.113e-02 16.555 < 2e-16 ***
## zipcode98119 7.710e-01 2.948e-02 26.150 < 2e-16 ***
## zipcode98122 6.507e-01 2.628e-02 24.759 < 2e-16 ***
## zipcode98125 3.572e-01 3.221e-02 11.089 < 2e-16 ***
## zipcode98126 3.813e-01 2.208e-02 17.269 < 2e-16 ***
## zipcode98133 2.140e-01 3.323e-02 6.440 1.22e-10 ***
## zipcode98136 5.172e-01 2.271e-02 22.770 < 2e-16 ***
## zipcode98144 5.223e-01 2.444e-02 21.377 < 2e-16 ***
## zipcode98146 1.330e-01 2.020e-02 6.586 4.63e-11 ***
## zipcode98148 8.730e-02 2.703e-02 3.230 0.001241 **
## zipcode98155 1.887e-01 3.458e-02 5.455 4.94e-08 ***
## zipcode98166 1.978e-01 1.863e-02 10.618 < 2e-16 ***
## zipcode98168 -3.600e-02 1.943e-02 -1.853 0.063930 .
## zipcode98177 3.369e-01 3.481e-02 9.678 < 2e-16 ***
## zipcode98178 8.003e-02 2.019e-02 3.964 7.40e-05 ***
## zipcode98188 3.016e-02 2.065e-02 1.461 0.144062
## zipcode98198 1.888e-02 1.563e-02 1.207 0.227338
## zipcode98199 6.479e-01 2.874e-02 22.548 < 2e-16 ***
## grade -3.624e-01 3.661e-02 -9.900 < 2e-16 ***
## view 6.475e-02 2.020e-03 32.062 < 2e-16 ***
## log_lot 8.132e-02 2.195e-03 37.056 < 2e-16 ***
## waterfront 4.492e-01 1.677e-02 26.783 < 2e-16 ***
## condition 5.614e-02 2.173e-03 25.828 < 2e-16 ***
## grade2 -1.200e-02 1.406e-03 -8.537 < 2e-16 ***
## renovated 7.318e-02 6.719e-03 10.891 < 2e-16 ***
## long -5.339e-01 5.106e-02 -10.458 < 2e-16 ***
## bathrooms 1.961e-02 3.021e-03 6.490 8.78e-11 ***
## age2 4.251e-05 1.869e-06 22.740 < 2e-16 ***
## age -4.693e-03 2.274e-04 -20.639 < 2e-16 ***
## lat 5.614e-01 7.221e-02 7.775 7.91e-15 ***
## bedrooms -8.418e-03 1.823e-03 -4.618 3.91e-06 ***
## floors -9.006e-03 3.458e-03 -2.604 0.009210 **
## sqft2 -4.575e-02 1.103e-02 -4.146 3.40e-05 ***
## log_sqft 4.763e-01 1.265e-01 3.766 0.000167 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02418 on 21526 degrees of freedom
## Multiple R-squared: 0.8774, Adjusted R-squared: 0.8769
## F-statistic: 1791 on 86 and 21526 DF, p-value: < 2.2e-16
# Coeficientes con errores robustos
coeftest(modelo_final_stepwise, vcov. = vcovHC(modelo_final_stepwise, type = "HC3"))
##
## t test of coefficients:
##
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.2604e+01 8.2188e+00 -10.0507 < 2.2e-16 ***
## sqft_grade 8.5464e-02 8.1091e-03 10.5392 < 2.2e-16 ***
## zipcode98002 2.5098e-02 1.4611e-02 1.7178 0.0858525 .
## zipcode98003 1.3858e-02 1.3085e-02 1.0591 0.2895716
## zipcode98004 1.0283e+00 2.8724e-02 35.7982 < 2.2e-16 ***
## zipcode98005 6.6456e-01 2.9706e-02 22.3710 < 2.2e-16 ***
## zipcode98006 5.9959e-01 2.5088e-02 23.8999 < 2.2e-16 ***
## zipcode98007 5.9696e-01 2.9324e-02 20.3574 < 2.2e-16 ***
## zipcode98008 6.0865e-01 2.9295e-02 20.7770 < 2.2e-16 ***
## zipcode98010 3.4772e-01 3.6776e-02 9.4551 < 2.2e-16 ***
## zipcode98011 2.7140e-01 3.8189e-02 7.1068 1.224e-12 ***
## zipcode98014 2.8942e-01 4.8181e-02 6.0070 1.921e-09 ***
## zipcode98019 2.4861e-01 4.2364e-02 5.8685 4.462e-09 ***
## zipcode98022 2.2854e-01 2.2617e-02 10.1048 < 2.2e-16 ***
## zipcode98023 -5.4065e-02 1.2948e-02 -4.1754 2.986e-05 ***
## zipcode98024 4.5460e-01 3.7948e-02 11.9796 < 2.2e-16 ***
## zipcode98027 5.2734e-01 2.6457e-02 19.9317 < 2.2e-16 ***
## zipcode98028 2.0613e-01 3.7717e-02 5.4652 4.676e-08 ***
## zipcode98029 6.3839e-01 2.8896e-02 22.0924 < 2.2e-16 ***
## zipcode98030 7.6676e-02 1.4453e-02 5.3053 1.136e-07 ***
## zipcode98031 8.7012e-02 1.5209e-02 5.7211 1.072e-08 ***
## zipcode98032 -4.6014e-02 2.0521e-02 -2.2423 0.0249491 *
## zipcode98033 6.4747e-01 3.3302e-02 19.4423 < 2.2e-16 ***
## zipcode98034 3.7764e-01 3.5183e-02 10.7336 < 2.2e-16 ***
## zipcode98038 2.7182e-01 1.9063e-02 14.2588 < 2.2e-16 ***
## zipcode98039 1.1732e+00 3.5899e-02 32.6793 < 2.2e-16 ***
## zipcode98040 8.0931e-01 2.4570e-02 32.9394 < 2.2e-16 ***
## zipcode98042 1.2645e-01 1.5696e-02 8.0562 8.279e-16 ***
## zipcode98045 4.9217e-01 3.7782e-02 13.0265 < 2.2e-16 ***
## zipcode98052 5.4509e-01 3.3451e-02 16.2953 < 2.2e-16 ***
## zipcode98053 5.2031e-01 3.6505e-02 14.2529 < 2.2e-16 ***
## zipcode98055 1.2314e-01 1.9705e-02 6.2489 4.212e-10 ***
## zipcode98056 2.7683e-01 2.1240e-02 13.0334 < 2.2e-16 ***
## zipcode98058 1.7385e-01 1.8152e-02 9.5774 < 2.2e-16 ***
## zipcode98059 3.3094e-01 2.0681e-02 16.0025 < 2.2e-16 ***
## zipcode98065 5.2738e-01 3.3500e-02 15.7428 < 2.2e-16 ***
## zipcode98070 8.8727e-02 2.8501e-02 3.1132 0.0018533 **
## zipcode98072 3.2193e-01 3.8876e-02 8.2809 < 2.2e-16 ***
## zipcode98074 5.3278e-01 3.1675e-02 16.8203 < 2.2e-16 ***
## zipcode98075 5.7448e-01 3.0388e-02 18.9049 < 2.2e-16 ***
## zipcode98077 3.1335e-01 4.0205e-02 7.7937 6.803e-15 ***
## zipcode98092 8.6594e-02 1.3647e-02 6.3454 2.263e-10 ***
## zipcode98102 8.0472e-01 3.3561e-02 23.9777 < 2.2e-16 ***
## zipcode98103 6.0345e-01 3.1939e-02 18.8937 < 2.2e-16 ***
## zipcode98105 7.7766e-01 3.2157e-02 24.1835 < 2.2e-16 ***
## zipcode98106 1.8926e-01 2.4042e-02 7.8718 3.661e-15 ***
## zipcode98107 6.1791e-01 3.1732e-02 19.4729 < 2.2e-16 ***
## zipcode98108 2.2132e-01 2.8313e-02 7.8169 5.660e-15 ***
## zipcode98109 8.0031e-01 3.7487e-02 21.3492 < 2.2e-16 ***
## zipcode98112 8.8545e-01 3.1433e-02 28.1693 < 2.2e-16 ***
## zipcode98115 6.2457e-01 3.2272e-02 19.3533 < 2.2e-16 ***
## zipcode98116 5.7150e-01 2.5556e-02 22.3624 < 2.2e-16 ***
## zipcode98117 5.7202e-01 3.2658e-02 17.5156 < 2.2e-16 ***
## zipcode98118 3.4980e-01 2.4563e-02 14.2409 < 2.2e-16 ***
## zipcode98119 7.7102e-01 3.2608e-02 23.6453 < 2.2e-16 ***
## zipcode98122 6.5069e-01 2.8858e-02 22.5480 < 2.2e-16 ***
## zipcode98125 3.5718e-01 3.5131e-02 10.1670 < 2.2e-16 ***
## zipcode98126 3.8134e-01 2.4329e-02 15.6742 < 2.2e-16 ***
## zipcode98133 2.1399e-01 3.6041e-02 5.9373 2.942e-09 ***
## zipcode98136 5.1721e-01 2.3599e-02 21.9165 < 2.2e-16 ***
## zipcode98144 5.2235e-01 2.6385e-02 19.7973 < 2.2e-16 ***
## zipcode98146 1.3300e-01 2.5030e-02 5.3136 1.085e-07 ***
## zipcode98148 8.7300e-02 3.3631e-02 2.5958 0.0094428 **
## zipcode98155 1.8867e-01 3.7418e-02 5.0423 4.637e-07 ***
## zipcode98166 1.9783e-01 2.1001e-02 9.4198 < 2.2e-16 ***
## zipcode98168 -3.6002e-02 2.2389e-02 -1.6080 0.1078505
## zipcode98177 3.3692e-01 3.8341e-02 8.7875 < 2.2e-16 ***
## zipcode98178 8.0030e-02 2.1655e-02 3.6956 0.0002199 ***
## zipcode98188 3.0160e-02 2.1403e-02 1.4091 0.1588095
## zipcode98198 1.8875e-02 1.6859e-02 1.1196 0.2628986
## zipcode98199 6.4795e-01 3.0746e-02 21.0739 < 2.2e-16 ***
## grade -3.6242e-01 4.5317e-02 -7.9973 1.335e-15 ***
## view 6.4752e-02 2.3111e-03 28.0174 < 2.2e-16 ***
## log_lot 8.1323e-02 2.6966e-03 30.1582 < 2.2e-16 ***
## waterfront 4.4918e-01 2.3627e-02 19.0116 < 2.2e-16 ***
## condition 5.6138e-02 2.6413e-03 21.2535 < 2.2e-16 ***
## grade2 -1.2001e-02 1.6499e-03 -7.2737 3.617e-13 ***
## renovated 7.3183e-02 8.1907e-03 8.9349 < 2.2e-16 ***
## long -5.3392e-01 6.1562e-02 -8.6729 < 2.2e-16 ***
## bathrooms 1.9606e-02 3.3169e-03 5.9111 3.450e-09 ***
## age2 4.2508e-05 2.1785e-06 19.5130 < 2.2e-16 ***
## age -4.6927e-03 2.5075e-04 -18.7146 < 2.2e-16 ***
## lat 5.6138e-01 7.9901e-02 7.0260 2.189e-12 ***
## bedrooms -8.4176e-03 2.2602e-03 -3.7244 0.0001963 ***
## floors -9.0062e-03 3.4621e-03 -2.6014 0.0092919 **
## sqft2 -4.5748e-02 1.3014e-02 -3.5154 0.0004401 ***
## log_sqft 4.7627e-01 1.5691e-01 3.0354 0.0024053 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
La selección de variables es una técnica clave en la construcción de modelos estadísticos y de machine learning. Se utiliza para identificar el subconjunto más relevante de variables explicativas (predictoras) que expliquen la variable dependiente sin sobreajustar ni incluir ruido innecesario.
Comienza con ninguna variable en el modelo (solo intercepto).
Para cada variable candidata que no esté en el modelo:
Añade la variable que más mejora el modelo, siempre que cumpla un criterio (por ejemplo, p-valor < 0.05).
Repite el proceso hasta que ninguna variable adicional cumpla el criterio.
Comienza con un modelo vacío o parcial.
En cada iteración:
Repite el proceso hasta que no se puedan añadir ni quitar más variables.
# Crear modelo base (solo intercepto) y modelo completo
model_base <- lm(y ~ 1, data = df)
model_full <- lm(y ~ x1 + x2 + x3 + ..., data = df)
# Selección Forward (hacia adelante)
step(model_base, scope = list(lower=model_base, upper=model_full), direction="forward")
# Selección Backward (hacia atrás)
step(model_full, direction="backward")
# Selección Stepwise (ambas direcciones)
step(model_base, scope = list(lower=model_base, upper=model_full), direction="both")