1. Cargar base de datos

¿Cómo se carga la base de datos desde un archivo CSV en R?

# Respuesta:
library(readr)
Inmuebles_Disponibles_Para_La_Venta_20250513<-
  read_csv("C:/Users/Sebas/Downloads/Inmuebles_Disponibles_Para_La_Venta_20250513.csv")
  1. Preguntas de Analisis

A. Analisis Inicial y Limpieza

  1. Importacion y Estructura:

¿Cuántos registros y columnas tiene el dataset?

dim(Inmuebles_Disponibles_Para_La_Venta_20250513)
## [1] 448  12

¿Qué tipos de datos hay en el dataset (numéricos, categóricos, texto)?

# Mostrar el tipo de cada columna
sapply(Inmuebles_Disponibles_Para_La_Venta_20250513, class)
##                 Codigo                 Ciudad           Departamento 
##              "numeric"            "character"            "character" 
##                 Barrio              Direccion           Area Terreno 
##            "character"            "character"              "numeric" 
##        Area Construida Detalle Disponibilidad                Estrato 
##              "numeric"            "character"            "character" 
##                 Precio       Tipo de Inmueble      Datos Adicionales 
##              "numeric"            "character"            "character"
  1. Valores nulos y duplicados:

¿Qué columnas tienen valores nulos?

# Columnas con al menos un NA
na_cols <- colSums(is.na(Inmuebles_Disponibles_Para_La_Venta_20250513))
na_cols[na_cols > 0]
##            Barrio Datos Adicionales 
##               389               371
# Total de NA en todo el dataset
sum(is.na(Inmuebles_Disponibles_Para_La_Venta_20250513))
## [1] 760

¿Que porcentaje Representan?

#Renombramos la base
total_na <- sum(is.na(Inmuebles_Disponibles_Para_La_Venta_20250513))
# Con Prod calculamos el producto de todos los valores valores(se multiplican los valores)
total_valores <- prod(dim(Inmuebles_Disponibles_Para_La_Venta_20250513))# filas × columnas

#Sacamos el porcentaje
porcentaje_total_na <- (total_na / total_valores) * 100
porcentaje_total_na
## [1] 14.1369

¿Existen Registros duplicados?

any(duplicated(Inmuebles_Disponibles_Para_La_Venta_20250513))
## [1] FALSE
  1. Depuracion de Datos:

¿Hay valores atípicos (outliers) en precios o áreas? (Usar boxplots).

# Boxplots para Precios
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(scales)  # para formatear ejes con comas o puntos
## Warning: package 'scales' was built under R version 4.4.3
## 
## Adjuntando el paquete: 'scales'
## The following object is masked from 'package:readr':
## 
##     col_factor
ggplot(Inmuebles_Disponibles_Para_La_Venta_20250513, aes(y = Precio)) +
  geom_boxplot(fill = "red", color = "darkred") +
  labs(title = "Boxplot de Precio", y = "Precio (COP)") +
  scale_y_continuous(labels = label_comma(big.mark = ".", decimal.mark = ",")) +
  theme_minimal()

#Boxplot para Area Terreno
library(ggplot2)
library(scales)
ggplot(Inmuebles_Disponibles_Para_La_Venta_20250513, aes(y = `Area Terreno`)) +
  geom_boxplot(fill = "green", color = "darkgreen") +
  labs(title = "Boxplot de Área Terreno", y = "Área Terreno (m²)") +
  scale_y_continuous(labels = label_comma(big.mark = ".", decimal.mark = ",")) +
  theme_minimal()

library(ggplot2)
library(scales)
ggplot(Inmuebles_Disponibles_Para_La_Venta_20250513, aes(y = `Area Construida`)) +
  geom_boxplot(fill = "skyblue", color = "steelblue") +
  labs(title = "Boxplot de Área Construida", y = "Área Construida (m²)") +
  scale_y_continuous(labels = label_comma(big.mark = ".", decimal.mark = ",")) +
  theme_minimal()

¿Existen errores en categorías (ej: “aparatmento” en lugar de “apartamento”)?

#Variables Categoricas

library(dplyr)
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
data.frame(
  Variable = names(Inmuebles_Disponibles_Para_La_Venta_20250513),
  Tipo = sapply(Inmuebles_Disponibles_Para_La_Venta_20250513, class)
) %>% 
  filter(Tipo %in% c("factor", "character"))
