title: “Taller Analisis” author: “Holman Marquez” date: “2025-05-18” output: html_document

1. Preguntas de Analisis

A. Analisis de Limpieza

getwd() setwd(“C:\Users\Equipo Familiar\OneDrive\Desktop\Analisis”)

1A. Importación y Estructura

datos <- read.csv(“C:\Users\Equipo Familiar\Downloads\Inmuebles_Disponibles_Para_La_Venta_20250518.csv”)

dim(datos) options(scipen=999) ##R// El Data Frame poseé 448 filas y 12 columnas

str(datos)

##R// El Data Frame tiene datos de tipo Categorico, de Texto y Númerico ($, chr, num, int)

2A. Valores Nulos y Duplicados

sum(is.na(datos))

Podemos ver que el data frame contiene espacios vacios y 0’s,debemos correguri eso

datos[datos==“”] <- NA

datos[datos==“0”] <- NA

Total_NA<-sum(is.na(datos))

Total_NA / (nrow(datos)ncol(datos)) 100

any(duplicated(datos))

> Hay un total de 1623 datos Nulos

> Representan un 30% del total de datos

> No existen duplicados

#3A. Depuración de Datos library(tidyverse) library(ggplot2) library(dplyr) library(sandwich) library(survival) attach(datos)

summary(datos)

Precio <- as.numeric(datos$Precio)

Q1 <- quantile(datos\(Precio, 0.25, na.rm = TRUE) Q3 <- quantile(datos\)Precio, 0.75, na.rm = TRUE)

IQR_Valor = Q3 - Q1

LimF <- Q1 - 1.5 * IQR_Valor LimS <- Q3 + 1.5 * IQR_Valor

datos_filtrados <- datos %>% filter(!is.na(Precio), !is.na(Departamento), Precio >= LimF, Precio <= LimS) %>% select(Precio, Departamento)

ggplot(datos_filtrados, aes(x = fct_reorder(Departamento, Precio, .fun = median), y = Precio, fill = Departamento))+ geom_boxplot(outlier.colour = “red”, outlier.shape = 16 )+ labs( title = “Distribución de Precios de Inmuebles Por Departamento”, x = “Departamento”, y = “Precio” )+ theme_minimal()+ theme(axis.text.x = element_text(angle = 45, hjust = 1))+ theme(legend.position = “none”)

>No se puden apreciar errores ortograficos o gramaticos que perjudiquen el analisis

>Efectivamente hay valores atipicos como se puede presentar en la grafica

B. Analisis Descriptivo

B4. Distribuciones

library(ggplot2) library(AER) library(e1071)

precios_filtrados <- datos %>% filter(!is.na(Precio), Precio >= LimF, Precio <= LimS) %>% pull(Precio)

Distribucion <- skewness(datos$Precio, na.rm = TRUE)

