Preparación previa al análisis PCA

1. Carga de datos:

Antes de proceder con el análisis de componentes principales (PCA), es fundamental contar con los conjuntos de datos ya depurados. Para evitar repetir el proceso de limpieza, hemos guardado las versiones finales de las bases de datos en archivos .Rds.

Las bases limpias se guardaron utilizando los siguientes comandos:

saveRDS(Valencia_Sale, file = "base_2018_limpia.Rds")
saveRDS(Valencia_Sale_2025, file = "base_2025_limpia.Rds")

Una vez guardadas, podemos cargarlas fácilmente en el entorno mediante:

Valencia_2018 <- readRDS("base_2018_limpia.Rds")
Valencia_2025 <- readRDS("base_2025_limpia.Rds")

Así, podremos proceder con los datos previamente depurados, lo que garantiza mayor coherencia y eficiencia en el análisis.

2. Librerías:

Además, será necesario cargar ciertas librerías que nos permitirán realizar y visualizar el Análisis de Componentes Principales (PCA). Estas son:

  • FactoMineR: proporciona funciones para llevar a cabo el PCA y otros métodos de análisis multivariante. Utilizaremos esta librería para ejecutar el PCA con la función PCA().

  • factoextra: facilita la visualización de los resultados del PCA mediante gráficos intuitivos. Usaremos esta librería para representar la varianza explicada y los individuos/componentes.

  • ggplot2: nos permitirá personalizar los gráficos generados (por ejemplo, añadiendo líneas, colores y etiquetas) ya que factoextra se basa en ggplot2.

  • knitr: nos permitirá utilizar la función kable().

3. Selección de variables:

Ahora que ya contamos con las bases de datos limpias y las librerías necesarias, el siguiente paso consiste en seleccionar las variables numéricas que se utilizarán en el PCA. Para ello, emplearemos los siguientes códigos:

  1. Para 2018
# Seleccionar solo variables numéricas para PCA
numerical_vars_2018 <- Valencia_2018[, c(
  "PRICE", "UNITPRICE", "CONSTRUCTEDAREA", "ROOMNUMBER", "BATHNUMBER",
  "CADCONSTRUCTIONYEAR","CADMAXBUILDINGFLOOR", "CADDWELLINGCOUNT",
  "CADASTRALQUALITYID", "DISTANCE_TO_CITY_CENTER", "DISTANCE_TO_METRO", 
  "DISTANCE_TO_BLASCO", "RHabitacion_Banyo"
)]

numerical_vars_2018$geometry <- NULL
numerical_vars_2018[] <- lapply(numerical_vars_2018, as.numeric)
  1. Para 2025
# Seleccionar solo variables numéricas para PCA
numerical_vars_2025 <- Valencia_2025[, c(
  "price", "priceByArea", "size", "rooms", "bathrooms",
  "numPhotos", "floor", "distance", "distancia_min_estacion_m"
)]

numerical_vars_2025[] <- lapply(numerical_vars_2025, as.numeric)

Realización del PCA

Ahora que ya lo tenemos todo listo, vamos a empezar escalando las variables que vamos a utilizar. Esto se hace para que cada variable tenga media 0 y desviación estándar 1. De esta forma, variables con unidades grandes como el precio no dominan tanto el análisis. Después, realizaremos un PCA con 10 componentes principales, seleccionando el precio como variable cuantitativa suplementaria. Una vez obtenido el PCA, representaremos qué porcentaje de varianza explica cada componente mediante un scree plot para ver cuantas componentes principales necesitaremos en el análisis:

  1. Para 2018
# Escalar los datos
scaled_data_2018 <- scale(numerical_vars_2018)

# Ejecutar PCA
res.pca_2018 = PCA(scaled_data_2018, scale.unit = TRUE, graph = FALSE, ncp = 10, quanti.sup = "PRICE")
eig.val_2018 <- get_eigenvalue(res.pca_2018)
VPmedio_2018 = 100 * (1/nrow(eig.val_2018))
fviz_eig(res.pca_2018, addlabels = TRUE) +
    geom_hline(yintercept=VPmedio_2018, linetype=2, color="red")

kable(eig.val_2018[1:10,])
eigenvalue variance.percent cumulative.variance.percent
Dim.1 3.4023558 28.352965 28.35296
Dim.2 1.9880306 16.566922 44.91989
Dim.3 1.5976210 13.313508 58.23340
Dim.4 1.1643176 9.702647 67.93604
Dim.5 1.0187814 8.489845 76.42589
Dim.6 0.6767069 5.639225 82.06511
Dim.7 0.5811865 4.843221 86.90833
Dim.8 0.4680395 3.900329 90.80866
Dim.9 0.3926027 3.271689 94.08035
Dim.10 0.3289087 2.740906 96.82126