##                                      Variable      Tipo
## Ciudad                                 Ciudad character
## Departamento                     Departamento character
## Barrio                                 Barrio character
## Direccion                           Direccion character
## Detalle Disponibilidad Detalle Disponibilidad character
## Estrato                               Estrato character
## Tipo de Inmueble             Tipo de Inmueble character
## Datos Adicionales           Datos Adicionales character
#Buscamos posibles errores en las variables categoricas mas importantes

# Vector con las columnas a revisar
cols <- c("Ciudad", "Departamento", "Tipo de Inmueble")

for (col in cols) {
  cat("---- Valores únicos en columna:", col, "----\n")
  print(sort(unique(Inmuebles_Disponibles_Para_La_Venta_20250513[[col]])))
  cat("\n")
}
## ---- Valores únicos en columna: Ciudad ----
##  [1] "AGUAZUL"                    "ANGOSTURA"                 
##  [3] "ARMERO"                     "BARRANQUILLA"              
##  [5] "BITUIMA"                    "BOGOTA"                    
##  [7] "BOLIVAR - CAUCA"            "BUGA"                      
##  [9] "CALI"                       "CALIMA EL DARIEN"          
## [11] "CARMEN DE BOLIVAR"          "CARTAGENA"                 
## [13] "CAUCASIA"                   "CHIA"                      
## [15] "CUCUTA"                     "CURITI"                    
## [17] "DAGUA"                      "EL AGUILA"                 
## [19] "EL PLAYON"                  "EL ROSAL"                  
## [21] "ENVIGADO"                   "FUNZA"                     
## [23] "GIRARDOT"                   "IBAGUE"                    
## [25] "LA CALERA"                  "LA DORADA"                 
## [27] "LA VIRGINIA"                "LOS PATIOS"                
## [29] "MADRID"                     "MANIZALES"                 
## [31] "MARSELLA"                   "MEDELLIN"                  
## [33] "MONTERIA"                   "PEREIRA"                   
## [35] "PIEDRAS"                    "PUERTO LOPEZ"              
## [37] "RICAURTE"                   "SAN ANTONIO DEL TEQUENDAMA"
## [39] "SANTANDER DE QUILICHAO"     "SOATA"                     
## [41] "SOGAMOSO"                   "TARAZA"                    
## [43] "TENJO"                      "TIBU"                      
## [45] "TURBO"                      "VILLA RICA"                
## [47] "VILLAVICENCIO"              "YUMBO"                     
## 
## ---- Valores únicos en columna: Departamento ----
##  [1] "ANTIOQUIA"          "ATLÁNTICO"          "BOLÍVAR"           
##  [4] "BOYACÁ"             "CALDAS"             "CASANARE"          
##  [7] "CAUCA"              "CÓRDOBA"            "CUNDINAMARCA"      
## [10] "META"               "NORTE DE SANTANDER" "RISARALDA"         
## [13] "SANTANDER"          "TOLIMA"             "VALLE DEL CAUCA"   
## 
## ---- Valores únicos en columna: Tipo de Inmueble ----
##  [1] "APARTAMENTO"           "BODEGA"                "CASA"                 
##  [4] "CLINICA"               "EDIFICIO"              "EDIFICIO VIVIENDA"    
##  [7] "FINCA"                 "GARAJE"                "HOTEL"                
## [10] "LOCAL"                 "LOTE"                  "LOTE AGRICOLA"        
## [13] "LOTE COMERCIAL"        "LOTE CON CONSTRUCCION" "LOTE INDUSTRIAL"      
## [16] "LOTE MIXTO"            "LOTE NO URBANIZABLE"   "LOTE VIVIENDA"        
## [19] "OFICINA"

B. Analisis Descriptivo

4.Distribuciones

¿Cómo se distribuyen los precios? ¿Es normal o sesgada? (Histograma + skewness).

# Histograma de los precios
options(scipen = 999)

hist(Inmuebles_Disponibles_Para_La_Venta_20250513$Precio,
     main = "Distribución de Precios",
     xlab = "Precio",
     col = "green", 
     border = "black",
     breaks = 30,
     xaxt = "n")  # Desactiva eje X automático

# Crear ticks automáticos del eje X
ticks <- axTicks(1)

# Agregar eje X con puntos como separadores de miles
axis(1, at = ticks, labels = format(ticks, big.mark = ".", scientific = FALSE))
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' y 'decimal.mark' son ambos '.', lo cual puede ser confuso

