library(tidyverse)
library(skimr)
library(gt)
library(summarytools)
library(ggplot2)
library(corrplot)
library(patchwork)
library(rstatix)
library(gtsummary)
library(janitor)
library(naniar)
library(visdat)
library(DataExplorer)
library(scales)
library(knitr)
library(kableExtra)
library(tidymodels)
library(lubridate)Projeto de Disciplina 26.1
Análise Exploratória de Dados
1 Carregando os pacotes
2 Carregando os dados
Base de dados baixada do Kaggle: https://www.kaggle.com/datasets/allanbruno/airbnb-rio-de-janeiro
dez19 = read_csv("dados/dezembro2019.csv")
jan20 = read_csv("dados/janeiro2020.csv")
fev20 = read_csv("dados/fevereiro2020.csv")
mar20 = read_csv("dados/maro2020.csv")
abr20 = read_csv("dados/abril2020.csv")
maio20 = read_csv("dados/maio2020.csv")2.1 Descrição das bases de dados
Reúnem informações dos imóveis disponíveis para locação pelo Airbnb no Rio de Janeiro, do período de dezembro de 2019 até maio de 2020.
Possuem 108 colunas, que descrevem desde o preço e o período de disponibilidade de locação até detalhes sobre o host (dono) e do próprio imóvel.
O dicionário dos dados pode ser encontrado no seguinte link: https://docs.google.com/spreadsheets/d/1iWCNJcSutYqpULSQHlNyGInUvHg2BoUGoNRIGa6Szc4/edit?gid=1322284596#gid=1322284596
3 Objetivo da análise
O objetivo da presente análise consiste em identificar as variáveis que mais influenciaram o preço cobrado na locação de imóveis em anúncios do Airbnb no Rio de Janeiro no período da base de dados.
A escolha por este tema de estudo se deu por uma curiosidade pessoal minha acerca da cidade onde moro desde nasci.
4 Limpeza dos dados
4.1 Construção de base única
Para facilitar o trabalho de limpeza e análise, as 6 bases serão unificadas em uma, com adição de uma coluna do mês e ano correspondente.
dez19 = dez19 |>
mutate(mes = "2019-12")
jan20 = jan20 |>
mutate(mes = "2020-01")
fev20 = fev20 |>
mutate(mes = "2020-02")
mar20 = mar20 |>
mutate(mes = "2020-03")
abr20 = abr20 |>
mutate(mes = "2020-04")
maio20 = maio20 |>
mutate(mes = "2020-05")df_raw = bind_rows(dez19, jan20, fev20, mar20, abr20, maio20)4.2 Visão geral
# skim(df_raw)Variável de interesse:
price, que determina o preço de aluguel dos imóveis.
A base df_raw possui muitas variáveis descartáveis para a análise no meio dela, como listing_url, last_scraped, host_thumbnail_url, entre outras.
Sendo assim, abaixo serão selecionadas somente as variáveis que, de fato, podem ter alguma influência no preço do aluguel de um imóvel:
df_clean = df_raw |>
select(
price,
room_type,
accommodates,
bedrooms,
bathrooms,
neighbourhood_cleansed,
number_of_reviews,
review_scores_rating,
minimum_nights,
host_is_superhost,
property_type,
mes,
guests_included
)4.3 Investigação inicial
df_clean |>
select(where(is.numeric), where(is.factor)) |>
tbl_summary(
statistic = list(
all_continuous() ~ "{median} ({p25}, {p75})",
all_categorical() ~ "{n} ({p}%)"
),
digits = all_continuous() ~ 2
) |>
modify_header(label ~ "**Variável**") |>
modify_spanning_header(all_stat_cols() ~ "**Resumo Geral**") |>
modify_caption("**Tabela 1. Estatística descritiva das variáveis da base de dados**") |>
bold_labels()| Variável |
Resumo Geral
|
|---|---|
| N = 213,5141 | |
| accommodates | 4.00 (2.00, 5.00) |
| bedrooms | 1.00 (1.00, 2.00) |
| Unknown | 389 |
| bathrooms | 1.00 (1.00, 2.00) |
| Unknown | 374 |
| number_of_reviews | 1.00 (0.00, 6.00) |
| review_scores_rating | 98.00 (93.00, 100.00) |
| Unknown | 95,105 |
| minimum_nights | 2.00 (1.00, 4.00) |
| guests_included | 1.00 (1.00, 2.00) |
| 1 Median (Q1, Q3) | |
Há mais de 200 mil observações na nossa base. Nesta primeira descrição geral, destacam-se as seguintes medianas e IQRs de características dos imóveis colocados para locação pelo Airbnb no período de dezembro de 2019 até maio de 2020 no Rio de Janeiro:
Quantidade máxima de pessoas acomodadas (
accommodates): 4 (IQR = 2, 5)Quantidade de reviews (
number_of_reviews): 1 (IQR = 0, 6)Notas das reviews (
review_scores_rating): 98 (IQR = 93, 100)Quantidade mínima de noites a serem alugadas (
minimum_nights): 2 (IQR = 1, 4)
Preço (price) não apareceu na lista, o que indica que a variável deve estar erroneamente classificada como categórica.
4.3.1 Tipagem de variáveis
Identificando os tipos de variáveis presentes na base:
df_clean |>
summarise(across(everything(), class)) |>
pivot_longer(everything(),
names_to = "variavel",
values_to = "tipo") |>
count(tipo, sort = TRUE) |>
kbl(col.names = c("Tipo", "Quantidade"), align = "lr") |>
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE)| Tipo | Quantidade |
|---|---|
| numeric | 7 |
| character | 5 |
| logical | 1 |
A base possui o total de 13 variáveis, sendo 7 numéricas, 5 categóricas e 1 lógica.
Checando quais variáveis numéricas são, de fato, numéricas:
df_clean |>
select(where(is.numeric)) |>
glimpse()Rows: 213,514
Columns: 7
$ accommodates <dbl> 5, 2, 3, 2, 2, 13, 1, 10, 3, 6, 12, 2, 6, 4, 6, 4…
$ bedrooms <dbl> 2, 1, 1, 1, 1, 6, 1, 4, 1, 4, 4, 0, 4, 1, 3, 3, 0…
$ bathrooms <dbl> 1.0, 1.0, 1.0, 1.5, 1.0, 7.0, 1.0, 3.5, 1.0, 3.0,…
$ number_of_reviews <dbl> 246, 236, 274, 171, 320, 64, 42, 3, 79, 71, 7, 16…
$ review_scores_rating <dbl> 93, 94, 96, 94, 98, 92, 98, 80, 93, 91, 91, 95, 9…
$ minimum_nights <dbl> 4, 7, 2, 2, 3, 2, 3, 4, 3, 3, 1, 3, 7, 5, 2, 4, 3…
$ guests_included <dbl> 2, 2, 2, 2, 2, 7, 1, 8, 2, 4, 1, 2, 5, 2, 3, 2, 2…
review_scores_rating: variável de nível de qualidade percebida = ambíguo (pode ser tanto numérica quanto fator)bathrooms: variável que carrega informação dupla (quantidade de banheiros completos e lavabos) = será mantida como variável numérica única, pois as informações fazem sentido quando unificadas e facilitam a análiseacommodates,bedrooms,number_of_reviews,minimun_nightseguests_included: variáveis de contagem = numéricas inteiras
Tratando as variáveis:
df_clean = df_clean |>
mutate(
across(
c(accommodates, bedrooms, number_of_reviews,
minimum_nights, guests_included),
as.integer
)
)OBS: Optou-se por manter a variável review_scores_rating como numérica (dbl), por representar uma escala contínua de qualidade, preservando maior nível de informação.
Checando quais variáveis categóricas são, de fato, categóricas:
df_clean |>
select(where(is.character)) |>
glimpse()Rows: 213,514
Columns: 5
$ price <chr> "$323.00", "$159.00", "$266.00", "$368.00", "$1…
$ room_type <chr> "Entire home/apt", "Entire home/apt", "Entire h…
$ neighbourhood_cleansed <chr> "Copacabana", "Copacabana", "Ipanema", "Ipanema…
$ property_type <chr> "Condominium", "Apartment", "Apartment", "Apart…
$ mes <chr> "2019-12", "2019-12", "2019-12", "2019-12", "20…
price: variável de preço = numéricames: variável de mês = data
Tratando as variáveis:
# Tratando price
df_clean = df_clean |>
mutate(price = parse_number(price))# Tratando mes
df_clean = df_clean |>
mutate(mes = ymd(paste0(mes, "-01")))Verificando tipagem final das variáveis:
df_clean |>
glimpse()Rows: 213,514
Columns: 13
$ price <dbl> 323, 159, 266, 368, 131, 3492, 78, 851, 184, 90…
$ room_type <chr> "Entire home/apt", "Entire home/apt", "Entire h…
$ accommodates <int> 5, 2, 3, 2, 2, 13, 1, 10, 3, 6, 12, 2, 6, 4, 6,…
$ bedrooms <int> 2, 1, 1, 1, 1, 6, 1, 4, 1, 4, 4, 0, 4, 1, 3, 3,…
$ bathrooms <dbl> 1.0, 1.0, 1.0, 1.5, 1.0, 7.0, 1.0, 3.5, 1.0, 3.…
$ neighbourhood_cleansed <chr> "Copacabana", "Copacabana", "Ipanema", "Ipanema…
$ number_of_reviews <int> 246, 236, 274, 171, 320, 64, 42, 3, 79, 71, 7, …
$ review_scores_rating <dbl> 93, 94, 96, 94, 98, 92, 98, 80, 93, 91, 91, 95,…
$ minimum_nights <int> 4, 7, 2, 2, 3, 2, 3, 4, 3, 3, 1, 3, 7, 5, 2, 4,…
$ host_is_superhost <lgl> TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALS…
$ property_type <chr> "Condominium", "Apartment", "Apartment", "Apart…
$ mes <date> 2019-12-01, 2019-12-01, 2019-12-01, 2019-12-01…
$ guests_included <int> 2, 2, 2, 2, 2, 7, 1, 8, 2, 4, 1, 2, 5, 2, 3, 2,…
Agora possuímos 18 variáveis, sendo:
room_type,neighbourhood_cleansedeproperty_type: categóricasprice,accommodates,bedrooms,bathrooms,number_of_reviews,review_scores_rating,minimum_nights,guests_included: numéricashost_is_superhost: lógicames: data
Tratando a variável lógica (transformando em categórica para facilitar ações futuras):
df_clean = df_clean |>
mutate(
host_is_superhost = factor(host_is_superhost,
levels = c(TRUE, FALSE),
labels = c("Sim", "Não"))
)Verificando tipagem final das variáveis:
df_clean |>
glimpse()Rows: 213,514
Columns: 13
$ price <dbl> 323, 159, 266, 368, 131, 3492, 78, 851, 184, 90…
$ room_type <chr> "Entire home/apt", "Entire home/apt", "Entire h…
$ accommodates <int> 5, 2, 3, 2, 2, 13, 1, 10, 3, 6, 12, 2, 6, 4, 6,…
$ bedrooms <int> 2, 1, 1, 1, 1, 6, 1, 4, 1, 4, 4, 0, 4, 1, 3, 3,…
$ bathrooms <dbl> 1.0, 1.0, 1.0, 1.5, 1.0, 7.0, 1.0, 3.5, 1.0, 3.…
$ neighbourhood_cleansed <chr> "Copacabana", "Copacabana", "Ipanema", "Ipanema…
$ number_of_reviews <int> 246, 236, 274, 171, 320, 64, 42, 3, 79, 71, 7, …
$ review_scores_rating <dbl> 93, 94, 96, 94, 98, 92, 98, 80, 93, 91, 91, 95,…
$ minimum_nights <int> 4, 7, 2, 2, 3, 2, 3, 4, 3, 3, 1, 3, 7, 5, 2, 4,…
$ host_is_superhost <fct> Sim, Não, Sim, Sim, Sim, Sim, Sim, Não, Não, Si…
$ property_type <chr> "Condominium", "Apartment", "Apartment", "Apart…
$ mes <date> 2019-12-01, 2019-12-01, 2019-12-01, 2019-12-01…
$ guests_included <int> 2, 2, 2, 2, 2, 7, 1, 8, 2, 4, 1, 2, 5, 2, 3, 2,…
Agora host_is_superhost é fator.
4.3.2 Tratamento de NAs
Identificando a proporção de NAs:
na.summary = df_clean |>
summarise(across(everything(), ~ mean(is.na(.)))) |>
pivot_longer(everything(),
names_to = "variavel",
values_to = "pct_na") |>
filter(pct_na > 0) |>
arrange(desc(pct_na)) |>
mutate(pct_na_fmt = percent(pct_na, accuracy = 0.1))
na.summary |>
kbl(col.names = c("Variável", "% NA", "% Formatada"), align = "lrr", caption = "Variáveis com valores ausentes") |>
kable_styling(bootstrap_options = c("striped", "hover"),
full_width = FALSE) |>
row_spec(which(na.summary$pct_na > 0.4), background = "#fa93b0")| Variável | % NA | % Formatada |
|---|---|---|
| review_scores_rating | 0.4454275 | 44.5% |
| bedrooms | 0.0018219 | 0.2% |
| bathrooms | 0.0017516 | 0.2% |
| host_is_superhost | 0.0006510 | 0.1% |
Visualização:
# Gerando amostragem para possibilitar a geração do gráfico
df_vis = df_clean |>
slice_sample(n = 5000)# Mapa Visual de NAs
vis_miss(
df_vis, sort_miss = TRUE
) +
labs(title = "Valores ausentes na base do Airbnb RJ",
subtitle = "Ordenado por proporção de missings") +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7))Observa-se que review_scores_rating é a única variável com mais de 1% de NAs (44,5%).
Analisando cada caso de NAs:
review_scores_ratingNAs = não há reviews para o imóvelbedroomsebathroomsNAs = números não especificados no anúnciohost_is_superhostNAs = não especificado no anúncio
Tratando os NAs:
- Para
review_scores_rating,bedrooms,bathrooms, foi imputada mediana:
df_clean = df_clean |>
mutate(
# rating
review_scores_rating = coalesce(
review_scores_rating,
median(review_scores_rating, na.rm = TRUE)
),
# variáveis estruturais
across(
c(bedrooms, bathrooms),
~ coalesce(., median(., na.rm = TRUE))
)
)- Para
host_is_superhost, foi imputada a moda:
moda_superhost = names(sort(table(df_clean$host_is_superhost), decreasing = TRUE))[1]
# Moda = "Não"df_clean = df_clean |>
mutate(
host_is_superhost = coalesce(host_is_superhost, moda_superhost)
)Checagem final da proporção de NAs da base de dados:
# Gerando amostragem para possibilitar a geração do gráfico
df_vis = df_clean |>
slice_sample(n = 5000)# Mapa Visual de NAs
vis_miss(
df_vis, sort_miss = TRUE
) +
labs(title = "Valores ausentes na base do Airbnb RJ",
subtitle = "Ordenado por proporção de missings") +
theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7))NAs foram totalmente removidos da base de dados.
4.3.3 Tratamento de outliers
Identificando outliers:
df_clean |>
ggplot(aes(y = price)) +
geom_boxplot(outlier.alpha = 0.3) +
scale_y_continuous(
labels = scales::label_dollar(
prefix = "R$ ",
big.mark = ".",
decimal.mark = ","
)
) +
theme_minimal()Observa-se que há outliers especialmente a partir de mais de R$ 70.000. Há outliers que ultrapassam R$ 125.000.
Identificando o IQR
q1 = quantile(df_clean$price, 0.25)
q3 = quantile(df_clean$price, 0.75)
iqr = q3 - q1
inferior = q1 - 1.5 * iqr
superior = q3 + 1.5 * iqrCaracterísticas de price:
Q1 = R$ 157
Q3 = R$ 611
IQR = R$ 454
Inferior = - R$ 524
Superior = R$ 1.292
Identificando quantos imóveis são muito caros:
df_clean |>
filter(price > superior) |>
nrow()[1] 22297
Temos o total de 22.297 imóveis acima do IQR superior. São muitas observações para cortarmos.
Investigando os outliers por bairro:
top_bairros = df_clean |>
count(neighbourhood_cleansed, sort = TRUE) |>
slice_head(n = 15) |>
pull(neighbourhood_cleansed)
df_clean |>
filter(neighbourhood_cleansed %in% top_bairros) |>
ggplot(aes(x = neighbourhood_cleansed, y = price)) +
geom_boxplot() +
scale_y_continuous(
labels = scales::label_dollar(
prefix = "R$ ",
big.mark = ".",
decimal.mark = ","
)
) +
labs(
title = "Distribuição de preço por bairro",
subtitle = "Bairros selecionados: top 20",
x = "Bairro",
y = "Preço"
) +
coord_flip() +
theme_minimal()Observa-se que Copacana é o bairro com 2 observações de extrema discrepância em relação ao restante.
Investigando estes outliers:
df_clean |>
filter(neighbourhood_cleansed == "Copacabana") |>
arrange(desc(price)) |>
select(price, accommodates, bedrooms, bathrooms, room_type, property_type) |>
head(5)# A tibble: 5 × 6
price accommodates bedrooms bathrooms room_type property_type
<dbl> <int> <int> <dbl> <chr> <chr>
1 138262 2 1 1 Private room Bed and breakfast
2 131727 2 1 1 Private room Bed and breakfast
3 57517 4 2 2 Entire home/apt Apartment
4 55305 4 2 3 Entire home/apt Apartment
5 54798 4 2 2 Entire home/apt Apartment
Os dois valores mais altos (R$ 138.262 e R$ 131.727) são relativos a quartos privativos em propriedades de categoria “Bed and breakfast”, com acomodação para 2 pessoas, 1 banheiro e 1 quarto. Há fortes indicativos de erro, uma vez que nem mesmo em hotéis de luxo encontramos esses valores para quartos.
Logo, estes outliers serão removidos, pois também destoam muito da concentração geral de valores.
df = df_clean |>
filter(price <= 60000)Checagem final de outliers:
df |>
ggplot(aes(y = price)) +
geom_boxplot(outlier.alpha = 0.3) +
scale_y_continuous(
labels = scales::label_dollar(
prefix = "R$ ",
big.mark = ".",
decimal.mark = ","
)
) +
theme_minimal()Agora todas as observações concentram-se em valores até R$ 60.000.
5 Análise Univariada
5.1 Variáveis numéricas
Descrição estatística da variável numérica price, após remoção de outliers:
df |>
select(price) |>
descr()Descriptive Statistics
df$price
N: 213510
price
----------------- -----------
Mean 701.89
Std.Dev 1930.32
Min 0.00
Q1 157.00
Median 298.00
Q3 611.00
Max 57517.00
MAD 260.94
IQR 454.00
CV 2.75
Skewness 12.92
SE.Skewness 0.01
Kurtosis 235.86
N.Valid 213510.00
N 213510.00
Pct.Valid 100.00
Trata-se de uma variável com mediana de R$ 298 e média de aproximadamente R$ 702, o que indica que pode se tratar de uma variável com assimetria à direita.
# Criando função para calcular normalidade
plot_normalidade = function(dados, var, bins = 30, xlim = NULL){
var_enquo = rlang::enquo(var)
vetor = dados |> dplyr::pull(!!var_enquo)
media = mean(vetor, na.rm = TRUE)
mediana = median(vetor, na.rm = TRUE)
p1 = dados |>
ggplot(aes(x = !!var_enquo)) +
geom_histogram(
aes(y = after_stat(density)),
bins = bins,
fill = "lightblue",
color = "black"
) +
geom_density(color = "darkblue", linewidth = 0.8, alpha = 0.3) +
theme_minimal() +
labs(
title = paste0("Distribuição - ", rlang::as_name(var_enquo)),
x = rlang::as_name(var_enquo),
y = "Densidade"
)
# aplicar limite do eixo x se for especificado
if(!is.null(xlim)){
p1 = p1 + coord_cartesian(xlim = xlim)
}
p2 = dados |>
ggplot(aes(sample = !!var_enquo)) +
stat_qq(size = 2, alpha = 0.6) +
stat_qq_line(color = "red", linewidth = 1) +
theme_minimal() +
labs(
title = paste0("QQ plot - ", rlang::as_name(var_enquo)),
x = "Quantis teóricos",
y = "Quantis amostrais"
)
p1 + p2
}df |>
plot_normalidade(price, bins = 300, xlim = c(0, 10000))OBS: A quantidade de bins escolhida para o histograma foi o valor encontrado que melhor permite a visualização da distribuição das observações.
Os gráficos acima indicam que, como esperado, a variável price não segue distribuição normal. Trata-se de uma variável assimétrica à direita. Ou seja, a maioria dos preços se concentram em valores abaixo de R$ 1.000, tendo poucas observações com valores extremos. O IQR de R$ 454 (R$ 157 - R$ 611) descreve a variabilidade dos preços mais comuns sem grande influência de valores extremos.
Descrição estatística da variável review_scores_rating:
df |>
select(review_scores_rating) |>
descr()Descriptive Statistics
df$review_scores_rating
N: 213510
review_scores_rating
----------------- ----------------------
Mean 96.11
Std.Dev 7.28
Min 20.00
Q1 97.00
Median 98.00
Q3 99.00
Max 100.00
MAD 1.48
IQR 2.00
CV 0.08
Skewness -5.27
SE.Skewness 0.01
Kurtosis 38.83
N.Valid 213510.00
N 213510.00
Pct.Valid 100.00
Trata-se de uma variável com mediana de 98 e média de aproximadamente 96, o que indica que pode se tratar de uma variável com assimetria à esquerda.
df |>
plot_normalidade(review_scores_rating, bins = 120)OBS: A quantidade de bins escolhida para o histograma foi o valor encontrado que melhor permite a visualização da distribuição das observações.
Os gráficos acima indicam que, como esperado, a variável review_scores_rating não segue distribuição normal. Trata-se de uma variável assimétrica à esquerda. Ou seja, a maioria das notas se concentram em valores acima de 90, tendo poucas observações com notas baixas. O IQR de 2 (97, 99) comprova a baixa variabilidade de notas.
Descrição estatística da variável number_of_reviews:
df |>
select(number_of_reviews) |>
descr()Descriptive Statistics
df$number_of_reviews
N: 213510
number_of_reviews
----------------- -------------------
Mean 9.69
Std.Dev 25.55
Min 0.00
Q1 0.00
Median 1.00
Q3 6.00
Max 401.00
MAD 1.48
IQR 6.00
CV 2.64
Skewness 5.23
SE.Skewness 0.01
Kurtosis 37.63
N.Valid 213510.00
N 213510.00
Pct.Valid 100.00
Trata-se de uma variável com mediana de 1 e média de aproximadamente 10, o que indica que pode se tratar de uma variável com assimetria à direita.
df |>
plot_normalidade(number_of_reviews, bins = 50, xlim = c(0, 100))OBS: A quantidade de bins escolhida para o histograma foi o valor encontrado que melhor permite a visualização da distribuição das observações.
Os gráficos acima indicam que, como esperado, a variável number_of_reviews não segue distribuição normal. Trata-se de uma variável assimétrica à direita. Ou seja, a maioria dos anúncios possuem menos de 1 review, sendo poucos os anúncios com maior quantidade de avaliações. O IQR de 6 (0, 6) descreve a variabilidade das quantidades de reviews por anúncio mais comuns sem grande influência de valores extremos.
5.2 Variáveis categóricas
Descrição estatística da variável room_type:
df |>
select(room_type) |>
tbl_summary() |>
modify_header(label ~ "**Variável**") |>
modify_spanning_header(all_stat_cols() ~ "**Proporção**") |>
modify_caption("**Tabela 3. Proporção de tipos de imóveis**") |>
bold_labels()| Variável |
Proporção
|
|---|---|
| N = 213,5101 | |
| room_type | |
| Entire home/apt | 153,028 (72%) |
| Hotel room | 1,278 (0.6%) |
| Private room | 54,591 (26%) |
| Shared room | 4,613 (2.2%) |
| 1 n (%) | |
df |>
filter(!is.na(room_type)) |>
ggplot(aes(x = reorder(room_type, room_type, function(x) length(x)), fill = room_type)) +
geom_bar() +
theme_minimal() +
labs (
x = "Tipo de imóvel",
y = "Frequência",
title = "Distribuição dos tipos de imóveis",
subtitle = "Base de dados: df_clean"
) +
theme(legend.position = "none")Observa-se que mais de 70% dos imóveis para locação são do tipo “entire home/apt” (em português, “casa/apartamento inteiro”). A segunda categoria mais comum é “private room” (“quarto privado”). As demais categorias (quarto de hotel e quarto compartilhado) representam menos de 3% das observações, mesmo somadas.
Descrição estatística da variável neighbourhood_cleansed:
df |>
select(neighbourhood_cleansed) |>
mutate(neighbourhood_cleansed = fct_infreq(neighbourhood_cleansed)) |>
tbl_summary() |>
modify_header(label ~ "**Variável**") |>
modify_spanning_header(all_stat_cols() ~ "**Proporção**") |>
modify_caption("**Tabela 4. Proporção de bairros**") |>
bold_labels()| Variável |
Proporção
|
|---|---|
| N = 213,5101 | |
| neighbourhood_cleansed | |
| Copacabana | 55,910 (26%) |
| Barra da Tijuca | 23,989 (11%) |
| Ipanema | 18,385 (8.6%) |
| Jacarepaguá | 12,033 (5.6%) |
| Botafogo | 10,476 (4.9%) |
| Recreio dos Bandeirantes | 10,053 (4.7%) |
| Leblon | 9,764 (4.6%) |
| Santa Teresa | 6,920 (3.2%) |
| Centro | 5,922 (2.8%) |
| Flamengo | 5,518 (2.6%) |
| Tijuca | 4,344 (2.0%) |
| Laranjeiras | 4,278 (2.0%) |
| Leme | 3,722 (1.7%) |
| Lagoa | 2,416 (1.1%) |
| Glória | 2,125 (1.0%) |
| Catete | 2,034 (1.0%) |
| Jardim Botânico | 1,909 (0.9%) |
| Gávea | 1,851 (0.9%) |
| Humaitá | 1,777 (0.8%) |
| Camorim | 1,775 (0.8%) |
| Maracanã | 1,754 (0.8%) |
| Vila Isabel | 1,589 (0.7%) |
| São Conrado | 1,465 (0.7%) |
| Freguesia (Jacarepaguá) | 1,313 (0.6%) |
| Vargem Pequena | 1,149 (0.5%) |
| Taquara | 1,067 (0.5%) |
| Itanhangá | 1,028 (0.5%) |
| Vidigal | 964 (0.5%) |
| Urca | 875 (0.4%) |
| Vargem Grande | 764 (0.4%) |
| Cosme Velho | 693 (0.3%) |
| Rio Comprido | 681 (0.3%) |
| São Cristóvão | 631 (0.3%) |
| Grajaú | 618 (0.3%) |
| Estácio | 555 (0.3%) |
| Joá | 520 (0.2%) |
| Curicica | 516 (0.2%) |
| Andaraí | 504 (0.2%) |
| Campo Grande | 482 (0.2%) |
| Praça da Bandeira | 467 (0.2%) |
| Engenho de Dentro | 460 (0.2%) |
| Pechincha | 437 (0.2%) |
| Guaratiba | 416 (0.2%) |
| Barra de Guaratiba | 405 (0.2%) |
| Anil | 356 (0.2%) |
| Jardim Guanabara | 339 (0.2%) |
| Alto da Boa Vista | 336 (0.2%) |
| Méier | 330 (0.2%) |
| Engenho Novo | 307 (0.1%) |
| Todos os Santos | 242 (0.1%) |
| Cachambi | 225 (0.1%) |
| Irajá | 216 (0.1%) |
| Praça Seca | 206 (<0.1%) |
| São Francisco Xavier | 200 (<0.1%) |
| Paquetá | 188 (<0.1%) |
| Portuguesa | 177 (<0.1%) |
| Tanque | 162 (<0.1%) |
| Cidade Nova | 161 (<0.1%) |
| Saúde | 158 (<0.1%) |
| Del Castilho | 155 (<0.1%) |
| Riachuelo | 154 (<0.1%) |
| Gardênia Azul | 153 (<0.1%) |
| Rocha | 151 (<0.1%) |
| Brás de Pina | 149 (<0.1%) |
| Gamboa | 144 (<0.1%) |
| Bangu | 137 (<0.1%) |
| Rocinha | 134 (<0.1%) |
| Bonsucesso | 128 (<0.1%) |
| Santa Cruz | 128 (<0.1%) |
| Encantado | 126 (<0.1%) |
| Mangueira | 118 (<0.1%) |
| Penha | 116 (<0.1%) |
| Lins de Vasconcelos | 109 (<0.1%) |
| Santo Cristo | 104 (<0.1%) |
| Vila Valqueire | 96 (<0.1%) |
| Pedra de Guaratiba | 90 (<0.1%) |
| Piedade | 90 (<0.1%) |
| Tauá | 90 (<0.1%) |
| Maria da Graça | 83 (<0.1%) |
| Cidade de Deus | 82 (<0.1%) |
| Campinho | 79 (<0.1%) |
| Marechal Hermes | 79 (<0.1%) |
| Realengo | 78 (<0.1%) |
| Guadalupe | 77 (<0.1%) |
| Quintino Bocaiúva | 75 (<0.1%) |
| Jardim Sulacap | 73 (<0.1%) |
| Vila da Penha | 72 (<0.1%) |
| Cosmos | 68 (<0.1%) |
| Jardim Carioca | 68 (<0.1%) |
| Parque Anchieta | 68 (<0.1%) |
| Bento Ribeiro | 67 (<0.1%) |
| Madureira | 63 (<0.1%) |
| Padre Miguel | 63 (<0.1%) |
| Olaria | 61 (<0.1%) |
| Sampaio | 61 (<0.1%) |
| Higienópolis | 60 (<0.1%) |
| Ramos | 60 (<0.1%) |
| Vasco da Gama | 60 (<0.1%) |
| Benfica | 55 (<0.1%) |
| Cascadura | 55 (<0.1%) |
| Osvaldo Cruz | 54 (<0.1%) |
| Penha Circular | 54 (<0.1%) |
| Cacuia | 51 (<0.1%) |
| Catumbi | 51 (<0.1%) |
| Moneró | 51 (<0.1%) |
| Paciência | 51 (<0.1%) |
| Vicente de Carvalho | 50 (<0.1%) |
| Anchieta | 45 (<0.1%) |
| Inhaúma | 45 (<0.1%) |
| Pilares | 45 (<0.1%) |
| Santíssimo | 42 (<0.1%) |
| Engenho da Rainha | 41 (<0.1%) |
| Freguesia (Ilha) | 41 (<0.1%) |
| Tomás Coelho | 41 (<0.1%) |
| Senador Vasconcelos | 40 (<0.1%) |
| Sepetiba | 40 (<0.1%) |
| Pavuna | 39 (<0.1%) |
| Magalhães Bastos | 36 (<0.1%) |
| Jacaré | 34 (<0.1%) |
| Ricardo de Albuquerque | 34 (<0.1%) |
| Abolição | 33 (<0.1%) |
| Parada de Lucas | 33 (<0.1%) |
| Barros Filho | 32 (<0.1%) |
| Cocotá | 31 (<0.1%) |
| Galeão | 31 (<0.1%) |
| Senador Camará | 28 (<0.1%) |
| Cordovil | 26 (<0.1%) |
| Inhoaíba | 26 (<0.1%) |
| Água Santa | 24 (<0.1%) |
| Pitangueiras | 24 (<0.1%) |
| Praia da Bandeira | 22 (<0.1%) |
| Complexo do Alemão | 20 (<0.1%) |
| Vila Kosmos | 19 (<0.1%) |
| Bancários | 18 (<0.1%) |
| Grumari | 18 (<0.1%) |
| Rocha Miranda | 18 (<0.1%) |
| Coelho Neto | 16 (<0.1%) |
| Colégio | 16 (<0.1%) |
| Ribeira | 16 (<0.1%) |
| Vaz Lobo | 16 (<0.1%) |
| Vila Militar | 16 (<0.1%) |
| Vigário Geral | 14 (<0.1%) |
| Deodoro | 12 (<0.1%) |
| Manguinhos | 12 (<0.1%) |
| Engenheiro Leal | 10 (<0.1%) |
| Caju | 7 (<0.1%) |
| Honório Gurgel | 7 (<0.1%) |
| Vista Alegre | 7 (<0.1%) |
| Campo dos Afonsos | 6 (<0.1%) |
| Cavalcanti | 6 (<0.1%) |
| Gericinó | 6 (<0.1%) |
| Parque Colúmbia | 6 (<0.1%) |
| Jardim América | 5 (<0.1%) |
| Maré | 5 (<0.1%) |
| Cidade Universitária | 3 (<0.1%) |
| 1 n (%) | |
Observa-se que a partir do 16º bairro, a proporção de anúncios cai para menos de 1%. Por isso, eles serão cortados da visualização do gráfico abaixo:
df |>
filter(!is.na(neighbourhood_cleansed)) |>
count(neighbourhood_cleansed, sort = TRUE) |>
slice_head(n = 15) |>
ggplot(aes(
x = reorder(neighbourhood_cleansed, n),
y = n,
fill = neighbourhood_cleansed
)) +
geom_col() +
coord_flip() +
theme_minimal() +
labs(
x = "Bairro",
y = "Frequência",
title = "Distribuição dos bairros",
subtitle = "Top 15 bairros com mais anúncios"
) +
theme(legend.position = "none")Mais de 20% dos anúncios de imóveis para locação são em Copacabana. Leblon, o metro quadrado mais caro do Rio de Janeiro há alguns anos, é o 7º bairro com mais anúncios, ficando com menos de 5% deles. A maior concentração de bairros com anúncios fica na zona sul da cidade, seguida pela zona oeste e pelo Centro.
Descrição estatística da variável property_type:
df |>
select(property_type) |>
mutate(property_type = fct_infreq(property_type)) |>
tbl_summary() |>
modify_header(label ~ "**Variável**") |>
modify_spanning_header(all_stat_cols() ~ "**Proporção**") |>
modify_caption("**Tabela 5. Proporção de tipos de construção**") |>
bold_labels()| Variável |
Proporção
|
|---|---|
| N = 213,5101 | |
| property_type | |
| Apartment | 163,788 (77%) |
| House | 21,495 (10%) |
| Condominium | 12,563 (5.9%) |
| Loft | 4,186 (2.0%) |
| Serviced apartment | 3,986 (1.9%) |
| Guest suite | 1,323 (0.6%) |
| Bed and breakfast | 861 (0.4%) |
| Guesthouse | 812 (0.4%) |
| Villa | 660 (0.3%) |
| Hostel | 651 (0.3%) |
| Hotel | 621 (0.3%) |
| Other | 480 (0.2%) |
| Townhouse | 381 (0.2%) |
| Aparthotel | 242 (0.1%) |
| Cottage | 231 (0.1%) |
| Tiny house | 226 (0.1%) |
| Earth house | 183 (<0.1%) |
| Chalet | 181 (<0.1%) |
| Boutique hotel | 162 (<0.1%) |
| Boat | 120 (<0.1%) |
| Cabin | 60 (<0.1%) |
| Nature lodge | 57 (<0.1%) |
| Bungalow | 51 (<0.1%) |
| Casa particular (Cuba) | 42 (<0.1%) |
| Island | 29 (<0.1%) |
| Houseboat | 15 (<0.1%) |
| Castle | 12 (<0.1%) |
| Farm stay | 12 (<0.1%) |
| Tent | 12 (<0.1%) |
| Treehouse | 12 (<0.1%) |
| Campsite | 11 (<0.1%) |
| Dorm | 10 (<0.1%) |
| Hut | 10 (<0.1%) |
| Camper/RV | 8 (<0.1%) |
| Barn | 6 (<0.1%) |
| Yurt | 6 (<0.1%) |
| Vacation home | 4 (<0.1%) |
| Igloo | 1 (<0.1%) |
| 1 n (%) | |
Observa-se que a partir do 5º tipo, as categorias passam a representar menos de 1% do total. Logo, a visualização abaixo será focada no top 5:
df |>
filter(!is.na(property_type)) |>
count(property_type, sort = TRUE) |>
slice_head(n = 5) |>
ggplot(aes(
x = reorder(property_type, n),
y = n,
fill = property_type
)) +
geom_col() +
coord_flip() +
theme_minimal() +
labs(
x = "Tipo de construção",
y = "Frequência",
title = "Distribuição dos tipos de construção",
subtitle = "Top 5 tipos de construção mais anunciados"
) +
theme(legend.position = "none")Observa-se que mais de 70% dos imóveis para locação são do tipo “Apartment”. A segunda categoria mais comum é “house”, seguido por “Condiminium”. As demais categorias (“Loft” e “Serviced apartment”) representam apenas cerca de 4% das observações, mesmo somadas.
6 Análise Bivariada
6.1 Price (numérica) x Categóricas
O preço de aluguel é diferente por tipo de imóvel?
df |>
mutate(room_type = fct_reorder(room_type, price, .fun = median)) |>
ggplot(aes(x = room_type, y = price, fill = room_type)) +
geom_boxplot(alpha = 0.75, outlier.alpha = 0.4, outlier.size = 1.2, width = 0.55, show.legend = FALSE) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "#C04828", show.legend = FALSE) +
scale_fill_manual(values = c("#B5D4F4", "#85B7EB", "#378ADD", "#185FA5", "#0C447C")) +
scale_y_continuous(labels = dollar_format(prefix = "R$")) +
coord_cartesian(ylim = c(0, 1000)) +
labs(title = "Preço de aluguel por tipo de imóvel",
subtitle = "Losango vermelho = média (Zoom até R$ 1000)",
x = "Tipo de imóvel",
y = "Preço") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"))df |>
group_by(room_type) |>
summarise(
n = n(),
min = min(price, na.rm = TRUE),
mediana = median(price, na.rm = TRUE),
q1 = quantile(price, 0.25),
q3 = quantile(price, 0.75),
media = mean(price, na.rm = TRUE),
max = max(price, na.rm = TRUE),
dp = sd(price)
) |>
arrange(desc(mediana)) |>
mutate(
across(c(min, max, mediana, media, dp, q1, q3),
~ dollar(., prefix = "R$"))
) |>
kbl(col.names = c("Tipo", "n", "Mínimo", "Mediana", "Q1", "Q3", "Média", "Máximo", "Desvio Padrão"),
align = "lrrrrrrrr") |>
kable_styling(bootstrap_options = c("stripped", "hover"), full_width = TRUE)| Tipo | n | Mínimo | Mediana | Q1 | Q3 | Média | Máximo | Desvio Padrão |
|---|---|---|---|---|---|---|---|---|
| Entire home/apt | 153028 | R$0 | R$382.00 | R$202 | R$802 | R$860.89 | R$57,517 | R$2,176.92 |
| Hotel room | 1278 | R$0 | R$201.50 | R$98 | R$402 | R$849.67 | R$17,841 | R$2,133.68 |
| Private room | 54591 | R$0 | R$151.00 | R$97 | R$286 | R$287.29 | R$54,981 | R$898.06 |
| Shared room | 4613 | R$28 | R$101.00 | R$63 | R$200 | R$292.62 | R$25,000 | R$1,185.08 |
Sim, o preço de aluguel difere por tipo de imóvel, sendo o tipo “Entire home/apt” o mais caro (mediana R$ 382, IQR = R$ 202-802), levando em conta a mediana. Observa-se que este também é o tipo de imóvel que possui a maior variabilidade de preço.
O preço de aluguel é diferente de acordo com o bairro?
df |>
filter(neighbourhood_cleansed %in% top_bairros) |>
mutate(neighbourhood_cleansed = fct_reorder(neighbourhood_cleansed, price, .fun = median)) |>
ggplot(aes(x = neighbourhood_cleansed, y = price, fill = neighbourhood_cleansed)) +
geom_boxplot(alpha = 0.75, outlier.alpha = 0.4, outlier.size = 1.2, width = 0.55, show.legend = FALSE) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "#C04828", show.legend = FALSE) +
scale_y_continuous(labels = dollar_format(prefix = "R$")) +
coord_flip(ylim = c(0, 1000)) + # coord_flip inverte os eixos (X vira Y)
labs(title = "Preço de aluguel nos 15 bairros com mais anúncios",
subtitle = "Ordenado pela mediana | Losango vermelho = média",
x = "Bairro",
y = "Preço (Zoom até R$ 1000)") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"),
panel.grid.minor = element_blank())df |>
filter(neighbourhood_cleansed %in% top_bairros) |>
group_by(neighbourhood_cleansed) |>
summarise(
n = n(),
min = min(price, na.rm = TRUE),
q1 = quantile(price, 0.25, na.rm = TRUE),
mediana = median(price, na.rm = TRUE),
q3 = quantile(price, 0.75, na.rm = TRUE),
media = mean(price, na.rm = TRUE),
max = max(price, na.rm = TRUE),
dp = sd(price, na.rm = TRUE)
) |>
arrange(desc(mediana)) |>
mutate(
across(c(min, q1, mediana, q3, media, max, dp),
~ dollar(., prefix = "R$"))
) |>
kbl(col.names = c("Bairro", "n", "Mínimo", "Q1", "Mediana", "Q3", "Média", "Máximo", "Desvio Padrão"),
align = "lrrrrrrrr") |>
kable_styling(bootstrap_options = c("striped", "hover"), full_width = TRUE)| Bairro | n | Mínimo | Q1 | Mediana | Q3 | Média | Máximo | Desvio Padrão |
|---|---|---|---|---|---|---|---|---|
| Lagoa | 2416 | R$49 | R$238.75 | R$498.50 | R$1,097.50 | R$1,018.11 | R$31,402 | R$2,025.27 |
| Leblon | 9764 | R$48 | R$288.00 | R$451.00 | R$852.00 | R$864.45 | R$25,002 | R$1,472.80 |
| Barra da Tijuca | 23989 | R$41 | R$247.00 | R$450.00 | R$1,002.00 | R$1,117.86 | R$54,981 | R$2,704.87 |
| Jacarepaguá | 12033 | R$0 | R$189.00 | R$413.00 | R$979.00 | R$801.42 | R$49,784 | R$2,203.05 |
| Ipanema | 18385 | R$30 | R$237.00 | R$399.00 | R$789.00 | R$790.46 | R$45,697 | R$1,729.51 |
| Recreio dos Bandeirantes | 10053 | R$28 | R$198.00 | R$393.00 | R$900.00 | R$796.92 | R$37,598 | R$1,516.67 |
| Leme | 3722 | R$38 | R$173.25 | R$298.00 | R$550.75 | R$604.23 | R$35,002 | R$1,842.64 |
| Copacabana | 55910 | R$0 | R$159.00 | R$250.00 | R$498.00 | R$562.04 | R$57,517 | R$1,580.41 |
| Botafogo | 10476 | R$37 | R$130.00 | R$220.00 | R$449.00 | R$435.19 | R$35,002 | R$1,276.05 |
| Flamengo | 5518 | R$35 | R$122.00 | R$218.00 | R$401.00 | R$485.68 | R$35,002 | R$1,445.48 |
| Laranjeiras | 4278 | R$37 | R$121.00 | R$218.00 | R$478.00 | R$480.65 | R$54,981 | R$1,862.18 |
| Tijuca | 4344 | R$31 | R$100.00 | R$201.00 | R$548.00 | R$500.00 | R$32,944 | R$1,251.79 |
| Santa Teresa | 6920 | R$35 | R$101.00 | R$179.00 | R$327.00 | R$550.04 | R$55,315 | R$2,328.70 |
| Glória | 2125 | R$29 | R$101.00 | R$176.00 | R$323.00 | R$433.42 | R$30,002 | R$1,762.49 |
| Centro | 5922 | R$30 | R$100.00 | R$151.00 | R$298.00 | R$425.81 | R$25,000 | R$1,306.30 |
Sim, o preço de aluguel é diferente por bairro. Dentre os 15 bairros mais populares, a Lagoa é o com maior mediana e também maior variabilidade de preço (R$ 498, IQR = R$ 239-1.097), contra o Centro, que possui mediana quase 3x menor e também menor variabilidade de preço (R$ 151, IQR = R$ 100-298).
O preço de aluguel sofre alterações caso o host seja considerado um superhost pela plataforma?
df |>
mutate(host_is_superhost = fct_reorder(host_is_superhost, price, .fun = median)) |>
ggplot(aes(x = host_is_superhost, y = price, fill = host_is_superhost)) +
geom_boxplot(alpha = 0.75, outlier.alpha = 0.4, outlier.size = 1.2, width = 0.55, show.legend = FALSE) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "#C04828", show.legend = FALSE) +
scale_fill_manual(values = c("#B5D4F4", "#85B7EB", "#378ADD", "#185FA5", "#0C447C")) +
scale_y_continuous(labels = dollar_format(prefix = "R$")) +
coord_cartesian(ylim = c(0, 1000)) +
labs(title = "Preço de aluguel por tipo de imóvel",
subtitle = "Losango vermelho = média (Zoom até R$ 1000)",
x = "Tipo de imóvel",
y = "Preço") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"))df |>
group_by(host_is_superhost) |>
summarise(
n = n(),
min = min(price, na.rm = TRUE),
mediana = median(price, na.rm = TRUE),
q1 = quantile(price, 0.25),
q3 = quantile(price, 0.75),
media = mean(price, na.rm = TRUE),
max = max(price, na.rm = TRUE),
dp = sd(price)
) |>
arrange(desc(mediana)) |>
mutate(
across(c(min, max, mediana, media, dp, q1, q3),
~ dollar(., prefix = "R$"))
) |>
kbl(col.names = c("Tipo", "n", "Mínimo", "Mediana", "Q1", "Q3", "Média", "Máximo", "Desvio Padrão"),
align = "lrrrrrrrr") |>
kable_styling(bootstrap_options = c("stripped", "hover"), full_width = TRUE)| Tipo | n | Mínimo | Mediana | Q1 | Q3 | Média | Máximo | Desvio Padrão |
|---|---|---|---|---|---|---|---|---|
| Não | 186373 | R$0 | R$299 | R$166 | R$684 | R$726.15 | R$57,517 | R$1,951.05 |
| Sim | 27137 | R$29 | R$202 | R$131 | R$361 | R$535.28 | R$46,085 | R$1,772.52 |
Sim, o preço é diferente, mas os superhosts cobram menos (em média) do que os hosts comuns. A mediana de preço de hosts comuns (R$ 299, IQR = R$ 166-684) é cerca de 32% maior do que de hosts que são superhosts (R$ 202, IQR = R$ 131-361). Também observa-se uma maior variabilidade de preço entre os hosts comuns.
O preço é diferente de acordo com o tipo de construção do imóvel?
top_propriedades = df |>
count(property_type, sort = TRUE) |>
slice_max(n, n = 5) |>
pull(property_type)
df |>
filter(property_type %in% top_propriedades) |>
mutate(property_type = fct_reorder(property_type, price, .fun = median)) |>
ggplot(aes(x = property_type, y = price, fill = property_type)) +
geom_boxplot(alpha = 0.75, outlier.alpha = 0.4, outlier.size = 1.2, width = 0.55, show.legend = FALSE) +
stat_summary(fun = mean, geom = "point", shape = 18, size = 3, color = "#C04828", show.legend = FALSE) +
scale_y_continuous(labels = dollar_format(prefix = "R$")) +
scale_fill_manual(values = c("#B5D4F4", "#85B7EB", "#378ADD", "#185FA5", "#0C447C")) +
coord_cartesian(ylim = c(0, 1500)) +
labs(title = "Preço de aluguel por tipo de construção (Top 5)",
subtitle = "Tipos mais frequentes | Losango vermelho = média",
x = "Tipo de construção",
y = "Preço (Zoom até R$ 1500)") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(face = "bold"))df |>
filter(property_type %in% top_propriedades) |>
group_by(property_type) |>
summarise(
n = n(),
min = min(price, na.rm = TRUE),
q1 = quantile(price, 0.25, na.rm = TRUE),
mediana = median(price, na.rm = TRUE),
q3 = quantile(price, 0.75, na.rm = TRUE),
media = mean(price, na.rm = TRUE),
max = max(price, na.rm = TRUE),
dp = sd(price, na.rm = TRUE)
) |>
arrange(desc(mediana)) |>
mutate(
across(c(min, q1, mediana, q3, media, max, dp),
~ dollar(., prefix = "R$"))
) |>
kbl(col.names = c("Tipo", "n", "Mínimo", "Q1", "Mediana", "Q3", "Média", "Máximo", "Desvio Padrão"),
align = "lrrrrrrrr") |>
kable_styling(bootstrap_options = c("striped", "hover"), full_width = TRUE)| Tipo | n | Mínimo | Q1 | Mediana | Q3 | Média | Máximo | Desvio Padrão |
|---|---|---|---|---|---|---|---|---|
| Apartment | 163788 | R$0 | R$171 | R$299 | R$649 | R$669.30 | R$57,517 | R$1,675.63 |
| Condominium | 12563 | R$35 | R$151 | R$278 | R$499 | R$500.74 | R$54,981 | R$1,491.36 |
| House | 21495 | R$0 | R$121 | R$272 | R$830 | R$1,135.75 | R$55,315 | R$3,282.97 |
| Serviced apartment | 3986 | R$41 | R$180 | R$254 | R$401 | R$404.27 | R$18,887 | R$828.09 |
| Loft | 4186 | R$33 | R$143 | R$200 | R$346 | R$422.78 | R$10,480 | R$790.08 |
Não, o preço de aluguel não muda consideravelmente entre as categorias de tipos de construções. No entanto, embora o tipo de construção apresente medianas de preço aproximadas (variando entre R$ 200 e R$ 299), o tipo de construção exerce forte influência na amplitude dos valores. Casas (House) apresentam uma média e um desvio padrão significativamente superiores (média = R$ 1.136, DP = R$ 3.283), indicando que este tipo de propriedade atinge patamares de preço muito mais elevados (outliers de luxo) do que apartamentos (média = R$ 669, DP = R$ 1.676) ou lofts (média = R$ 423, DP = R$ 790), que possuem preços mais homogêneos e previsíveis.
6.2 Price (numérica) x Numéricas
Há correlação entre preço de aluguel e a quantidade de pessoas que o imóvel consegue acomodar?
df |>
filter(accommodates <= 10, price <= 2000) |>
ggplot(aes(x = accommodates, y = price)) +
geom_smooth(method = "lm", se = TRUE,
color = "#C04828", fill = "#C04828", alpha = 0.15, linewidth = 1) +
geom_point(alpha = 0.4) +
scale_y_continuous(labels = dollar_format(prefix = "R$", scale = 1e-3, suffix = "k")) +
labs(title = "Preço de aluguel por quantidade de pessoas acomodadas",
x = "Quantidade de pessoas",
y = "Preço de aluguel") +
theme_minimal() +
theme(plot.title = element_text((face = "bold")))cor(df$accommodates, df$price, method = "pearson")[1] 0.2464007
cor(df$accommodates, df$price, method = "spearman")[1] 0.5191272
Sim, segundo o coeficiente de Spearman, há uma correlação moderada (r = 0,51) entre o preço de aluguel e a quantidade de pessoas que o imóvel acomoda. Como observado pelo gráfico, trata-se de uma relação monotônica, não-linear. Por isso, optou-se pelo uso do coeficiente de Spearman para descrever sua força.
Há correlação entre o preço de aluguel e a quantidade de quartos do imóvel?
df |>
ggplot(aes(x = bedrooms, y = price)) +
geom_point(alpha = 0.4) +
geom_smooth(method = "lm", se = TRUE,
color = "#C04828", fill = "#C04828", alpha = 0.15, linewidth = 1) +
scale_y_continuous(labels = dollar_format(prefix = "R$", scale = 1e-3, suffix = "k")) +
labs(title = "Quantidade de quartos vs Preço de aluguel",
x = "Quantidade de quartos",
y = "Preço de aluguel") +
theme_minimal() +
theme(plot.title = element_text((face = "bold")))cor(df$bedrooms, df$price, method = "pearson")[1] 0.2964119
cor(df$bedrooms, df$price, method = "spearman")[1] 0.5395045
Sim, segundo o coeficiente de Spearman, há uma correlação moderada (r = 0,53) entre o preço de aluguel e a quantidade de quartos do imóvel. Como observado pelo gráfico, trata-se de uma relação monotônica, não-linear. Por isso, optou-se pelo uso do coeficiente de Spearman para descrever sua força.
Há correlação entre o preço de aluguel e a quantidade de banheiros do imóvel?
df |>
filter(bathrooms <= 25, price <= 2000) |>
ggplot(aes(x = bathrooms, y = price)) +
geom_point(alpha = 0.4) +
geom_smooth(method = "lm", se = TRUE,
color = "#C04828", fill = "#C04828", alpha = 0.15, linewidth = 1) +
scale_y_continuous(labels = dollar_format(prefix = "R$", scale = 1e-3, suffix = "k")) +
labs(title = "Quantidade de banheiros vs Preço de aluguel",
x = "Quantidade de banheiros",
y = "Preço de aluguel") +
theme_minimal() +
theme(plot.title = element_text((face = "bold")))cor(df$bathrooms, df$price, method = "pearson")[1] 0.2475232
cor(df$bathrooms, df$price, method = "spearman")[1] 0.4682769
Sim, segundo o coeficiente de Spearman, há uma correlação moderada (r = 0,46) entre o preço de aluguel e a quantidade de banheiros do imóvel. Como observado pelo gráfico, trata-se de uma relação monotônica, não-linear. Por isso, optou-se pelo uso do coeficiente de Spearman para descrever sua força.
Há correlação entre o preço de aluguel e a quantidade de reviews de um anúncio?
df |>
ggplot(aes(x = number_of_reviews, y = price)) +
geom_point(alpha = 0.4) +
geom_smooth(method = "lm", se = TRUE,
color = "#C04828", fill = "#C04828", alpha = 0.15, linewidth = 1) +
scale_y_continuous(labels = dollar_format(prefix = "R$", scale = 1e-3, suffix = "k")) +
labs(title = "Quantidade de reviews vs Preço de aluguel",
x = "Quantidade de reviews",
y = "Preço de aluguel") +
theme_minimal() +
theme(plot.title = element_text((face = "bold")))cor(df$number_of_reviews, df$price, method = "pearson")[1] -0.07881441
cor(df$number_of_reviews, df$price, method = "spearman")[1] -0.3690749