En primer lugar, se importan las librerías con las que se trabajará: tidyverse, data.table, corrr, ggplot2, GGally y hrbtthemes.
library(tidyverse)
library(data.table)
library(corrr)
library(ggplot2)
library(GGally)
library(hrbrthemes)
library(modelr)
Como primer paso en la preparación de los datos, se procede a cargar el dataset con la función fread de la librerría data.table y se lo asigna a una variable.
A continuación se puede observar que este dataset consta de 388891 registros y 24 columnas.
dataset = fread("ar_properties.csv")
|--------------------------------------------------|
|==================================================|
dataset
Con el fin de conocer un poco mejor su estructura, se emplea la función summary de R base para ver qué tipo de información contiene cada columna.
Aquí se puede apreciar que, de los 24 atributos, 15 contienen información de tipo “caracter”; 8, de tipo “numérico” y uno contiene solamente missing values (l6).
De aquellos atributos numéricos, se obtienen también las medidas de posición (media, mediana, primer cuartil, tercer cuartil, mínimo y máximo) y la cantidad de datos faltantes (NAs).
summary(dataset)
id ad_type start_date end_date created_on lat lon l1 l2
Length:388891 Length:388891 Length:388891 Length:388891 Length:388891 Min. :-54.98 Min. :-105.27 Length:388891 Length:388891
Class :character Class :character Class :character Class :character Class :character 1st Qu.:-34.67 1st Qu.: -58.80 Class :character Class :character
Mode :character Mode :character Mode :character Mode :character Mode :character Median :-34.60 Median : -58.48 Mode :character Mode :character
Mean :-34.48 Mean : -59.37
3rd Qu.:-34.43 3rd Qu.: -58.40
Max. : 44.67 Max. : -41.90
NA's :50597 NA's :50597
l3 l4 l5 l6 rooms bedrooms bathrooms surface_total surface_covered
Length:388891 Length:388891 Length:388891 Mode:logical Min. : 1.0 Min. : -2.00 Min. : 1.00 Min. : -3.0 Min. : -139
Class :character Class :character Class :character NA's:388891 1st Qu.: 2.0 1st Qu.: 1.00 1st Qu.: 1.00 1st Qu.: 50.0 1st Qu.: 43
Mode :character Mode :character Mode :character Median : 3.0 Median : 2.00 Median : 1.00 Median : 91.0 Median : 70
Mean : 2.9 Mean : 2.16 Mean : 1.67 Mean : 458.3 Mean : 235
3rd Qu.: 4.0 3rd Qu.: 3.00 3rd Qu.: 2.00 3rd Qu.: 266.0 3rd Qu.: 142
Max. :40.0 Max. :390.00 Max. :20.00 Max. :200000.0 Max. :4000000
NA's :144668 NA's :230747 NA's :94136 NA's :74063 NA's :97854
price currency price_period title property_type operation_type
Min. :0.000e+00 Length:388891 Length:388891 Length:388891 Length:388891 Length:388891
1st Qu.:2.000e+04 Class :character Class :character Class :character Class :character Class :character
Median :9.400e+04 Mode :character Mode :character Mode :character Mode :character Mode :character
Mean :2.690e+05
3rd Qu.:2.250e+05
Max. :2.147e+09
NA's :21222
Dado que se observa una gran cantidad de atributos categóricos, se utiliza la función glimpse de la librería tidyverse, que permite visualizar de modo general qué valores contiene cada atributo
glimpse(dataset)
Observations: 388,891
Variables: 24
$ id [3m[38;5;246m<chr>[39m[23m "S0we3z3V2JpHUJreqQ2t/w==", "kMxcmAS8NvrynGBVbMOEaQ==", "Ce3ojF+ZTOkB8d+LI9dpxg==", "AUGpj3raGmOCiulSMGIBPA==", "m+MwZmJl3OoxmfWcB//sBA==", "pJRPrB5G8Jl…
$ ad_type [3m[38;5;246m<chr>[39m[23m "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propiedad", "Propieda…
$ start_date [3m[38;5;246m<chr>[39m[23m "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14"…
$ end_date [3m[38;5;246m<chr>[39m[23m "2019-06-14", "2019-04-16", "9999-12-31", "9999-12-31", "2019-07-09", "2019-08-08", "2019-07-10", "2019-06-14", "2019-04-29", "2019-07-10", "2019-04-29"…
$ created_on [3m[38;5;246m<chr>[39m[23m "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14", "2019-04-14"…
$ lat [3m[38;5;246m<dbl>[39m[23m -34.94331, -34.63181, NA, -34.65471, -34.65495, -32.93547, -34.65183, -34.91213, -34.60338, NA, -34.59005, NA, NA, NA, -39.05412, -39.05859, -34.59413, …
$ lon [3m[38;5;246m<dbl>[39m[23m -54.92966, -58.42060, NA, -58.79089, -58.78712, -60.68398, -58.65912, -54.84749, -58.43450, NA, -58.43672, NA, NA, NA, -67.39418, -67.58741, -58.44373, …
$ l1 [3m[38;5;246m<chr>[39m[23m "Uruguay", "Argentina", "Argentina", "Argentina", "Argentina", "Argentina", "Argentina", "Uruguay", "Argentina", "Argentina", "Argentina", "Argentina", …
$ l2 [3m[38;5;246m<chr>[39m[23m "Maldonado", "Capital Federal", "Bs.As. G.B.A. Zona Norte", "Bs.As. G.B.A. Zona Oeste", "Bs.As. G.B.A. Zona Oeste", "Santa Fe", "Bs.As. G.B.A. Zona Oest…
$ l3 [3m[38;5;246m<chr>[39m[23m "Punta del Este", "Boedo", NA, "Moreno", "Moreno", "Rosario", "Ituzaingó", "José Ignacio", "Almagro", "Miramar", "Palermo", "Roldán", "Roldán", "Rosario…
$ l4 [3m[38;5;246m<chr>[39m[23m NA, NA, NA, "Moreno", "Moreno", NA, "Ituzaingó", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ l5 [3m[38;5;246m<chr>[39m[23m NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ l6 [3m[38;5;246m<lgl>[39m[23m NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ rooms [3m[38;5;246m<int>[39m[23m 2, NA, 2, 2, 2, 4, NA, 6, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, NA, NA, NA, NA, NA, NA, NA…
$ bedrooms [3m[38;5;246m<int>[39m[23m NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ bathrooms [3m[38;5;246m<int>[39m[23m 1, NA, 1, 2, 3, 1, 3, 3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 1, NA, 2, 5, 5, 5, 5, 5…
$ surface_total [3m[38;5;246m<int>[39m[23m 45, NA, 200, 460, 660, NA, 70, NA, 1300, 405, 352, 373, 360, 1325, 250, 80142, 101, NA, 54, 180, 36, 36, 40, 43, 40, 40, 36, 36, 36, 36, 43, 43, 36, 37,…
$ surface_covered [3m[38;5;246m<int>[39m[23m 40, NA, NA, 100, 148, 89, 122, NA, NA, NA, NA, NA, NA, 2, NA, NA, NA, NA, 54, 180, 33, 33, 34, 34, 34, 34, 33, 33, 33, 33, 34, 34, 33, 32, 97, 50, NA, N…
$ price [3m[38;5;246m<int>[39m[23m 13000, 0, NA, NA, NA, NA, NA, NA, 0, NA, 0, NA, NA, NA, NA, NA, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NA, NA, NA, NA, NA, 0, 0, 0, 0…
$ currency [3m[38;5;246m<chr>[39m[23m "UYU", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ price_period [3m[38;5;246m<chr>[39m[23m "Mensual", "Mensual", NA, "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", "Mensual", NA, "…
$ title [3m[38;5;246m<chr>[39m[23m "Departamento - Roosevelt", "PH - Boedo", "Ituzaingo 1100 - $ 1 - Casa Alquiler", "Dr. Vera 300 - Consulte precio - Casa en Venta", "L. N. Alem 240…
$ property_type [3m[38;5;246m<chr>[39m[23m "Departamento", "PH", "Casa", "Casa", "Casa", "Casa", "Casa", "Casa", "Lote", "Lote", "Lote", "Lote", "Lote", "Lote", "Lote", "Lote", "Lote", "Oficina",…
$ operation_type [3m[38;5;246m<chr>[39m[23m "Alquiler", "Venta", "Alquiler", "Venta", "Venta", "Venta", "Venta", "Alquiler", "Venta", "Venta", "Venta", "Venta", "Venta", "Venta", "Venta", "Venta",…
De lo observado, se puede realizar la siguiente descripción de cada atributo:
Dado que solo se trabajará con las propiedades en venta que correspondan a casas, departamentos o PHs que se encuentren ubicados en Capital Federal (Argentina) y cuyo precio se exprese en dólares (USD), se procede a filtrar del dataset para que muestre los registros deseados.
Para ello se utiliza la función filter del paquete dplyr importado junto a tidyverse.
Asimismo, se emplea la función select del mismo paquete para seleccionar los atributos de interés para este trabajo: id, l3, rooms, bedrooms, bathrooms, surface_total, surface_covered, price y property_type.
Se obtiene una dataset de 61905 registros y 9 atributos y se lo asigna a una nueva varibale.
dataset_filtrado <- dataset %>%
filter(l1 == 'Argentina',
l2 == 'Capital Federal',
currency == 'USD',
property_type %in% c('Departamento','PH','Casa'),
operation_type == 'Venta') %>%
select(id, l3, rooms, bedrooms, bathrooms, surface_total, surface_covered, price, property_type)
dataset_filtrado
En un primer análisis exploratorio, se verifica la cantidad de valores faltantes y de valores únicos en cada atributo.
Para obtener la cantidad de valores únicos se utiliza la función summarise_all de paquete dplyr que permite aplicar una misma función a todas las columnas del dataset. En este caso, se le aplica la función n_distinct que devuelve la cantidad de valores distintos en cada atributo.
unique_values <- dataset_filtrado %>%
summarise_all(n_distinct)
unique_values
En el caso de los valores faltantes, se aplica la función is.na de R base sobre el dataset filtrado para obtener una máscara booleana que indique si en cada celda hay un NA o no. Luego, por columna, se suman las filas que sí tienen un NA (que resultaron TRUE para la función aplicada). Para una mejor visualización, se transpone la información obtenida y se la muestra en un data frame.
na_values <- dataset_filtrado %>%
is.na() %>%
colSums() %>%
t() %>%
as.data.frame()
na_values
Con el propósito de cotejar si existe alguna correlación entre la variables numéricas, se realiza una matriz de correlación de las mismas y se la grafica con la función rplot del paquete ggplot2.
Para calcular la correlación se utiliza el coeficiente de correlación de Pearson y se toman en cuenta solamente los registros completos. Esto último se realiza mediante el parámetro “complete.obs”.
dataset_filtrado %>%
select_if(is.numeric) %>%
correlate(use="complete.obs") %>%
shave() %>%
fashion()
Correlation method: 'pearson'
Missing treated using: 'complete.obs'
dataset_filtrado %>%
select_if(is.numeric) %>%
correlate(use="complete.obs") %>%
rplot(colours = c('#003366','#3399FF','#FF3300')) +
geom_point(size=5) +
labs(title = 'Correlograma de variables') +
theme(axis.text.x = element_text(angle = 45, hjust=1))
Correlation method: 'pearson'
Missing treated using: 'complete.obs'
El análisis exploratorio realizado en el apartado anterior se halló que las variables dormitorios (bedrooms) y habitaciones (rooms) presentan una alta correlacionadas positiva (con un valor de 0.92). Esto significa que cuando los valores de una aumentan, los de la otra también lo hacen. De este modo, la información que ofrecen es, en cierto sentido, redundante. Esto permite optar por remover una de dichas variables y, debido a que dormitorios demostró tener gran cantidad de valores faltantes, se quita esta variable del dataset.
Para no tener mayores inconvenientes con el resto de los registros, se decide asimismo quitar aquellos que contengan valores faltantes, preservando solamente los registros completos.
Como resultado, se obtiene un dataset con 8 variables y 51210 registros.
dataset_sin_NA <- dataset_filtrado %>%
select(-c(bedrooms)) %>%
na.omit()
dataset_sin_NA
Se realiza un nuevo análisis exploratorio, ahora utilizando el dataset sin faltantes, obtenido en la sección 3.
A continuación, se ofrece una exploración más detallada sobre la variable precio (price) y su relación con el atributo tipo de propiedad (property_type).
Asimismo, se realiza un nuevo correlograma con el dataset sin faltantes.
Mediante la función summary se obtienen las medidad de posición de la variable precio.
Aquí, se ve que su valores pueden tomar un máximo de 6000000 y un mínimo de 6000 o, lo que es lo mismo, que su rango es de 5994000.
Los cuartiles son 119000 (primer cuartil) y 270000 (tercer cuartil), lo que indica una distancia intercuartil de 151000.
Y se observa una media de 251577 y una mediana de 170000. Es decir que la media es mayor que la mediana, lo que nos hace suponer una distribución asimétrica a derecha.
dataset_sin_NA %>%
select(price) %>%
summary()
price
Min. : 6000
1st Qu.: 119000
Median : 170000
Mean : 251577
3rd Qu.: 270000
Max. :6000000
Se realiza un histograma que permita visualizar más claramente esta información.
dataset_sin_NA %>%
ggplot(aes(x=price)) +
geom_histogram(fill="#69b3a2", color="#e9ecef", bins = 227, binwidth = 26429) +
#ggtitle("Histograma de precios") +
labs(title='Histograma de precios',
x = 'Precios (USD)',
y = 'Frecuencia') +
theme_minimal()
Como se anticipó, la variable presenta una distribución asimétrica a derecha.
Se realiza además un conteo de frecunecia relativa y frecuencia relativa acumulada con el fin de verificar los datos del gráfico. Como resultado, se encuentra que el 50% de los registros se concentra en apenas el 2% de los valores observados, y que la mayoría de estos valores se encuentran por debajo de los 350000.
frec <- count(dataset_sin_NA, price) %>%
mutate(frec = n/nrow(dataset_sin_NA)*100) %>%
arrange(desc(frec)) %>%
mutate(frec_acum = cumsum(frec),
id = 1:nrow(.)) %>%
select(id, everything())
frec
En vistas de amplio rango de precios observado, se busca obtener métricas de posición de esta variable agrupándola por tipo de propiedad para verificar si existe algún patrón relacionado.
dataset_sin_NA %>%
group_by(property_type) %>%
summarise(mín = min(price),
Q1 = quantile(x = price, probs = 0.25, names = FALSE),
mediana = median(price),
media = mean(price),
Q3 = quantile(x = price, probs = 0.75, names = FALSE),
máx = max(price))
De estas medidas se puede extraer que el tipo de propiedad Departamento es el que presenta el mayor rango de valores y el tipo de propiedad PH, el menor.
De hecho, si bien el tipo de propiedad Departamento muestra una media y una mediana similares a las del tipo de propiedad PH, dado que también evidencia un rango considerablemente mayor, es de esperar que las colas de su distribución sean más livianas que las de la distribución del tipo de propiedad PH.
El tipo de propiedad Casa, por su parte, posee una media y una mediana mayor a las de ambos atributos ya mencionados.
A continuación, se grafica un boxplot que facilite la visualización de estos datos. Previamente, se convierten los valores de la variable tipo de propiedad en factores.
ggdata <- dataset_sin_NA %>%
select(property_type, price) %>%
mutate(property_type = as.factor(property_type))
ggplot(ggdata, aes(x = property_type, y = price, group = property_type, fill = property_type)) +
geom_boxplot() +
labs(title='Precio por tipo de propiedad',
x = 'Tipos de propiedad',
y = 'Precio (USD)')
Si bien el boxplot confirma las suposiciones anteriores, también muestra que no es posible utilizarlo para encontrar valores atípicos, dado que hay una gran cantidad de datos que caen por fuera de los bigotes y que no se encuentran aislados o separados del resto.
Se realiza un nuevo correlograma de variable con el dataset sin datos faltantes. Esta vez se utiliza la función ggcorr de la librería GGAlly.
dataset_sin_NA %>%
select_if(is.numeric) %>%
ggcorr(method = c("complete.obs","pearson"),
low = '#e0f3db',
mid = '#a8ddb5',
high = '#43a2ca',
label = TRUE,
label_color = "black",
nbreaks = 5,
hjust = 0.75,
legend.position = "left") +
labs(title = "Propiedades en venta en CABA - Correlograma")
Este gráfico muestra una fuerte correlación positiva entre la variable superficie cubierta (surface_covered) y superficie total (surface_total). Desde el sentido común, esto resulta esperable en las propiedades de Capital Federal, dado que muchas veces ambas superficies coinciden y, cuando no lo hacen, es infrecuente que se deba a que la propiedad tiene una superficie descubierta mayor que la cubierta (caso en el que la superficie total aumentaría pero la superficie cubierta no).
También resulta esperable la correlación observada entre habitaciones y baños (bathrooms), pues suele ocurrir que, a medida que la primera aumenta, la segunda también lo hace.
Quizá sí pueda ser curioso el hecho de que, si bien estas útimas dos variables se correlacionan de manera semejante con el precio, la cantidad de baños exhibe, aunque muy leve, una mayor correlación, dando lugar a la sospecha de que la cantidad de baños aumenta en mayor medida la cotizaicón de una propiedad (en comparación con la cantidad de habitaciones).
En vistas del amplio rango de la variable precio, se propone remover los valores atípicos.
Para ello, se ordenan los datos de manera creciente y se los grafica en un scatterplot con el fin de encontrar si existe algún punto de corte a partir del cual se observen outliers.
sort(dataset_sin_NA$price, decreasing = FALSE) %>%
plot(main = "Scatterplot de precios",
xlab = "Índice",
ylab = "Precios",
col = "#43a2ca")
Si bien no parece haber un punto de corte claro, se intenta estableciendo el límite en 3000000, se filtran todos los precios menores a ese valor y se obtienen nuevas medidas de posición para evaluar el impacto de esta decisión.
dataset_sin_NA %>%
filter(price < 3000000) %>%
select(price) %>%
summary()
price
Min. : 6000
1st Qu.: 119000
Median : 170000
Mean : 245391
3rd Qu.: 270000
Max. :2975000
Aunque el rango de los valores obtenidos es menor, aún se observa una alta variación entre un extremo y otro. Se propone entonces eliminar los valores que se encuentren a 1.5 rangos intercuartiles del primer y tercer cuartil.
Para esto se buscan primero el rango intercuartil y los cuartiles de precios y se los asignado a una variable. Luego, se establece como corte mínimo el punto que se ubica a 1.5 veces el rango intercuartil por debajo del primer cuartil, y se hace lo mismo con el corte máximo, solo que ubicándolo por encima del tercer cuartil. Finalmente, se filtra el dataset y se almacenan solamente los registros cuyo precio esté por encima del corte mínimo y por debajo del corte máximo.
data.riq <- IQR(dataset_sin_NA$price)
cuantiles<-quantile(dataset_sin_NA$price, c(0.25, 0.5, 0.75), type = 7)
outliers_min<-as.numeric(cuantiles[1])-1.5*data.riq
outliers_max<-as.numeric(cuantiles[3])+1.5*data.riq
dataset_sin_outliers <- dataset_sin_NA %>%
filter(price > outliers_min,
price < outliers_max)
dataset_sin_outliers
Se procede a realizar el mismo análisis desarrollado en el apartado 4 pero utilizando el dataset sin faltantes y sin valores atípicos.
Se calculan nuevamente las medidas de posición.
dataset_sin_outliers %>%
select(price) %>%
summary()
price
Min. : 6000
1st Qu.:115000
Median :160000
Mean :187634
3rd Qu.:240000
Max. :496000
Se observa que el valor mínimo se mantiene, mientras que el máximo ha disminuido considerablemente hasta un valor que presenta la misma cantidad de dígitos que la media.
Asimismo, la media y la mediana se han aproximado. Sin embargo, en tanto la primera constinúa siendo mayor que la segunda, cabe esperar que la distribución de la variable siga siendo asimétrica a derecha. Se confirma esto con un nuevo histograma.
dataset_sin_outliers %>%
ggplot(aes(x=price)) +
geom_histogram(fill="#69b3a2", color="#e9ecef",bins = 100) +
labs(title='Histograma de precios',
subtitle = 'Valores atípicos eliminados',
x = 'Precios (USD)',
y = 'Frecuencia') +
theme_minimal()
El haber filtrado los valores atípicos ha facilitado la visualización de la información, peritiendo observar más claramente el intervalo en el cual se concentra la mayor cantidad de datos.
De todos modos, se mantiene constante el hecho de que aproximadamente el 2% de los precios observados represente al 50% de las propiedades del dataset.
count(dataset_sin_outliers, price) %>%
mutate(frec = n/nrow(dataset_sin_outliers)*100) %>%
arrange(desc(frec)) %>%
mutate(frec_acum = cumsum(frec),
id = 1:nrow(.)) %>%
select(id, everything())
Se replica la obtención de medidas de posición de la variable precio agrupada de acuerdo a la variable tipo de propiedad.
dataset_sin_outliers %>%
group_by(property_type) %>%
summarise(mín = min(price),
Q1 = quantile(x = price, probs = 0.25, names = FALSE),
mediana = median(price),
media = mean(price),
Q3 = quantile(x = price, probs = 0.75, names = FALSE),
máx = max(price))
Si bien persiste el hecho de que el tipo de propiedad Departamento presente el mayor rango entre sus valores, ahora los tres tipos de propiedad exhiben valores máximos muy similares. Esto era esperable dada la remoción previa de valores atípicos, en la cual se estableció una cota superior e inferior y se filtraron los valores por encima y por debajo respectivamente. En tanto no existían valores menores a la cota inferior, el mínimo se mantuvo. El máximo, en cambio, se vio reducido al límite superior establecido.
La media y la mediana del tipo de propiedad Departamento sigue siendo similar a las del tipo de propiedad PH aunque en ambos casos las distancias entre estas dos medidas se ha acortado.
Esto también ha ocurrido con la media y la mediana del tipo de propiedad Casa, donde ambas medidas se han aproximado de manera más notable. Si se agrega a este dato el hecho de que, como producto de la poda de outliers, este grupo presente menor dispersión, se podría suponer que su distribución ya no debería se asimétrica o, al menos, no de forma tan marcada.
Se cotejan estos supuestos con un nuevo boxplot. Igual que se hizo anteriormente, se convierten los valores de la variable tipo de propiedad en factores para poder realizar el gráfico.
ggdata_sin_out <- dataset_sin_outliers %>%
mutate(property_type = as.factor(property_type))
ggplot(ggdata_sin_out, aes(x = property_type, y = price, group = property_type, fill = property_type)) +
geom_boxplot() +
labs(title='Precio por tipo de propiedad',
subtitle = 'Valores atípicos eliminados',
x = 'Tipos de propiedad',
y = 'Precio (USD)')
Nuevamete, se grafica un correlograma que evidencie la relación entre las variables del dataset sin faltantes ni datos atípicos.
dataset_sin_outliers %>%
select_if(is.numeric) %>%
ggcorr(method = c("complete.obs","pearson"),
low = '#e0f3db',
mid = '#a8ddb5',
high = '#43a2ca',
label = TRUE,
label_color = "black",
nbreaks = 5,
hjust = 0.75,
legend.position = "left") +
labs(title = "Propiedades en venta en CABA - Correlograma",
subtitle = "Valores atípicos eliminados")
Al igual que se observó anteriormente, la variable superficie total y superficie cubierta son las que se encuentran más correlacionadas en un sentido positivo.
Lo que ha camiado es que ya no son las variables habitaciones y baños las que le siguen en orden de correlación, sino que ahora son las correlaciones de baño y precio y de habitaciones y precio las que ocupan el segundo lugar, ambas con una correlación apenas superior a 0.6.
Esto demuestra que, si bien la remoción de datos faltantes no tuvo mayores consecunecias en el dataset utilizado, tampoco fue inocuo. Previamente a realizar este procesamiento, las variables más correlacionadas luego de superficie total y superficie cubierta eran habitaciones y baños, por un lado, y precio y baño, por otro. La correlación entre dormitorios y precio se encontraba recién en un tercer lugar.
Ahora, además de haber modificado sus órdenes, esta últimas tres correlaciones se han aproximado entre sí.
Se realizan dos modelos lineales con el fin de poder predecir el precio en función de otra variable.
En este primer modelo, se busca explicar el precio en función de la variable habitaciones (rooms). Primero se seleccionan los atributos a utilizar y luego se ajusta el modelo.
Mediante la función summary se extraen los coficientes estimados para la recta generada por el modelo:
data.model1 <- dataset_sin_outliers %>%
select(price, rooms)
mod1 <- lm(price ~ rooms, data = data.model1)
summary(mod1)
Call:
lm(formula = price ~ rooms, data = data.model1)
Residuals:
Min 1Q Median 3Q Max
-710329 -46904 -11781 33219 370504
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 57218.9 821.3 69.67 <2e-16 ***
rooms 49561.7 282.7 175.29 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 75360 on 46950 degrees of freedom
Multiple R-squared: 0.3956, Adjusted R-squared: 0.3956
F-statistic: 3.073e+04 on 1 and 46950 DF, p-value: < 2.2e-16
En un segundo modelo, se busca explicar el precio en función de la variable superficie total (surface_total). Nuevamente, se seleccionan los atributos a utilizar y luego se ajusta el modelo.
Del mismo modo que se hizo anteriormente, se extraen los coficientes estimados:
data.model2 <- dataset_sin_outliers %>%
select(price, surface_total)
mod2 <- lm(price ~ surface_total, data = data.model2)
summary(mod2)
Call:
lm(formula = price ~ surface_total, data = data.model2)
Residuals:
Min 1Q Median 3Q Max
-609854 -72458 -27592 52385 308340
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.872e+05 4.494e+02 416.568 <2e-16 ***
surface_total 5.058e+00 5.270e-01 9.599 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 96840 on 46950 degrees of freedom
Multiple R-squared: 0.001959, Adjusted R-squared: 0.001938
F-statistic: 92.15 on 1 and 46950 DF, p-value: < 2.2e-16
De los modelos anteriormente ajustado, el modelo 1, que intenta explicar el precio de una propiedad en función de la cantidad de habitaciones que posee, parece ser el más adecuado.
Si bien ninguno de los modelos exhibe un residuo con una mediana 0 o cercana a 0, lo que sería deseable puesto que eso significa que la diferencia entre los datos observados y los predichos presenta una distribución simétrica y da cuenta de cuánto se ajusta el modelo a los datos, la mediana de los residuos del modelo 1 presenta una menor distancia al 0 que la mediana del modelo 2.
Además, aunque los desvíos estándares de los coeficientes del primer modelo son mayores en términos absolutos, cuando se los relaciona con los coeficientes estimados, resultan valores proporcionalmente menores a los exhibidos por el modelo 2.
Por último, el t valor observado entre la variable habitaciones y precio es mayor que el que existe entre superficie total y precio, sugiriendo que la primera relación es más estrecha.