Skewness

# Instalar y cargar la librería e1071 para skewness
#install.packages("e1071") 
library(e1071)
## Warning: package 'e1071' was built under R version 4.4.3
skewness(Inmuebles_Disponibles_Para_La_Venta_20250513$Precio, na.rm = TRUE) 
## [1] 7.256093

#La cola es mas larga a la derecha(Asimetria positiva)

¿Qué tipo de inmueble es más común? (Gráfico de barras).

# Gráfico de barras del tipo de inmueble
library(ggplot2)

ggplot(Inmuebles_Disponibles_Para_La_Venta_20250513, aes(x = `Tipo de Inmueble`)) +
  geom_bar(fill = "red", color = "blue") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  labs(title = "Frecuencia de Tipos de Inmueble",
       x = "Tipo de Inmueble",
       y = "Frecuencia")

  1. Estadisticas Clave

Calcular media, mediana, desviación estándar, cuartiles y tablas de frecuencias

Media de los Precios

mean(Inmuebles_Disponibles_Para_La_Venta_20250513$Precio, na.rm = TRUE)
## [1] 9372905838386

Mediana de los Precios

median(Inmuebles_Disponibles_Para_La_Venta_20250513$Precio, na.rm = TRUE)
## [1] 165205000000

Desviación estándar de los precios

sd(Inmuebles_Disponibles_Para_La_Venta_20250513$Precio, na.rm = TRUE)
## [1] 38179638410195

Cuartiles de los precios

quantile(Inmuebles_Disponibles_Para_La_Venta_20250513$Precio, na.rm = TRUE)
##              0%             25%             50%             75%            100% 
##               0    125725000000    165205000000   1861440000000 452337898200000

Tablas de frecuencia, ordenadas de mayor a menor

Tipo Inmuebles

sort(table(Inmuebles_Disponibles_Para_La_Venta_20250513$`Tipo de Inmueble`), decreasing = TRUE)
## 
##                 LOCAL         LOTE VIVIENDA               OFICINA 
##                   304                    38                    28 
##                  CASA                BODEGA                 FINCA 
##                    14                     8                     8 
## LOTE CON CONSTRUCCION            LOTE MIXTO           APARTAMENTO 
##                     8                     6                     5 
##         LOTE AGRICOLA              EDIFICIO                  LOTE 
##                     5                     4                     4 
##       LOTE INDUSTRIAL               CLINICA        LOTE COMERCIAL 
##                     4                     3                     3 
##     EDIFICIO VIVIENDA                GARAJE                 HOTEL 
##                     2                     2                     1 
##   LOTE NO URBANIZABLE 
##                     1

Ciudad

sort(table(Inmuebles_Disponibles_Para_La_Venta_20250513$Ciudad), decreasing = TRUE)
## 
##              VILLAVICENCIO                     BOGOTA 
##                        285                         34 
##               BARRANQUILLA                  MANIZALES 
##                         14                         13 
##                    PEREIRA           CALIMA EL DARIEN 
##                         12                         10 
##                     CUCUTA                       CALI 
##                          9                          7 
##                   MONTERIA                       BUGA 
##                          6                          5 
##                   MEDELLIN                   GIRARDOT 
##                          5                          4 
##                    AGUAZUL                  CARTAGENA 
##                          3                          3 
##                     ARMERO                       CHIA 
##                          2                          2 
## SAN ANTONIO DEL TEQUENDAMA     SANTANDER DE QUILICHAO 
##                          2                          2 
##                  ANGOSTURA                    BITUIMA 
##                          1                          1 
##            BOLIVAR - CAUCA          CARMEN DE BOLIVAR 
##                          1                          1 
##                   CAUCASIA                     CURITI 
##                          1                          1 
##                      DAGUA                  EL AGUILA 
##                          1                          1 
##                  EL PLAYON                   EL ROSAL 
##                          1                          1 
##                   ENVIGADO                      FUNZA 
##                          1                          1 
##                     IBAGUE                  LA CALERA 
##                          1                          1 
##                  LA DORADA                LA VIRGINIA 
##                          1                          1 
##                 LOS PATIOS                     MADRID 
##                          1                          1 
##                   MARSELLA                    PIEDRAS 
##                          1                          1 
##               PUERTO LOPEZ                   RICAURTE 
##                          1                          1 
##                      SOATA                   SOGAMOSO 
##                          1                          1 
##                     TARAZA                      TENJO 
##                          1                          1 
##                       TIBU                      TURBO 
##                          1                          1 
##                 VILLA RICA                      YUMBO 
##                          1                          1

