Projeto de Disciplina 26.1

Análise Exploratória de Dados

Author

Anabella Sgarbi Pereira

Published

April 13, 2026

1 Carregando os pacotes

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)

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()
Tabela 1. Estatística descritiva das variáveis da base de dados
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álise

  • acommodates, bedrooms, number_of_reviews, minimun_nights e guests_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érica

  • mes: 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_cleansed e property_type: categóricas

  • price, accommodates, bedrooms, bathrooms, number_of_reviews, review_scores_rating, minimum_nights, guests_included: numéricas

  • host_is_superhost: lógica

  • mes: 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áveis com valores ausentes
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_rating NAs = não há reviews para o imóvel

  • bedrooms e bathrooms NAs = números não especificados no anúncio

  • host_is_superhost NAs = 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 * iqr

Caracterí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()
Tabela 3. Proporção de tipos de imóveis
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()
Tabela 4. Proporção de bairros
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()
Tabela 5. Proporção de tipos de construção
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