En un mercado inmobiliario en constante evolución, es fundamental para las empresas del sector entender a profundidad las dinámicas que influyen en la oferta y la demanda de propiedades. Este informe se enfoca en analizar un conjunto de datos extensos proporcionados por una inmobiliaria líder en la ciudad, con el objetivo de identificar patrones y relaciones clave que afectan la variación de precios y otros factores relevantes en el mercado de viviendas urbanas. A través de técnicas avanzadas de análisis de datos, se busca proporcionar insights estratégicos que puedan guiar la toma de decisiones y optimizar las operaciones de la empresa en un entorno competitivo.
Realizar un análisis integral y multidimensional del mercado inmobiliario urbano utilizando un conjunto de datos que contiene información detallada sobre diversas propiedades residenciales en Cali.
Identificar las características clave que influyen en la variación del precio de las viviendas mediante el Análisis de Componentes Principales (PCA).
Agrupar las propiedades en segmentos homogéneos utilizando el Análisis de Conglomerados, para entender mejor las dinámicas de las ofertas en diferentes partes de la ciudad y en distintos estratos socioeconómicos.
Explorar las relaciones entre variables categóricas como el tipo de vivienda, zona y barrio a través del Análisis de Correspondencia, para identificar patrones de comportamiento en la oferta del mercado inmobiliario.
Presentar los resultados de manera clara y visual a través de gráficos y tablas que faciliten la interpretación de los hallazgos.
Discutir los resultados obtenidos y brindar recomendaciones que ayuden a la inmobiliaria a optimizar sus estrategias de negocio y maximizar los beneficios en un mercado en constante cambio.
El análisis comenzó con una limpieza exhaustiva del conjunto de datos, que incluyó la eliminación de valores duplicados, el tratamiento de valores faltantes y la estandarización de variables. Posteriormente, se llevó a cabo un análisis exploratorio de los datos, donde se validaron outliers, se generaron diagramas de barras para visualizar la distribución de variables categóricas, y se utilizó un mapa geoespacial para identificar la ubicación de las propiedades dentro de la ciudad.
Luego, se aplicó el Análisis de Componentes Principales (PCA) para reducir la dimensionalidad del conjunto de datos y visualizar la estructura de las variables en componentes principales, lo que permitió identificar las características clave que influyen en la variación de precios. Con estas componentes, se realizó un Análisis de Conglomerados para agrupar las propiedades en segmentos homogéneos, y un Análisis de Correspondencia para explorar las relaciones entre variables categóricas. Los resultados se presentaron mediante gráficos y tablas, y se incluyó una discusión detallada con recomendaciones estratégicas para la inmobiliaria.
Se descarga y valida el tipo de datos del dataset vivienda
## id zona piso estrato preciom areaconst
## "numeric" "character" "character" "numeric" "numeric" "numeric"
## parqueaderos banios habitaciones tipo barrio longitud
## "numeric" "numeric" "numeric" "character" "character" "numeric"
## latitud
## "numeric"
El dataset contiene las siguientes columnas con sus respectivos tipos de datos: id es de tipo numeric, zona y piso son de tipo character, estrato es de tipo numeric (pero debe tratarse como character porque representa diferentes niveles socioeconómicos, que no son cuantitativos), preciom y areaconst son de tipo numeric, parqueaderos, banios, y habitaciones son de tipo numeric (pero deben tratarse como character porque representan la cantidad de características presentes, como el número de parqueaderos, baños o habitaciones, las cuales son categorías discretas más que valores continuos), tipo y barrio son de tipo character, y finalmente longitud y latitud son de tipo numeric.
Transformamos las variables de clasificación a character
## id zona piso estrato preciom areaconst
## "numeric" "character" "character" "character" "numeric" "numeric"
## parqueaderos banios habitaciones tipo barrio longitud
## "character" "character" "character" "character" "character" "numeric"
## latitud
## "numeric"
Posteriormente, transformamos los datos de tipo carácter a mayúsculas, lo cual nos permitirá unificar y estandarizar mejor la información
char_columns <- sapply(vivienda, is.character)
vivienda[char_columns] <- lapply(vivienda[char_columns], toupper)
Identificamos el número de valores nulos presentes en cada columna.
## id zona piso estrato preciom areaconst
## 3 3 2638 3 2 3
## parqueaderos banios habitaciones tipo barrio longitud
## 1605 3 3 3 3 3
## latitud
## 3
El resultado generado evidencia la presencia de muchos valores nulos, lo que puede afectar el análisis de los datos, ya que pueden distorsionar los resultados o limitar la cantidad de información utilizable. En este caso, se observa que algunas columnas tienen una cantidad significativa de valores nulos, como las columnas de piso y parqueaderos, que tiene 2638 y 1602 valores nulos respectivamente, lo que podría indicar que esta información no está disponible o no se registró para muchas observaciones. Además de esto se identifica que todas las columnas se tienen un total de 3 datos nullos por lo que se proceden a borrar los datos que no tienen id para limpiar los datos que no representan nada para el dataset.
## id zona piso estrato preciom areaconst
## 0 0 2635 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 1602 0 0 0 0 0
## latitud
## 0
Luego de eliminar los tres registros que no aportaban información relevante al conjunto de datos, se procedió a calcular el porcentaje de datos nulos en las columnas piso y parqueaderos. Esto se realizó con el objetivo de evaluar si es viable eliminar los registros incompletos, o bien, considerar alternativas como reemplazar los valores faltantes por 0 o por la moda, dependiendo de lo que resulte más adecuado para mantener la integridad y representatividad del análisis.
## id zona piso estrato preciom areaconst
## 0.00000 0.00000 31.67448 0.00000 0.00000 0.00000
## parqueaderos banios habitaciones tipo barrio longitud
## 19.25712 0.00000 0.00000 0.00000 0.00000 0.00000
## latitud
## 0.00000
Después de analizar los datos, se identificó que la columna piso presenta un 31.67% de valores nulos, lo que indica una proporción significativa de registros sin información en esta variable. De manera similar, la columna parqueaderos tiene un 19.26% de datos faltantes, lo que también es relevante. Las demás columnas no presentan valores nulos, manteniéndose con un 0% de datos faltantes.
En este contexto, la imputación de los valores nulos en las columnas piso y parqueaderos con el valor 0 es una estrategia justificada por varias razones clave. A diferencia de la eliminación de registros con datos faltantes, que podría reducir significativamente el tamaño de la muestra y comprometer la representatividad de los datos, la imputación con 0 permite conservar todas las observaciones. Esto garantiza que la muestra se mantenga completa y representativa.
Además, imputar con 0 es preferible a utilizar la moda en situaciones donde se busca evitar la introducción de sesgos, especialmente cuando la distribución de los datos no es uniforme. El valor 0 tiene un significado claro y lógico en este contexto, indicando la ausencia de un piso específico o la falta de parqueaderos.
Se modifican los datos por 0
## id zona piso estrato preciom areaconst
## 0 0 0 0 0 0
## parqueaderos banios habitaciones tipo barrio longitud
## 0 0 0 0 0 0
## latitud
## 0
Se realizó una validación del total de datos duplicados en el conjunto de datos, excluyendo la columna id, y se determinó que aproximadamente el 0.69% de los registros estaban duplicados. Para garantizar la consistencia y la calidad en la preparación de los modelos que se presentarán más adelante, se ha tomado la decisión de eliminar estos registros duplicados. Esta acción busca evitar posibles inconsistencias en los resultados del análisis y asegurar que el modelo se base en datos únicos y representativos. Por lo que quedamos con un total de 8.262 registros.
## [1] 57
## [1] 0.6851785
En el análisis de las variables precio de las propiedades y área construida, se identificaron valores atípicos significativos a través de los gráficos boxplot. Estos valores atípicos se presentan como propiedades con precios y áreas construidas que se sitúan considerablemente por encima del rango intercuartílico (IQR), indicando la presencia de inmuebles de características excepcionales dentro del conjunto de datos.
Dado que estos valores atípicos reflejan la realidad del mercado inmobiliario y no son errores de medición ni datos incorrectos, se ha decidido mantenerlos en el análisis. Estos outliers son representativos de segmentos específicos del mercado, como las propiedades de alta gama, y su eliminación podría resultar en una pérdida significativa de información y una distorsión del análisis.
Al conservar estos outliers, se garantiza que el análisis sea integral y representativo, permitiendo una evaluación más precisa de la variabilidad en los precios y tamaños de las propiedades en el mercado inmobiliario.
El análisis univariado de las variables proporciona una visión inicial de la distribución de cada característica relevante del mercado inmobiliario.
La mayoría de las propiedades cuentan con 2 o 3 baños, lo cual es consistente con las configuraciones típicas de viviendas familiares. Es notable que las propiedades con más de 4 baños son relativamente raras, indicando que estas suelen pertenecer a un segmento de lujo.
La distribución del estrato muestra que los estratos 4, 5 y 6 son los más comunes, lo cual refleja un mercado orientado principalmente hacia clases medias y altas. Este patrón es típico en áreas urbanas con desarrollo inmobiliario orientado a sectores socioeconómicos con mayor poder adquisitivo.
El análisis de las habitaciones revela que la mayoría de las propiedades tienen entre 2 y 4 habitaciones. Propiedades con más de 5 habitaciones son menos frecuentes, sugiriendo que las viviendas de gran tamaño son menos comunes en el mercado.
Un gran número de propiedades tienen solo un parqueadero, mientras que la cantidad de propiedades con 2 o más parqueaderos disminuye significativamente. Esto podría indicar que la mayoría de las propiedades están diseñadas para familias con uno o dos vehículos.
La mayoría de las propiedades tienen solo uno o dos pisos, lo que es típico en viviendas unifamiliares y algunos apartamentos. Propiedades con más pisos son menos comunes, lo que puede reflejar un menor número de edificios residenciales altos en el área de estudio.
Hay una predominancia de apartamentos en comparación con casas.
La mayor concentración de propiedades se encuentra en la Zona Sur.
El mapa geoespacial de las zonas más vendidas resalta las áreas con mayor actividad de ventas, con una evidente concentración en la Zona Sur. Esto sugiere que esta área es actualmente la más dinámica en términos de transacciones inmobiliarias, representando una oportunidad clave para la inversión y el desarrollo de nuevas propiedades.
En esta sección podrás encontrar todo el código realizado para presentar el informe
install.packages("knitr")
library(paqueteMODELOS)
# Descargar la vivienda
data(vivienda)
######################################################### Limpieza de datos
# Validar los tipos de datos
sapply(vivienda, class)
# Transformar a character
vivienda$estrato <- as.character(vivienda$estrato)
vivienda$parqueaderos <- as.character(vivienda$parqueaderos)
vivienda$banios <- as.character(vivienda$banios)
vivienda$habitaciones <- as.character(vivienda$habitaciones)
vivienda$tipo <- as.character(vivienda$tipo)
# Validar los tipos de datos
sapply(vivienda, class)
#convertir a mayusculas los valores
char_columns <- sapply(vivienda, is.character)
vivienda[char_columns] <- lapply(vivienda[char_columns], toupper)
## Validación de datos null
colSums(is.na(vivienda))
#Eliminacioin tres registor null
vivienda <- vivienda[!is.na(vivienda$id),]
##Volvemos a validar que registros continuan nullos
colSums(is.na(vivienda)) ## identificamos que al eliminar los valores nullos de id unicamente quedamos con valores nullos en parquedaros y pisos que a pesar de ser variables numericas en este caso nos funcionaban como variables categoricas, ya que, nos permitia entender que caracteristicas buscaban los posibles compradores ahora es importante saber cual es el procentaje de valores nullos para tomar una desicion
# Calcular el porcentaje de valores nullos por columna
percentage_na_per_column <- colSums(is.na(vivienda)) / nrow(vivienda) * 100
# Mostrar el porcentaje de valores nulos por columna
percentage_na_per_column
## Se identifica que existe un total de 19.26% de datos nulos para parqueadero mientras que para piso tenemos un 31.67 es importante mencionar que en este caso no podemos realizar un ponderado con la media la mediana o la moda
## Se modifican los datos por 0
vivienda$piso[is.na(vivienda$piso)] <- 0
vivienda$parqueaderos[is.na(vivienda$parqueaderos)] <- 0
colSums(is.na(vivienda))
# Eliminar filas duplicadas considerando todas las columnas excepto 'id'
total_filas <- nrow(vivienda)
duplicados <- sum(duplicated(vivienda[, -which(names(vivienda) == "id")]))
porcentaje_duplicados <- (duplicados / total_filas) * 100
duplicados
porcentaje_duplicados
vivienda_sin_duplicados <- vivienda[!duplicated(vivienda[, -which(names(vivienda) == "id")]), ]
# Mostrar el DataFrame sin duplicados
vivienda_sin_duplicados
setwd("C:/Users/anaso/OneDrive/Desktop")
######################################## Analisis exploratorio de los Datos
## precio y area constuida
boxplot(vivienda_sin_duplicados$preciom, main="Boxplot de Precios", ylab="Precio")
boxplot(vivienda_sin_duplicados$areaconst, main="Boxplot de Área Construida", ylab="Área Construida")
install.packages("ggplot2")
install.packages("dplyr")
library(ggplot2)
library(dplyr)
# Banios
png(filename = "C:/ruta_a_donde_quieres_guardar/plot.png", width = 480, height = 480)
# Aquí tu código para generar la gráfica
dev.off()
ggplot(vivienda_sin_duplicados, aes(x=banios, fill=factor(banios))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución de Baños", x="Número de Baños", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Estrato
ggplot(vivienda_sin_duplicados, aes(x=estrato, fill=factor(estrato))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución de Estrato", x="Estrato", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Habitaciones
ggplot(vivienda_sin_duplicados, aes(x=habitaciones, fill=factor(habitaciones))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución de Habitaciones", x="Número de Habitaciones", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Parqueaderos
ggplot(vivienda_sin_duplicados, aes(x=parqueaderos, fill=factor(parqueaderos))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución de Parqueaderos", x="Número de Parqueaderos", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Piso
ggplot(vivienda_sin_duplicados, aes(x=piso, fill=factor(piso))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución de Pisos", x="Número de Pisos", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Tipo
ggplot(vivienda_sin_duplicados, aes(x=tipo, fill=factor(tipo))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución de Tipo de Vivienda", x="Tipo de Vivienda", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Zona
ggplot(vivienda_sin_duplicados, aes(x=zona, fill=factor(zona))) +
geom_bar() +
theme_minimal() +
labs(title="Distribución por Zona", x="Zona", y="Frecuencia") +
theme(axis.text.x = element_text(angle=45, hjust=1)) +
scale_fill_brewer(palette="Set3") # Usa una paleta de colores diferente
# Creación del mapa interactivo con leaflet
library(leaflet)
mapa <- leaflet(vivienda_sin_duplicados, options = leafletOptions(minZoom = 11, maxZoom = 40)) %>%
addTiles() %>%
addCircleMarkers(
~longitud, ~latitud,
color = "#034A94",
clusterOptions = markerClusterOptions(spiderfyDistanceMultiplier = 1.5)
)
mapa