Departamento

sort(table(Inmuebles_Disponibles_Para_La_Venta_20250513$Departamento), decreasing = TRUE)
## 
##               META       CUNDINAMARCA    VALLE DEL CAUCA          ATLÁNTICO 
##                286                 49                 25                 14 
##             CALDAS          RISARALDA NORTE DE SANTANDER          ANTIOQUIA 
##                 14                 14                 11                 10 
##            CÓRDOBA            BOLÍVAR              CAUCA             TOLIMA 
##                  6                  4                  4                  4 
##           CASANARE             BOYACÁ          SANTANDER 
##                  3                  2                  2

Barrio

sort(table(Inmuebles_Disponibles_Para_La_Venta_20250513$Barrio), decreasing = TRUE)
## 
##             AV 30 DE AGOSTO                       SINAI 
##                          10                          10 
##              VEREDA PALERMO            JOSE MARIA CABAL 
##                          10                           4 
##            PRADOS DEL NORTE                      CENTRO 
##                           4                           3 
##                  BELLAVISTA        CIUDADELA CHIPICHAPE 
##                           1                           1 
## CONDOMINIO CAMPESTRE MONACO     CORREGIMIENTO EL CARMEN 
##                           1                           1 
##                   EL CENTRO                     EL HOYO 
##                           1                           1 
##                    EL PRADO                    GUACANDÁ 
##                           1                           1 
##                   LA CALERA        PARQUE IND CAUCADESA 
##                           1                           1 
## PARQUE INDUSTRIAL CAUCADESA               SANTA MATILDE 
##                           1                           1 
##                        SUBA                     TINTALA 
##                           1                           1 
##           VEREDA CHAMBIMBAL          VEREDA DE CAMBULAR 
##                           1                           1 
##             VEREDA FONQUETA               VILLA DEL SUR 
##                           1                           1

Estrato

sort(table(Inmuebles_Disponibles_Para_La_Venta_20250513$Estrato), decreasing = TRUE)
## 
##  COMERCIAL      RURAL        DOS       SEIS       TRES     CUATRO      CINCO 
##        321         36         32         18         16         13          8 
## INDUSTRIAL        UNO 
##          3          1
  1. Agrupaciones

¿Cuál es el precio promedio por estrato? ¿Y por ciudad? (Tablas resumen).

Precio promedio por estrato

library(dplyr)

Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  group_by(Estrato) %>%
  summarise(Promedio_Precio = mean(Precio, na.rm = TRUE)) %>%
  mutate(Promedio_Precio = format(Promedio_Precio, big.mark = ".", scientific = FALSE)) %>%
  arrange(Estrato)
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `Promedio_Precio = format(Promedio_Precio, big.mark = ".",
##   scientific = FALSE)`.
## Caused by warning in `prettyNum()`:
## ! 'big.mark' y 'decimal.mark' son ambos '.', lo cual puede ser confuso
## # A tibble: 9 × 2
##   Estrato    Promedio_Precio      
##   <chr>      <chr>                
## 1 CINCO      " 15.974.667.112.500"
## 2 COMERCIAL  "  4.148.108.896.355"
## 3 CUATRO     "  7.842.247.833.700"
## 4 DOS        " 13.018.464.040.359"
## 5 INDUSTRIAL "122.124.958.169.933"
## 6 RURAL      " 30.753.696.738.056"
## 7 SEIS       "  7.057.725.237.767"
## 8 TRES       " 38.728.254.529.850"
## 9 UNO        "    982.368.000.000"

Precio promedio por ciudad

library(dplyr)

Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  group_by(Ciudad) %>%
  summarise(Promedio_Precio = mean(Precio, na.rm = TRUE)) %>%
  mutate(Promedio_Precio = format(Promedio_Precio, big.mark = ".", scientific = FALSE)) %>%
  arrange(desc(Promedio_Precio))
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `Promedio_Precio = format(Promedio_Precio, big.mark = ".",
##   scientific = FALSE)`.
## Caused by warning in `prettyNum()`:
## ! 'big.mark' y 'decimal.mark' son ambos '.', lo cual puede ser confuso
## # A tibble: 48 × 2
##    Ciudad     Promedio_Precio      
##    <chr>      <chr>                
##  1 SOGAMOSO   "147.133.144.000.000"
##  2 MADRID     "116.565.311.500.000"
##  3 EL ROSAL   "109.839.864.000.000"
##  4 RICAURTE   "104.073.361.725.000"
##  5 BUGA       " 96.470.765.841.600"
##  6 VILLA RICA " 70.903.412.109.800"
##  7 PIEDRAS    " 68.451.105.930.000"
##  8 CURITI     " 55.248.601.890.000"
##  9 BOGOTA     " 52.663.773.505.921"
## 10 GIRARDOT   " 43.901.185.791.250"
## # ℹ 38 more rows