ggplot(datos_filtrados, aes(x =precios_filtrados))+ geom_histogram(bins = 30, fill = “purple”, color =“black”)+ labs( title = “Distribución de Precios de Inmuebles (COP)”, x = “Precio”, y = “Frecuencia” )+ annotate(“text”, x = Inf, y = Inf, label = paste0(“Skewness:”, round(Distribucion, 2)), hjust = 1.1, vjust = 2, size = 5, color = “#301”)

>Hay claros sesgos de infomación dada la gran diferencia de precios y sus respectivas frecuencias

>Podemos hacer otro histograma basandonos en la media para ver una distribución más clara

mediana <- median(datos$Precio, na.rm =TRUE)

Datos_Dstr <- datos %>% filter(!is.na(Precio), Precio > 0, Precio <= 1.5*mediana)

Distribucion1 <- skewness(Datos_Dstr$Precio, na.rm = TRUE)

ggplot(Datos_Dstr, aes(x =Datos_Dstr$Precio))+ geom_histogram(bins = 30, fill = “purple”, color =“black”)+ labs( title = “Distribución de Precios de Inmuebles (COP)”, x = “Precio”, y = “Frecuencia” )+ annotate(“text”, x = Inf, y = Inf, label = paste0(“Skewness:”, round(Distribucion1, 2)), hjust = 1.1, vjust = 2, size = 5, color = “#301”)

> Este es un nuevo grafico basandonos en la mediana de los precios, por lo que tenemos una mejor distribución

#Dado que los precios son excesivamente altos esto rezagaba a los demás por lo que esta distrubución es más equitativa

Tipo de Inmueble más Común

datos_grafico <- datos %>% filter(!is.na(Tipo.de.Inmueble), !is.na(Precio)) %>% group_by(Tipo.de.Inmueble)%>% summarise( conteo = n(), precio_medio = mean(Precio, na.rm =TRUE) ) %>% arrange(desc(conteo))%>% slice_head(n=10)

ggplot(datos_grafico, aes(x = reorder(Tipo.de.Inmueble, -conteo)))+ geom_bar(aes(y=conteo), stat = “identity”, fill = “skyblue”, alpha = 0.7)+ geom_line(aes(y= precio_medio / max(precio_medio)max(conteo)), group = 1, color = “#300”, size = 1)+ geom_point(aes(y=precio_medio/max(precio_medio)max(conteo)), color = “#300”, size = 3)+ scale_y_continuous( name = “Cantidad de Inmuebles”, sec.axis = sec_axis(~.*max(datos_grafico\(precio_medio)/max(datos_grafico\)conteo), name = “Precio Promedio (COP)”))+ labs(title = “Tipos de Inmueble Más Comunes y su Precio Promedio”, x = “Tipo de Inmueble”)+ theme_minimal()+ theme(axis.text.x = element_text(angle = 45, hjust = 1))

B5. Estadisticas Clave

Estadisticas_Clave <- datos %>% summarise( Medina = median(Precio, na.rm = TRUE), Mediana = mean(Precio,na.rm = TRUE), SD = sd(Precio, na.rm = TRUE), Q1 = quantile(datos\(Precio, 0.25, na.rm = TRUE), Q2 = quantile(datos\)Precio, 0.50, na.rm = TRUE), Q3 = quantile(datos$Precio, 0.75, na.rm = TRUE) )

print(Estadisticas_Clave)

Tabla de Frecuencia

Tabla_F <- datos %>% group_by(Tipo.de.Inmueble)%>% summarise( Frecuencia = n(), Frecuencia_Relativa = n() / nrow(datos))%>% arrange(desc(Frecuencia))

print(Tabla_F)

Alternativa con paquete “psych”

library(psych)

describe(datos)

B6 Agrupaciones

Precio Promedio Por Estrato

options(scipen = 999)

Promedio_P_Estrato <- datos %>% filter(!is.na(Estrato), !is.na(Precio)) %>% group_by(Estrato)%>% summarise( Inmuebles = n(), precio_medio = mean(Precio, na.rm =TRUE), precio_mediana = median(Precio, na.rm = TRUE), ) %>% arrange(desc(Estrato))

view(Promedio_P_Estrato)

Promedio_P_Ciudad <- datos %>% filter(!is.na(Ciudad), !is.na(Precio)) %>% group_by(Ciudad)%>% summarise( Inmuebles = n(), precio_medio = mean(Precio, na.rm =TRUE), precio_mediana = median(Precio, na.rm = TRUE), ) %>% arrange(desc(Ciudad))

view(Promedio_P_Ciudad)

C. Agrupaciones

C7. Mapas y Geolocalización

install.packages(“sf”) install.packages(“stringr”) install.packages(“tmap”) install.packages(“leaflet”) install.packages(“ggmap”) install.packages(“tidygeocoder”) install.packages(“viridis”) library(dplyr) library(sf) library(tmap) library(leaflet) library(stringr) library(ggmap) library(tidygeocoder) library(viridis)

library(sf) library(dplyr)

base_mapa <- st_read(“C:\Users\Equipo Familiar\OneDrive\Desktop\Analisis”) %>% select(DPTO_CNMBR, geometry) %>% rename(Departamento = DPTO_CNMBR)

Cargar datos del archivo CSV

inmuebles_P <- read.csv(“C:/Users/Equipo Familiar/Downloads/Inmuebles_Disponibles_Para_La_Venta_20250518.csv”)

Verificar que se cargó

head(inmuebles_P) deptos_csv <- unique(inmuebles_P\(Departamento) deptos_shapefile <- unique(base_mapa\)Departamento)

st_geometry(base_mapa) names(base_mapa)

> Visualización basica del mapa

ggplot(base_mapa) + geom_sf(fill = “lightblue”, color = “white”) + theme_void()+ labs(title = “Mapa de Colombia”)

Seguidamente haremos una nueva base de datos en la cual usaremos solo los datos que nos conviene

inmuebles_P <- datos %>% group_by(Departamento) %>% summarise( Precio_Bill = sum(Precio, na.rm = TRUE) / 1e12
) %>% arrange(desc(Precio_Bill))

print(datos_rsm, n = Inf)

Ahora haremos la Base de datos final para el mapa

Mapa_Final <- base_mapa %>% left_join(inmuebles_P)%>% mutate( Precio_Bill = ifelse(is.na(Precio_Bill), 0, Precio_Bill) )

Mapa_Final <- Mapa_Final %>% mutate( Rango_Precio = case_when( Precio_Bill == 0 ~ “Sin datos (0 B)”, Precio_Bill > 0 & Precio_Bill <= 100 ~ “Bajo (0-100 B)”, Precio_Bill > 100 & Precio_Bill <= 500 ~ “Medio (100-500 B)”, Precio_Bill > 500 ~ “Alto (>500 B)”, TRUE ~ NA_character_ ), Rango_Precio = factor( Rango_Precio, levels = c(“Sin datos (0 B)”, “Bajo (0-100 B)”, “Medio (100-500 B)”, “Alto (>500 B)”) ) )

El mapa más elaborado, sin leaflet

ggplot(Mapa_Final) + geom_sf( aes(fill = Rango_Precio), color = “gray”, size = 0.3, alpha = 0.9 # Transparencia para mejor legibilidad ) + scale_fill_manual( values = c( “Sin datos (0 B)” = “#f0f0f0”, # Gris claro “Bajo (0-100 B)” = “#bdd7e7”, # Azul claro “Medio (100-500 B)” = “#3182bd”, # Azul medio “Alto (>500 B)” = “#08519c” # Azul oscuro ), na.value = “gray90”, guide = guide_legend( title = “Rango de precios (billones)”, title.position = “top”, nrow = 1 ) ) + theme_void() + labs( title = “Precios de inmuebles por departamento”, subtitle = “Distribución en rangos”, caption = paste(“Max:”, max(Mapa_Final$Precio_Bill, na.rm = TRUE), “billones”) ) + theme( plot.title = element_text(hjust = 0.5, face = “bold”, size = 16), legend.position = “bottom”, legend.text = element_text(size = 10))

A contuniación el procedimiento para hacer el mapa en leaflet

Mapa_Final <- st_transform(Mapa_Final, crs = 4326)

paleta_roja <- colorNumeric( palette = c(“#FFCCCC”, “#FF6666”, “#FF0000”, “#990000”, “#330000”, “#220000”, “#110000”, “#080000”), domain = Mapa_Final$Precio_Bill )

etiquetas <- sprintf( “%s
Precio: %s billones”, Mapa_Final\(Departamento, round(Mapa_Final\)Precio_Bill, 1))%>% lapply(htmltools::HTML)

leaflet(Mapa_Final)%>% addProviderTiles(providers$CartoDB.Positron)%>% addPolygons( fillColor = ~paleta_roja(Precio_Bill), fillOpacity = 0.8, color = “white”, weight = 1, smoothFactor = 0.5, highlightOptions =highlightOptions( weight = 3, color = “#FF0000”, fillOpacity = 1, bringToFront = TRUE, sendToBack = TRUE ), label = etiquetas, labelOptions = labelOptions( style = list(“font-weight”=“normal”, padding = “3px 8px”), textsize = “15px”, direction = “auto” ) )%>% addLegend( pal = paleta_roja, values = ~Precio_Bill, title = “Precio (Billones COP)”, opacity = 0.9, labFormat = labelFormat(suffix = “B”) )

C8. Patrones GeoGraficos

library(ggplot2) library(dplyr)

datos2 <- datos %>% filter(!is.na(Precio), !is.na(Departamento))%>% mutate( Precio_Bill = Precio/1e12 )

ggplot(datos2, aes( x = reorder(Departamento, Precio_Bill, FUN = median), y = Precio_Bill, fill = Departamento ))+ geom_boxplot( outlier.shape = 1, width = 0.6, alpha = 0.8 )+ geom_jitter( width = 0.15, size = 1.5, alpha = 0.3, color = “#333333” )+ labs( title = “Distribución de Precios de Inmuebles Por Departamento”, subtitle = “Valores en Billones de COP”, x= ““, y=”Precio (Billones COP)” )+ theme_minimal(base_size = 12)+ theme( axis.text.x = element_text(angle = 45, hjust = 1, face = “bold”), legend.position = “none”, plot.title = element_text(size = 16, hjust = 0.5, face = “bold”), panel.grid.major.x = element_blank() )+ scale_fill_viridis_d(option =“plasma”, begin = 0.2, end = 0.8)

Ahora como varia el Precio por m^2 en barrios de alto estrato

Filtrar y calcular precio/m² para estratos altos (4-6)

datos_filtrados <- datos %>% filter( # Condición: Area.Construida válida O Area.Terreno válida (!is.na(Area.Construida) & Area.Construida > 0) | (!is.na(Area.Terreno) & Area.Terreno > 0) ) %>% mutate( Area_Util = ifelse(!is.na(Area.Construida) & Area.Construida > 0, Area.Construida, Area.Terreno), precio_m2 = Precio / Area_Util, Barrio_Depto1 = paste0(Barrio, ” (“, Departamento,”)“) )

analisis_barrios <- datos_filtrados %>% filter(!is.na(Barrio)) %>% # Excluir barrios desconocidos group_by(Barrio_Depto1, Estrato) %>% summarise( n_inmuebles = n(), precio_mediano = median(precio_m2, na.rm = TRUE), precio_promedio = mean(precio_m2, na.rm = TRUE), .groups = ‘drop’ )

ggplot(analisis_barrios, aes(x = reorder(Barrio_Depto1, precio_mediano), y = precio_mediano/1e6,
fill = Estrato)) + geom_col(position = “dodge”) + coord_flip() + labs(title = “Precio mediano por m² por Barrio y Estrato”, y = “Precio por m² (millones COP)”, x = ““, fill =”Estrato”) + theme_minimal() + theme(axis.text.y = element_text(size = 8), legend.position = “bottom”) + scale_fill_brewer(palette = “Reds”)

D9. Relación entre variables

library(dplyr)

Preparación robusta de datos

datos_correlacion <- datos %>% mutate( across(c(Area.Construida, Area.Terreno), ~ifelse(. <= 0, NA, .)) ) %>% select(Precio, Area.Construida, Area.Terreno) %>% filter(rowSums(!is.na(.)) > 0) # Elimina filas completamente vacías

Verificación final

if (nrow(datos_correlacion) > 10) { # Mínimo 10 observaciones tryCatch({ matriz_cor <- cor(datos_correlacion, use = “pairwise.complete.obs”)

if (any(is.na(matriz_cor))) {
  message("Advertencia: Algunas correlaciones no pudieron calcularse")
  print(matriz_cor)
} else {
  corrplot::corrplot(matriz_cor, method = "color")
}

}, error = function(e) { message(“Error:”, e$message) }) }

Conclusiones

#Sí, el área construida influye más en el precio que el área de terreno, con una correlación significativamente mayor (0.92 vs 0.68). Esto sugiere que:

#Los compradores valoran más la edificación que el terreno vacío.

#El precio depende más de metros cuadrados habitables que del tamaño total del lote.

D10. Analisis Multivariable

library(dplyr) library(ggplot2)

1. Preparación de datos

datos_plot <- datos %>% filter( !is.na(Precio), !is.na(Estrato), !is.na(Tipo.de.Inmueble), Precio > 0 ) %>% mutate( # Estandarizar nombres de tipos de inmueble Tipo = case_when( grepl(“APART|APTO|APARTAMENTO”, Tipo.de.Inmueble, ignore.case = TRUE) ~ “Apartamento”, grepl(“CASA”, Tipo.de.Inmueble, ignore.case = TRUE) ~ “Casa”, grepl(“LOTE|TERRENO”, Tipo.de.Inmueble, ignore.case = TRUE) ~ “Terreno”, TRUE ~ “Otros” ) )

2. Gráfico de dispersión con facetas

ggplot(datos_plot, aes(x = Estrato, y = Precio/1e6, color = Tipo)) + geom_point(alpha = 0.6, position = position_jitter(width = 0.2)) + facet_wrap(~ Tipo, ncol = 2) + scale_y_log10(labels = scales::comma) + labs(title = “Relación Precio-Estrato por Tipo de Inmueble”, x = “Estrato”, y = “Precio (millones COP)”) + theme_minimal()+ theme( axis.text.x = element_text( angle = 45, hjust = 1, size = 10, margin = margin(t = 5) ))

```