Seleccionamos 5 componentes principales, que explican un 76,4% del total de variabilidad de los datos, porque cumplen tanto con el criterio del codo como con el de superar la “varianza media” explicada por PC:

res.pca_2018 = PCA(scaled_data_2018, scale.unit = TRUE, graph = FALSE, ncp = 5, quanti.sup = "PRICE")
  1. Para 2025
# Escalar los datos
scaled_data_2025 <- scale(numerical_vars_2025)

# Ejecutar PCA
res.pca_2025 = PCA(scaled_data_2025, scale.unit = TRUE, graph = FALSE, ncp = 10, quanti.sup = "price")
eig.val_2025 <- get_eigenvalue(res.pca_2025)
VPmedio_2025 = 100 * (1/nrow(eig.val_2025))
fviz_eig(res.pca_2025, addlabels = TRUE) +
    geom_hline(yintercept=VPmedio_2025, linetype=2, color="red")

kable(eig.val_2025[1:8,])
eigenvalue variance.percent cumulative.variance.percent
Dim.1 2.7963332 34.954166 34.95417
Dim.2 1.2671371 15.839214 50.79338
Dim.3 1.2041602 15.052003 65.84538
Dim.4 0.8607514 10.759393 76.60477
Dim.5 0.7023619 8.779524 85.38430
Dim.6 0.5183204 6.479005 91.86330
Dim.7 0.3650732 4.563415 96.42672
Dim.8 0.2858625 3.573282 100.00000

Seleccionamos 3 componentes principales, que explican un 65,8% del total de variabilidad de los datos, porque cumplen tanto con el criterio del codo como con el de superar la “varianza media” explicada por PC:

res.pca_2025 = PCA(scaled_data_2025, scale.unit = TRUE, graph = FALSE, ncp = 3, quanti.sup = "price")

Visualización PCA y resultados

Visualizamos ahora las variables mediante fviz_pca_var() con el fin de ver qué variables están más correlacionadas y cuales contribuyen más en cada componente:

  1. Para 2018
fviz_pca_var(res.pca_2018, axes = c(1,2), repel = TRUE, col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

fviz_pca_var(res.pca_2018, axes = c(3,4), repel = TRUE, col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

Entre las variables con mayor contribución a las componentes se encuentran:

Por otro lado, variables como DISTANCE_TO_BLASCO o RHabitacion_Banyo presentan una contribución menor y están situadas más cerca del centro del gráfico, lo que indica que están menos representadas en estas dos dimensiones.

Finalmente, observamos como la variable PRICE está bastante correlacionada con UNITPRICE, CONSTRUCTEDYEARy BATHNUMBER.

  1. Para 2025
fviz_pca_var(res.pca_2025, axes = c(1,2), repel = TRUE, col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

fviz_pca_var(res.pca_2025, axes = c(1,3), repel = TRUE, col.var = "contrib",
             gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"))

Conclusión

En ambos análisis, las variables relacionadas con las características físicas de la vivienda, como el número de habitaciones (ROOMNUMBER / rooms), superficie (CONSTRUCTEDAREA / size) y número de baños (BATHNUMBER / bathrooms), aparecen consistentemente como principales contribuyentes a las primeras componentes. Esto indica que estos factores han sido estructuralmente determinantes en la configuración del valor de las viviendas en ambos periodos.

Además, la variable PRICE, aunque se ha tratado como suplementaria, mantiene una alineación clara con las variables estructurales de la vivienda en ambos años. Esto refuerza la idea de que el precio está más influenciado por aspectos como tamaño, número de estancias o baños, que por otros factores.

Variables relacionadas con la ubicación o accesibilidad (como DISTANCE_TO_CITY_CENTER, DISTANCE_TO_METRO, distance, distancia_min_estacion_m) muestran una dirección opuesta a la de las variables estructurales, reflejando su relación inversa con el precio y tamaño: cuanto mayor la distancia, menor es el valor o calidad de la vivienda.

Por último, En el PCA de 2025 aparecen nuevas variables como priceByArea o numPhotos, que no estaban presentes en 2018. Algunas, como priceByArea, muestran un comportamiento particular y contribuyen significativamente a componentes diferentes, lo que podría estar relacionado con cambios en cómo se percibe el valor por metro cuadrado o con nuevas formas de marketing digital (por ejemplo, la cantidad de fotos en un anuncio).