C. Analisis Espacial(Geografico)

  1. Mapas y geolocalización:

#Dado que no hay coordenadas, Analizar precios por departamento (mapas coropléticos).

#Dado que no hay coordenadas, analizamos por departamento
#Necesitamos un Shapefile para el analisis

library(sf)       # para leer y manejar shapefiles
## Warning: package 'sf' was built under R version 4.4.3
## Linking to GEOS 3.13.0, GDAL 3.10.1, PROJ 9.5.1; sf_use_s2() is TRUE
library(dplyr)    # para manipular datos
library(ggplot2)  # para graficar
library(scales)   # para formatear números en los gráficos

#Cargamos el shapefile
departamentos_sf <- st_read("C:/Users/Sebas/Downloads/gadm41_COL_1.json/gadm41_COL_1.json")
## Reading layer `gadm41_COL_1' from data source 
##   `C:\Users\Sebas\Downloads\gadm41_COL_1.json\gadm41_COL_1.json' 
##   using driver `GeoJSON'
## Simple feature collection with 33 features and 11 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -81.8412 ymin: -4.2284 xmax: -66.8377 ymax: 15.9125
## Geodetic CRS:  WGS 84
#Calculamos el precio promedio por ciudad
precios_departamento <- Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  group_by(Departamento) %>%
  summarise(Promedio_Precio = mean(Precio, na.rm = TRUE))

#El shapefile y la base Imbuebles tienen nombres diferentes para la columna departamento
#Ajustamos lo nombres para que coincidan en ambas bases

# Nombres de departamentos en el shapefile
unique(departamentos_sf$NAME_1)
##  [1] "Amazonas"              "Antioquia"             "Arauca"               
##  [4] "Atlántico"             "BogotáD.C."            "Bolívar"              
##  [7] "Boyacá"                "Caldas"                "Caquetá"              
## [10] "Casanare"              "Cauca"                 "Cesar"                
## [13] "Chocó"                 "Córdoba"               "Cundinamarca"         
## [16] "Guainía"               "Guaviare"              "Huila"                
## [19] "LaGuajira"             "Magdalena"             "Meta"                 
## [22] "Nariño"                "NortedeSantander"      "Putumayo"             
## [25] "Quindío"               "Risaralda"             "SanAndrésyProvidencia"
## [28] "Santander"             "Sucre"                 "Tolima"               
## [31] "ValledelCauca"         "Vaupés"                "Vichada"
#Nombres de departamentos en la base Inmuebles
unique(precios_departamento$Departamento)
##  [1] "ANTIOQUIA"          "ATLÁNTICO"          "BOLÍVAR"           
##  [4] "BOYACÁ"             "CALDAS"             "CASANARE"          
##  [7] "CAUCA"              "CUNDINAMARCA"       "CÓRDOBA"           
## [10] "META"               "NORTE DE SANTANDER" "RISARALDA"         
## [13] "SANTANDER"          "TOLIMA"             "VALLE DEL CAUCA"
#Observamos que hay diferencias en el uso de: Mayusculas, Espacios y Tildes 


#Para hacer el join(Unir las bases) correctamente, necesitamos normalizar y limpiar ambos vectores de nombres para que coincidan.

#Pasamos ambas a minusculas
departamentos_sf <- departamentos_sf %>%
  mutate(NAME_1 = tolower(NAME_1))

precios_departamento <- precios_departamento %>%
  mutate(Departamento = tolower(Departamento))


#Eliminamos las tildes
#install.packages("stringi")
library(stringi)

departamentos_sf <- departamentos_sf %>%
  mutate(NAME_1 = stri_trans_general(NAME_1, "Latin-ASCII"))

precios_departamento <- precios_departamento %>%
  mutate(Departamento = stri_trans_general(Departamento, "Latin-ASCII"))

