library(readxl)
datos = read_excel("C:/Users/kaqu/Documents/Maestria Ciencia de Datos/Metodos_simulacion_estadistica/Actividad 1/Datos_Vivienda.xlsx")
attach(datos)
ID=1:dim(datos)[1]
datos=data.frame(ID,datos)
kbl(head(datos)) %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| ID | Zona | piso | Estrato | precio_millon | Area_contruida | parqueaderos | Banos | Habitaciones | Tipo | Barrio | cordenada_longitud | Cordenada_latitud |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Zona Sur | 2 | 6 | 880 | 237 | 2 | 5 | 4 | Casa | pance | -76.46300 | 3.43000 |
| 2 | Zona Oeste | 2 | 4 | 1200 | 800 | 3 | 6 | 7 | Casa | miraflores | -76.46400 | 3.42800 |
| 3 | Zona Sur | 3 | 5 | 250 | 86 | NA | 2 | 3 | Apartamento | multicentro | -76.46400 | 3.42900 |
| 4 | Zona Sur | NA | 6 | 1280 | 346 | 4 | 6 | 5 | Apartamento | ciudad jardv<U+2260>n | -76.46400 | 3.43300 |
| 5 | Zona Sur | 2 | 6 | 1300 | 600 | 4 | 7 | 5 | Casa | pance | -76.46438 | 3.43463 |
| 6 | Zona Sur | 3 | 6 | 513 | 160 | 2 | 4 | 4 | Casa | pance | -76.46438 | 3.43463 |
Esta actividad tiene como objetivo familiarizarnos con posibles retos que nos podemos encontrar a la hora de trabajar con información acerca de viviendas. En este caso se trabaja con un Data Frame asociado a diferentes tipos de viviendas (casas, apartamentos, etc.) cuya fuente es OLX.
Se encuentran dentro del DataFrame variables a asociadas a las caractéristicas de las viviendas, tales como ubicación (coordenadas, zona, estrato, etc), como propias (Area conatruida, número de baños, habitaciones,entre otras.)
library(dplyr)
names(datos)
## [1] "ID" "Zona" "piso"
## [4] "Estrato" "precio_millon" "Area_contruida"
## [7] "parqueaderos" "Banos" "Habitaciones"
## [10] "Tipo" "Barrio" "cordenada_longitud"
## [13] "Cordenada_latitud"
¿La base trabajada cuenta con datos faltantes?
library(inspectdf)
df3 = datos
summary(df3)
## ID Zona piso Estrato
## Min. : 1 Length:8322 Length:8322 Min. :3.000
## 1st Qu.:2081 Class :character Class :character 1st Qu.:4.000
## Median :4162 Mode :character Mode :character Median :5.000
## Mean :4162 Mean :4.634
## 3rd Qu.:6242 3rd Qu.:5.000
## Max. :8322 Max. :6.000
## NA's :3
## precio_millon Area_contruida parqueaderos Banos
## Min. : 58.0 Min. : 30.0 Length:8322 Min. : 0.000
## 1st Qu.: 220.0 1st Qu.: 80.0 Class :character 1st Qu.: 2.000
## Median : 330.0 Median : 123.0 Mode :character Median : 3.000
## Mean : 433.9 Mean : 174.9 Mean : 3.111
## 3rd Qu.: 540.0 3rd Qu.: 229.0 3rd Qu.: 4.000
## Max. :1999.0 Max. :1745.0 Max. :10.000
## NA's :2 NA's :3 NA's :3
## Habitaciones Tipo Barrio cordenada_longitud
## Min. : 0.000 Length:8322 Length:8322 Min. :-76.59
## 1st Qu.: 3.000 Class :character Class :character 1st Qu.:-76.54
## Median : 3.000 Mode :character Mode :character Median :-76.53
## Mean : 3.605 Mean :-76.53
## 3rd Qu.: 4.000 3rd Qu.:-76.52
## Max. :10.000 Max. :-76.46
## NA's :3 NA's :3
## Cordenada_latitud
## Min. :3.333
## 1st Qu.:3.381
## Median :3.416
## Mean :3.418
## 3rd Qu.:3.452
## Max. :3.498
## NA's :3
nas = inspect_na(df3)
kbl(nas, caption = "<center><strong>Inspección de NA's por variable </strong></center>") %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| col_name | cnt | pcnt |
|---|---|---|
| Zona | 3 | 0.0360490 |
| piso | 3 | 0.0360490 |
| Estrato | 3 | 0.0360490 |
| Area_contruida | 3 | 0.0360490 |
| parqueaderos | 3 | 0.0360490 |
| Banos | 3 | 0.0360490 |
| Habitaciones | 3 | 0.0360490 |
| Tipo | 3 | 0.0360490 |
| Barrio | 3 | 0.0360490 |
| cordenada_longitud | 3 | 0.0360490 |
| Cordenada_latitud | 3 | 0.0360490 |
| precio_millon | 2 | 0.0240327 |
| ID | 0 | 0.0000000 |
Se identifica que la cantidad de NA’s de la base se puede considerar pequeña ya que alcanza tan solo un 3% del total de la base, por lo que de inicio se piensa en ver si es posible recuperar esta información.
Con la revisión de los registros vacíos por variable, se concluye que el porcentaje de los mismos no supera el 3%, valor que podría considerarse como bajo. Dadas las condiciones como fue extraída esta información, la fuente y que la información es de carácter público, podría evaluarse no trabajar con estos datos. A continuación se presenta la tabla que contiene las frecuencias absolutas y relativas de datos faltantes por variable:
Se inspecciona por medio del siguiente gráfico la combinación de campos vacíos por registros y el número de veces que se presenta.
library(VIM)
capture.output(aggr(df3, numbers=T, prop=F,sortVars = T,cex.axis = 0.5), file=tempfile())
De la figura anterior, se identifica que existen 8319 registros que cuentan con completitud en la data, para las observaciones con datos faltantes se presentan los siguientes casos:
Datos Atípicos
df4=df3
kbl(descriptivas(df3$precio_millon), caption = "<center><strong> Comportamiento Precio de Vivienda </strong></center>") %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| MEDIDA | VALOR |
|---|---|
| Observaciones | 8320.000000 |
| Mínimo | 58.000000 |
| 1er Q | 220.000000 |
| Media | 433.891947 |
| Mediana | 330.000000 |
| Desv Est | 328.647244 |
| 3er Q | 540.000000 |
| Máximo | 1999.000000 |
| Asimetría | 1.849256 |
| Curtosis | 3.672296 |
| atípico leve< | -260.000000 |
| atípico leve> | 1020.000000 |
| atípico extremo< | -740.000000 |
| atípico extremo> | 1500.000000 |
| Err Est Media | 3.603034 |
| IC(95%) Media Up | 440.953893 |
| IC(95%) Media Down | 426.830001 |
par(mfrow = c(2,1))
boxplot(df4$precio_millon, horizontal = TRUE, main = "Boxplot Precio Vivienda General",col="#A6CEE3" )
hist(df4$precio_millon,main = "Histograma Precio Vivienda General" , ylab = "Frecuencia" , xlab = "Precio Vivienda General",col="#A6CEE3")
Se puede observar tanto en los gráficos como en las medidas calculadas que el precio de vivienda en promedio esta alrededor de 434 millones, mientras que la mediana es apenas de 330 millones. Lo que evidencia varios valores atípicos, identificando que el cerco superior esta al rededor de 1000 millones, asi pues, se evidencia asímetria positiva.
Tipos de variables a trabajar
str(datos)
## 'data.frame': 8322 obs. of 13 variables:
## $ ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ Zona : chr "Zona Sur" "Zona Oeste" "Zona Sur" "Zona Sur" ...
## $ piso : chr "2" "2" "3" "NA" ...
## $ Estrato : num 6 4 5 6 6 6 6 5 4 6 ...
## $ precio_millon : num 880 1200 250 1280 1300 513 870 310 240 690 ...
## $ Area_contruida : num 237 800 86 346 600 160 490 82.5 80 150 ...
## $ parqueaderos : chr "2" "3" "NA" "4" ...
## $ Banos : num 5 6 2 6 7 4 6 2 2 5 ...
## $ Habitaciones : num 4 7 3 5 5 4 5 3 3 4 ...
## $ Tipo : chr "Casa" "Casa" "Apartamento" "Apartamento" ...
## $ Barrio : chr "pance" "miraflores" "multicentro" "ciudad jardv<U+2260>n" ...
## $ cordenada_longitud: num -76.5 -76.5 -76.5 -76.5 -76.5 ...
## $ Cordenada_latitud : num 3.43 3.43 3.43 3.43 3.43 ...
Categorizando algunas variables
datos$parqueaderos_cat=cut(datos$parqueaderos, breaks = c(-1,0,1,4), include.lowest = F, labels = c("0","1",">=2"))
datos$Banos_cat=cut(datos$Banos, breaks = c(-1,0,1,2,6), include.lowest = F, labels = c("0","1","2",">=3"))
datos$Habitaciones_cat=cut(datos$Habitaciones, breaks = c(-1,0,1,2,7), include.lowest = F, labels = c("0","1","2",">=3"))
Filtrando Tipo de vivienda = Apartamento"
Conteo Tipo de vivienda
## Tipo n
## 1 Apartamento 5100
## 2 Casa 3219
## 3 <NA> 3
datos_sub <- datos %>%
filter(Tipo == 'Apartamento' )
dim(datos_sub)[1]
## [1] 5100
Se puede observar que hay mayor presencia, de datos asociados a apartamentos, en la base que actualmente se esta trabajando, pues representa mas del 50% del total.
RecordLinkage
require(RecordLinkage)
datos_colse=which(jarowinkler("colseguros",datos_sub$Barrio)>0.8)
datos_sub_colse=datos_sub[datos_colse,]
dim(datos_sub_colse)[1]
## [1] 23
Alternativa a RecordLinkage
datos_sub_barrio=datos_sub %>% filter(grepl('colse', Barrio))
dim(datos_sub_barrio)[1]
## [1] 25
kbl(table(datos_sub_barrio$Barrio), caption = "<center><strong> Barrios asociados a Colseguros </strong></center>") %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| Var1 | Freq |
|---|---|
| colseguros | 22 |
| colseguros andes | 1 |
| urbanizaciv=n colseguros | 2 |
Se puede observar que apartir de las dos técnicas planteadas, los resultados cambian un poco, mientras por recordlinkage queda un total de 23 apartamentos, por la opción de filtrado con dplyr, queda un total de 25 apartamentos.
summary(datos_sub_colse)
## ID Zona piso Estrato precio_millon
## Min. : 840 Zona Centro : 0 2 :4 3: 1 Min. :120.0
## 1st Qu.:3906 Zona Norte : 0 5 :4 4:22 1st Qu.:144.0
## Median :4069 Zona Oeste : 0 NA :4 5: 0 Median :163.0
## Mean :3977 Zona Oriente: 0 3 :3 6: 0 Mean :209.3
## 3rd Qu.:4580 Zona Sur :23 4 :3 3rd Qu.:245.0
## Max. :5831 1 :2 Max. :420.0
## (Other):3
## Area_contruida parqueaderos Banos Habitaciones
## Min. : 55.00 Min. :1.00 Min. :1.000 Min. :0.000
## 1st Qu.: 62.00 1st Qu.:1.00 1st Qu.:1.000 1st Qu.:3.000
## Median : 73.00 Median :1.00 Median :2.000 Median :3.000
## Mean : 96.98 Mean :1.05 Mean :2.261 Mean :3.174
## 3rd Qu.: 93.50 3rd Qu.:1.00 3rd Qu.:2.500 3rd Qu.:3.000
## Max. :300.00 Max. :2.00 Max. :5.000 Max. :6.000
## NA's :3
## Tipo Barrio cordenada_longitud Cordenada_latitud
## Apartamento:23 Length:23 Min. :-76.54 Min. :3.365
## Casa : 0 Class :character 1st Qu.:-76.53 1st Qu.:3.423
## Mode :character Median :-76.53 Median :3.427
## Mean :-76.53 Mean :3.422
## 3rd Qu.:-76.53 3rd Qu.:3.428
## Max. :-76.50 Max. :3.432
##
## parqueaderos_cat Banos_cat Habitaciones_cat
## 0 : 0 0 : 0 0 : 1
## 1 :19 1 : 7 1 : 0
## >=2 : 1 2 :10 2 : 2
## NA's: 3 >=3: 6 >=3:20
##
##
##
datos_sub_colse$parqueaderos = as.numeric(datos_sub_colse$parqueaderos)
datos_sub_colse$parqueaderos_cat=cut(datos_sub_colse$parqueaderos, breaks = c(-1,0,1,4), include.lowest = F, labels = c("0","1",">=2"))
parque = tabla_freq(datos_sub_colse$parqueaderos_cat)
kbl(parque, caption = "<center><strong> Número de Parqueaderos: Colseguros (apartamentos) </strong></center>") %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| Categoría | Freq. Abs. | Freq. Rel. |
|---|---|---|
| 0 | 0 | 0.000000 |
| 1 | 19 | 82.608696 |
| >=2 | 1 | 4.347826 |
| NA | 3 | 13.043478 |
| Total | 23 | 100.000000 |
El 82% de los apartamentos pertenecientes al barrio colseguros, tienen al menos 1 parqueadero.
datos_sub_colse$Banos_cat=cut(datos_sub_colse$Banos, breaks = c(-1,0,1,2,6), include.lowest = F, labels = c("0","1","2",">=3"))
banoscat = tabla_freq(datos_sub_colse$Banos_cat)
kbl(banoscat, caption = "<center><strong> Número de Baños: Colseguros (apartamentos) </strong></center>") %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| Categoría | Freq. Abs. | Freq. Rel. |
|---|---|---|
| 0 | 0 | 0.00000 |
| 1 | 7 | 30.43478 |
| 2 | 10 | 43.47826 |
| >=3 | 6 | 26.08696 |
| Total | 23 | 100.00000 |
El 73% de los apartamentos ubicados en este barrio contienen al menos 2 baños.
datos_sub_colse$Habitaciones_cat=cut(datos_sub_colse$Habitaciones, breaks = c(-1,0,1,2,7), include.lowest = F, labels = c("0","1","2",">=3"))
habi = tabla_freq(datos_sub_colse$Habitaciones_cat)
kbl(habi, caption = "<center><strong> Número de Habitaciones: Colseguros (apartamentos) </strong></center>") %>%
kable_paper(bootstrap_options = "striped", full_width = FALSE,position = "left")
| Categoría | Freq. Abs. | Freq. Rel. |
|---|---|---|
| 0 | 1 | 4.347826 |
| 1 | 0 | 0.000000 |
| 2 | 2 | 8.695652 |
| >=3 | 20 | 86.956522 |
| Total | 23 | 100.000000 |
Aunque podría ser un error de la base de datos, se observa que existe un apartamento que tiene cero habitaciones, lo que podría sugerir que no precisamente es un apartamento. 20 apartamentos de los 23 evaluados (87%) contienen tres o mas habitaciones.
##Tabla de Indicadores Importantes
promedio_precio=mean(datos_sub_colse$precio_millon,na.rm=TRUE)
mediana_precio=median(datos_sub_colse$precio_millon,na.rm=TRUE)
max_precio=quantile(datos_sub_colse$precio_millon, probs = 1,na.rm=TRUE)
promedio_area=mean(datos_sub_colse$Area_contruida,na.rm=TRUE)
cantidad_ofertas=length(datos_sub_colse$Zona)
resultado=data.frame(promedio_precio,mediana_precio,promedio_area,max_precio,cantidad_ofertas)
resultado
## promedio_precio mediana_precio promedio_area max_precio cantidad_ofertas
## 100% 209.3478 163 96.98435 420 23
Se observa que en promedio el precio de los apartamentos para la muestra encontrada en el barrio colseguros es de 209 millones. El precio mas alto es de 420 millones, lo que provoca que difiera la media vs la mediana.
El area promedio de estos apartamentos es de 97 m2 aproximadamente.
par(mfrow=c(1,3))
D1= boxplot(precio_millon ~ Barrio , data=datos_sub_barrio,
col=c('#A6CEE3', '#1F78B4'),
xlab='Barrio', main='(a)',
ylab='Precio Apto.',cex.axis = 0.7)
D2= boxplot(precio_millon ~ Banos_cat , data=datos_sub_barrio,
col=c('#A6CEE3', '#1F78B4'),
xlab='Num Baños', main='(b)',
ylab='Precio Apto.',cex.axis = 0.7)
D3= boxplot(precio_millon ~ parqueaderos_cat, data=datos_sub_barrio,
col=c('#A6CEE3', '#1F78B4'),
xlab='Num. parqueaderos', main='(c)',
ylab='Precio Apto.',cex.axis = 0.7)
mtext("Figura 6: Distribución precio según Barrios, Baños y Parqueaderos para apartamentos en Colseguros", side = 3, line = -0.8, outer = TRUE,cex=0.7,font=3)
En el gráfico a se puede observar que los barrios clasificados según urbanización colseguros parecen tener un precio mas elevado. En el gráfico 2, se observa que hay una relación directa entre el precio del apartamento y la cantidad de baños.
En el gráfico b, se puede observar que cuando hay tres o mas baños en un apartamento, al 50% de los apartamentos, tienen un precio de 270 millones aproximadamente.
En el gráfico c, se observa que cuando hay dos o mas parqueaderos, puede incrementar el valor del apartamento notablemente.
library(ggplot2)
ggplot(data = datos_sub_colse, aes(x = precio_millon)) +
geom_histogram(aes(y = ..count.., fill = ..count..)) +
scale_fill_gradient(low = "light blue", high = "light blue") +
stat_function(fun = dnorm, colour = "black", args = list(mean = mean(precio_millon), sd = sd(precio_millon))) +
ggtitle("Histograma Valor de Apartamento Colseguros") + labs(colour = "Horas")+ labs(x = "Precio $MM")
Gracias al histograma, se puede observar que evidentemente hay unos apartamentos, que tienen unos precios bastante altos, casi de 400 millones de pesos. La mayoria parece concentrarse hasta los 200 millones de pesos.
require(leaflet)
leaflet() %>% addCircleMarkers(lng = datos_sub_colse$cordenada_longitud,lat = datos_sub_colse$Cordenada_latitud,radius = 0.3,color = "black",label = datos_sub_colse$ID) %>% addTiles()
Se puede observar gracias al anterior mapa interactivo, que pueden haber 3 apartamentos que estan quedando mal clasificados, esto lo explica la lejanía que existe frente a la concentración. Una de las observaciones esta quedando en el sur, y otras dos observaciones en el oriente de cali.
datos_sub_colse[datos_sub_colse$ID==5831,]
## ID Zona piso Estrato precio_millon Area_contruida parqueaderos Banos
## 3439 5831 Zona Sur 5 4 201 105.01 1 2
## Habitaciones Tipo Barrio cordenada_longitud Cordenada_latitud
## 3439 3 Apartamento colseguros -76.53877 3.36514
## parqueaderos_cat Banos_cat Habitaciones_cat
## 3439 1 2 >=3
datos_sub_colse[datos_sub_colse$ID==840,]
## ID Zona piso Estrato precio_millon Area_contruida parqueaderos Banos
## 462 840 Zona Sur 4 4 138 60 1 1
## Habitaciones Tipo Barrio cordenada_longitud Cordenada_latitud
## 462 3 Apartamento colseguros -76.50397 3.422
## parqueaderos_cat Banos_cat Habitaciones_cat
## 462 1 1 >=3
datos_sub_colse[datos_sub_colse$ID==863,]
## ID Zona piso Estrato precio_millon Area_contruida parqueaderos Banos
## 472 863 Zona Sur 4 4 128 55 1 1
## Habitaciones Tipo Barrio cordenada_longitud Cordenada_latitud
## 472 2 Apartamento colseguros -76.504 3.4
## parqueaderos_cat Banos_cat Habitaciones_cat
## 472 1 1 2
require(plotly)
graph1=ggplot(data = datos_sub_colse,aes(y=precio_millon,x=Area_contruida)) + geom_point() + geom_smooth()
ggplotly(graph1)
Gracias al anterior gráfico interactivo, se puede observar una relación en su mayoria directa entre el area construida y el precio del apartamento,aunque no se es una tendencia completamente marcada.
Es por esto que no se establece un punto claro, en el cual la tendencia cambie, y se decide hacer un filtro en el cual se calcula la mediana del precio de los apartamentos.
mediana=quantile(datos_sub_colse$precio_millon, probs = 0.5)
mediana
## 50%
## 163
La mediana del precio de los apartamentos ubicados en el barrio colseguros es de 163 millones.
filter_area_construida=which(datos_sub_colse$Area_contruida>=mediana)
datos_sub_colse2=datos_sub_colse[filter_area_construida,]
graph2=ggplot(data = datos_sub_colse2,aes(y=precio_millon,x=Area_contruida)) + geom_point() + geom_smooth()
ggplotly(graph2)
Se observa que para las observaciones cuyo precio es mayor a 163 millones, no hay mucha diferencia en el area construida. Al parece se encuentran apartamentos que pueden tener un precio atípico, de mas de 390 millones que tiene una area construida menor.