#Elimanamos espacios y/o caracteres especiales
departamentos_sf <- departamentos_sf %>%
  mutate(NAME_1 = gsub(" ", "", NAME_1)) %>%   # eliminar espacios
  mutate(NAME_1 = gsub("\\.", "", NAME_1))    # eliminar puntos

precios_departamento <- precios_departamento %>%
  mutate(Departamento = gsub(" ", "", Departamento)) %>%
  mutate(Departamento = gsub("\\.", "", Departamento))


#Verificamos si coinciden los nombres de los departamentos
unique(departamentos_sf$NAME_1)
##  [1] "amazonas"              "antioquia"             "arauca"               
##  [4] "atlantico"             "bogotadc"              "bolivar"              
##  [7] "boyaca"                "caldas"                "caqueta"              
## [10] "casanare"              "cauca"                 "cesar"                
## [13] "choco"                 "cordoba"               "cundinamarca"         
## [16] "guainia"               "guaviare"              "huila"                
## [19] "laguajira"             "magdalena"             "meta"                 
## [22] "narino"                "nortedesantander"      "putumayo"             
## [25] "quindio"               "risaralda"             "sanandresyprovidencia"
## [28] "santander"             "sucre"                 "tolima"               
## [31] "valledelcauca"         "vaupes"                "vichada"
unique(precios_departamento$Departamento)
##  [1] "antioquia"        "atlantico"        "bolivar"          "boyaca"          
##  [5] "caldas"           "casanare"         "cauca"            "cundinamarca"    
##  [9] "cordoba"          "meta"             "nortedesantander" "risaralda"       
## [13] "santander"        "tolima"           "valledelcauca"
#Ya confirmamos que ambas bases tienen los nombres de los departamentos igual

#Ahora, Unimos las bases
departamentos_mapa <- departamentos_sf %>%
  left_join(precios_departamento, by = c("NAME_1" = "Departamento"))


#Creamos un mapa mejor

library(leaflet)
## Warning: package 'leaflet' was built under R version 4.4.3
library(sf)
library(dplyr)

# Definir paleta de colores para los precios
pal <- colorNumeric(palette = "YlOrRd", domain = departamentos_mapa$Promedio_Precio)

# Creamos el mapa 
leaflet(departamentos_mapa) %>%
  addProviderTiles("CartoDB.Positron") %>%
  addPolygons(
    fillColor = ~pal(Promedio_Precio),
    weight = 1,
    opacity = 1,
    color = "white",
    dashArray = "3",
    fillOpacity = 0.8,
    highlight = highlightOptions(
      weight = 3,
      color = "#666",
      dashArray = "",
      fillOpacity = 0.7,
      bringToFront = TRUE
    ),
    label = ~paste0(NAME_1, ": $", format(Promedio_Precio, big.mark = ".", scientific = FALSE)),
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "13px",
      direction = "auto"
    )
  ) %>%
  addLegend(pal = pal, values = ~Promedio_Precio, opacity = 0.7,
            title = "Precio Promedio", position = "bottomright")
## Warning in prettyNum(.Internal(format(x, trim, digits, nsmall, width, 3L, :
## 'big.mark' y 'decimal.mark' son ambos '.', lo cual puede ser confuso
  1. Patrones Geograficos

¿Hay diferencias de precio entre regiones o departamentos? (Boxplot por ciudad).

library(dplyr)
library(scales)

# Calcular resumen estadístico por departamento
resumen_departamento <- Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  group_by(Departamento) %>%
  summarise(
    N = n(),
    Mediana = median(Precio, na.rm = TRUE),
    Min = min(Precio, na.rm = TRUE),
    Max = max(Precio, na.rm = TRUE)
  ) %>%
  arrange(desc(Mediana))

# Mostrar la tabla con separadores de miles para mejor legibilidad
resumen_departamento %>%
  mutate(across(Mediana:Max, ~ comma(.)))
## # A tibble: 15 × 5
##    Departamento           N Mediana            Min               Max            
##    <chr>              <int> <chr>              <chr>             <chr>          
##  1 BOYACÁ                 2 76,981,516,250,000 6,829,888,500,000 147,133,144,00…
##  2 SANTANDER              2 29,446,428,945,000 3,644,256,000,000 55,248,601,890…
##  3 BOLÍVAR                4 23,355,338,265,000 0                 76,590,000,000…
##  4 CUNDINAMARCA          49 14,482,416,000,000 299,400,000,000   328,393,170,35…
##  5 CAUCA                  4 10,770,526,430,000 341,715,000,000   70,903,412,109…
##  6 CASANARE               3 8,834,784,000,000  4,298,641,200,000 28,679,755,510…
##  7 VALLE DEL CAUCA       25 8,109,750,100,000  206,080,036,800   452,337,898,20…
##  8 TOLIMA                 4 5,555,332,100,000  3,533,589,780,000 68,451,105,930…
##  9 CÓRDOBA                6 5,351,620,000,000  673,191,500,000   14,356,563,410…
## 10 ANTIOQUIA             10 4,356,002,625,000  807,621,000,000   24,581,464,440…
## 11 ATLÁNTICO             14 2,132,057,600,000  1,590,195,200,000 36,673,427,000…
## 12 NORTE DE SANTANDER    11 1,798,350,000,000  1,377,450,000,000 8,980,970,000,…
## 13 RISARALDA             14 693,001,875,000    65,990,400,000    43,343,535,000…
## 14 CALDAS                14 365,760,000,000    335,520,000,000   66,147,000,000…
## 15 META                 286 125,725,000,000    69,750,000,000    41,901,550,210…

Boxplot por ciudades

library(dplyr)
library(ggplot2)
library(scales)

# Filtrar ciudades con al menos 10 observaciones
ciudades_con_suficientes_datos <- Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  group_by(Ciudad) %>%
  filter(n() >= 10)

# Crear boxplot de precio por ciudad
ggplot(ciudades_con_suficientes_datos, aes(x = reorder(Ciudad, Precio, FUN = median), y = Precio)) +
  geom_boxplot(fill = "skyblue", outlier.color = "red", outlier.shape = 1) +
  scale_y_continuous(labels = comma) +
  labs(title = "Distribución del Precio por Ciudad",
       x = "Ciudad",
       y = "Precio (COP)") +
  coord_flip() +
  theme_minimal()

¿Cómo varía el precio por m² en barrios de alto estrato?

# Contamos cuántos registros hay en estratos altos (CINCO y SEIS)
Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  filter(Estrato %in% c("CINCO", "SEIS")) %>%
  summarise(
    total_registros = n(),
    con_area_construida = sum(`Area Construida` > 0, na.rm = TRUE),
    con_area_terreno = sum(`Area Terreno` > 0, na.rm = TRUE)
  )
## # A tibble: 1 × 3
##   total_registros con_area_construida con_area_terreno
##             <int>               <int>            <int>
## 1              26                   0                0

No se puede calcular el precio por metro cuadrado en barrios de estrato alto (CINCO y SEIS) porque no hay datos válidos de área construida ni de área terreno; todos los registros tienen estas áreas en cero, lo que impide el análisis.

D. Relaciones entre Variables

  1. Correlaciones

¿Qué variables numéricas correlacionan más con el precio? (Matriz de correlación).

# Mostrar los nombres de las columnas numéricas
names(select_if(Inmuebles_Disponibles_Para_La_Venta_20250513, is.numeric))
## [1] "Codigo"          "Area Terreno"    "Area Construida" "Precio"
# Cargar librerías necesarias
library(dplyr)
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.4.3
## corrplot 0.95 loaded
# Seleccionar las variables numéricas relevantes
df_num <- Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  select(Precio, `Area Terreno`, `Area Construida`) %>%
  filter(!is.na(Precio), !is.na(`Area Terreno`), !is.na(`Area Construida`))

# Calcular la matriz de correlación
cor_mat <- cor(df_num, use = "complete.obs")

# Mostrar matriz de correlación en consola
print(cor_mat)
##                    Precio Area Terreno Area Construida
## Precio          1.0000000    0.4701345       0.5621413
## Area Terreno    0.4701345    1.0000000       0.6840462
## Area Construida 0.5621413    0.6840462       1.0000000

Grafica

# Graficar la matriz de correlación con corrplot
corrplot(cor_mat, method = "color", addCoef.col = "black",
         tl.cex = 1, number.cex = 0.8, tl.col = "black",
         title = "Matriz de correlación",
         mar=c(0,0,1,0))

El área construida influye más que el área de terreno?

Si, la correlación entre precio y área construida es mayor que la correlación entre precio y área terreno

Explicacion:

La correlación entre precio y área construida es fuerte y positiva, lo que indica que a mayor área construida, mayor es el precio del inmueble. Esto es esperado ya que la construcción suele agregar valor directo a la propiedad.

-La correlación entre precio y área del terreno es positiva, pero menor que la de área construida, sugiriendo que aunque el tamaño del terreno influye en el precio, su impacto es menos determinante que el área construida.

-La correlación entre las dos áreas (terreno y construida) también es positiva, lo que refleja que terrenos más grandes tienden a tener construcciones mayores.

  1. Análisis multivariable:

¿Cómo se relaciona el precio con el estrato y el tipo de inmueble? (Gráficos de dispersión con facetas).

Primero calculamos las estadisticas clave

library(dplyr)
library(scales)  # para la función comma()

resumen <- Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  group_by(Estrato, `Tipo de Inmueble`) %>%
  summarise(
    n = n(),
    Precio_mediana = median(Precio, na.rm = TRUE),
    Precio_media = mean(Precio, na.rm = TRUE)
  )
## `summarise()` has grouped output by 'Estrato'. You can override using the
## `.groups` argument.
# Con el siguiente codigo muestra con separadores de miles
resumen %>%
  mutate(
    Precio_mediana = comma(Precio_mediana),
    Precio_media = comma(Precio_media)
  ) %>%
  print()
## # A tibble: 50 × 5
## # Groups:   Estrato [9]
##    Estrato   `Tipo de Inmueble`     n Precio_mediana      Precio_media       
##    <chr>     <chr>              <int> <chr>               <chr>              
##  1 CINCO     CASA                   5 10,202,150,000,000  16,501,209,060,000 
##  2 CINCO     CLINICA                1 43,343,535,000,000  43,343,535,000,000 
##  3 CINCO     LOCAL                  1 162,150,000,000     162,150,000,000    
##  4 CINCO     LOTE VIVIENDA          1 1,785,606,600,000   1,785,606,600,000  
##  5 COMERCIAL BODEGA                 2 58,282,655,750,000  58,282,655,750,000 
##  6 COMERCIAL CASA                   2 15,986,362,255,000  15,986,362,255,000 
##  7 COMERCIAL CLINICA                2 125,286,522,000,000 125,286,522,000,000
##  8 COMERCIAL EDIFICIO               4 115,376,457,500,000 100,547,179,625,000
##  9 COMERCIAL HOTEL                  1 104,073,361,725,000 104,073,361,725,000
## 10 COMERCIAL LOCAL                291 125,725,000,000     358,532,438,711    
## # ℹ 40 more rows

Creamos el Gráficos de dispersión con facetas(con los tipo inmuebles mas frecuentes)

library(dplyr)
library(ggplot2)
library(scales)

tipos_interes <- c("LOCAL", "LOTE VIVIENDA", "OFICINA", "CASA")

df_filtrado <- Inmuebles_Disponibles_Para_La_Venta_20250513 %>%
  filter(`Tipo de Inmueble` %in% tipos_interes,
         !is.na(Precio),
         Precio > 0,  # elimina precios 0 para escala log
         !is.na(Estrato),
         Estrato %in% c("UNO", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "COMERCIAL", "INDUSTRIAL"))

orden_estratos <- c("UNO", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "COMERCIAL", "INDUSTRIAL")
df_filtrado$Estrato <- factor(df_filtrado$Estrato, levels = orden_estratos)
df_filtrado$`Tipo de Inmueble` <- factor(df_filtrado$`Tipo de Inmueble`, levels = tipos_interes)

ggplot(df_filtrado, aes(x = Estrato, y = Precio, color = `Tipo de Inmueble`)) +
  geom_jitter(alpha = 0.6, width = 0.2, size = 1.8) +
  scale_y_log10(
    labels = label_number(scale_cut = cut_short_scale(), big.mark = ".", decimal.mark = ","),
    breaks = scales::trans_breaks("log10", function(x) 10^x),
    minor_breaks = NULL
  ) +
  facet_grid(. ~ `Tipo de Inmueble`, scales = "free_x", space = "free_x") +
  labs(
    title = "Precio vs Estrato según Tipo de Inmueble (escala logarítmica)",
    x = "Estrato",
    y = "Precio (log escala, abreviado)",
    color = "Tipo de Inmueble"
  ) +
  theme_minimal() +
  theme(
    strip.background = element_rect(fill = "lightgray", color = "black"),
    strip.text = element_text(size = 12, face = "bold"),
    axis.text.x = element_text(angle = 45, hjust = 1),
    panel.spacing.x = unit(1, "lines")
  )