Projeto de Data Science: Análise de Dados do Airbnb
Tags: programming, python, pandas, datascience
Published: 2023-11-05 10:33:46

Neste artigo, vamos realizar um projeto de data science completo com pandas, numpy e seaborn, usando os dados do Airbnb, a maior empresa hoteleira da atualidade, que não possui nenhum hotel.

O Airbnb é uma plataforma de hospedagem alternativa que conecta pessoas que querem viajar (e se hospedar) com anfitriões que querem alugar seus imóveis de maneira prática, segura e com bom custo-benefício.

O Airbnb disponibiliza dados do seu site para algumas das principais cidades do mundo, através do portal [Inside Airbnb](http://insideairbnb.com/). Neste projeto, vamos usar os dados referentes à cidade de São Paulo, no Brasil, para explorar e responder algumas questões sobre o mercado de hospedagem na capital paulista.

## Obtenção dos Dados

Os dados que vamos usar neste projeto podem ser obtidos diretamente do portal [Inside Airbnb](http://insideairbnb.com/), na seção [Get the Data](http://insideairbnb.com/get-the-data). Para facilitar, vamos usar o arquivo `listings.csv`, que contém um resumo das informações e métricas para cada imóvel disponível na cidade de São Paulo, se não estiver disponivel São Paulo, utilize outro estado.

Para baixar o arquivo, basta clicar no link [listings.csv](http://data.insideairbnb.com/brazil/rj/rio-de-janeiro/2023-09-22/visualisations/listings.csv) e salvar o arquivo no seu computador. Em seguida, vamos importar as bibliotecas necessárias e carregar o arquivo em um DataFrame, usando a biblioteca pandas.

```python
# Importar as bibliotecas necessárias
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

# Carregar o arquivo listings.csv em um DataFrame
df = pd.read_csv("listings.csv")
```

## Análise dos Dados

Nesta etapa, vamos realizar uma análise exploratória dos dados, buscando entender a estrutura, a qualidade e as características dos dados que temos.

### Visualização das primeiras entradas

Para começar, vamos visualizar as primeiras cinco entradas do nosso DataFrame, usando o método `head`.

```python
# Visualizar as primeiras cinco entradas
df.head()
```

| id | name | host_id | host_name | neighbourhood_group | neighbourhood | latitude | longitude | room_type | price | minimum_nights | number_of_reviews | last_review | reviews_per_month | calculated_host_listings_count | availability_365 |
| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
| 17878 | Very Nice 2Br in Copacabana | 68997 | Viviane | NaN | Copacabana | -22.96592 | -43.17896 | Entire home/apt | 221 | 5 | 260 | 2020-02-15 | 2.01 | 1 | 304 |
| 25026 | Beautiful Modern Decorated Studio in Copa | 37490 | Marcia | NaN | Copacabana | -22.97712 | -43.19045 | Entire home/apt | 307 | 4 | 85 | 2018-02-14 | 0.67 | 1 | 10 |
| 31560 | NICE & COZY 1BDR - IPANEMA BEACH | 120694 | Renata | NaN | Ipanema | -22.98302 | -43.21427 | Entire home/apt | 160 | 2 | 181 | 2020-03-15 | 2.09 | 1 | 328 |
| 35636 | Cosy flat close to Ipanema beach | 153232 | Patricia | NaN | Arpoador | -22.98816 | -43.19359 | Entire home/apt | 273 | 2 | 353 | 2020-03-10 | 2.37 | 1 | 207 |
| 35764 | COPACABANA SEA BREEZE  -  RIO | 153691 | Bob | NaN | Copacabana | -22.98127 | -43.18923 | Entire home/apt | 135 | 3 | 10 | 2015-07-02 | 0.13 | 1 | 101 |

A partir da visualização das primeiras entradas, podemos observar algumas informações importantes, como:

- O DataFrame possui 16 colunas, que representam as variáveis ou atributos dos dados.
- Cada coluna possui um tipo de dado, que pode ser numérico, categórico ou textual.
- Cada linha representa uma observação ou instância dos dados, que corresponde a um imóvel disponível na plataforma do Airbnb.
- Algumas colunas possuem valores ausentes, indicados por `NaN`, que significa Not a Number. Isso pode indicar que o dado não foi informado ou não é aplicável para aquele imóvel.
- Algumas colunas possuem valores que não são muito relevantes para a nossa análise, como o `id` e o `host_id`, que são apenas identificadores numéricos.

### Identificação das variáveis

Para facilitar a nossa análise, vamos identificar as variáveis que temos no nosso DataFrame, bem como os seus tipos de dados e as suas descrições. Para isso, vamos usar os métodos `info` e `dtypes`.

```python
# Identificar o volume de dados do DataFrame
print("Entradas:\t {}".format(df.shape[0]))
print("Variáveis:\t {}\n".format(df.shape[1]))

# Identificar os tipos de dados das variáveis
display(df.dtypes)
```

Entradas:	 35870
Variáveis:	 16

| Variável | Tipo | Descrição |
| -- | -- | -- |
| id | int64 | Número de identificação do imóvel |
| name | object | Nome do imóvel |
| host_id | int64 | Número de identificação do anfitrião |
| host_name | object | Nome do anfitrião |
| neighbourhood_group | float64 | Grupo de bairros (vazio) |
| neighbourhood | object | Nome do bairro |
| latitude | float64 | Coordenada de latitude do imóvel |
| longitude | float64 | Coordenada de longitude do imóvel |
| room_type | object | Tipo de quarto oferecido |
| price | int64 | Preço da diária em reais |
| minimum_nights | int64 | Número mínimo de noites para reservar |
| number_of_reviews | int64 | Número de avaliações do imóvel |
| last_review | object | Data da última avaliação |
| reviews_per_month | float64 | Número de avaliações por mês |
| calculated_host_listings_count | int64 | Número de imóveis do mesmo anfitrião |
| availability_365 | int64 | Número de dias disponíveis no ano |

### Análise estatística dos dados

Para ter uma visão geral dos dados numéricos do nosso DataFrame, vamos usar o método `describe`, que retorna algumas medidas estatísticas, como média, mediana, desvio padrão, valor mínimo, valor máximo e quartis.

```python
# Ver as medidas estatísticas dos dados numéricos
df.describe()
```

| count | mean | std | min | 25% | 50% | 75% | max |
| -- | -- | -- | -- | -- | -- | -- | -- |
| id | 35870.000000 | 2.162079e+07 | 17878.000000 | 2.062874e+06 | 1.063895e+07 | 2.098962e+07 | 4.535038e+07 |
| host_id | 35870.000000 | 9.527658e+07 | 68997.000000 | 3.592192e+06 | 1.475763e+07 | 1.374868e+08 | 3.625386e+08 |
| neighbourhood_group | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN |
| latitude | 35870.000000 | 2.361415e-02 | -23.072920 | -23.013050 | -22.983020 | -22.951020 | -22.749820 |
| longitude | 35870.000000 | 3.433486e-02 | -43.704790 | -43.197070 | -43.187550 | -43.173060 | -43.104860 |
| price | 35870.000000 | 1.533537e+04 | 0.000000 | 157.000000 | 280.000000 | 550.000000 | 1380000.000000 |
| minimum_nights | 35870.000000 | 1.770685e+01 | 1.000000 | 2.000000 | 3.000000 | 4.000000 | 1000.000000 |
| number_of_reviews | 35870.000000 |

### Verificação de valores ausentes

Uma das etapas importantes da análise de dados é verificar se há valores ausentes no nosso conjunto de dados. Valores ausentes podem indicar problemas na coleta, no armazenamento ou no processamento dos dados, e podem afetar a qualidade e a confiabilidade da nossa análise.

Para verificar a quantidade e a proporção de valores ausentes em cada coluna do nosso DataFrame, vamos usar os métodos `isnull` e `sum`.

```python
# Verificar a quantidade de valores ausentes em cada coluna
df.isnull().sum()
```

| Variável | Valores Ausentes |
| -- | -- |
| id | 0 |
| name | 62 |
| host_id | 0 |
| host_name | 62 |
| neighbourhood_group | 35870 |
| neighbourhood | 0 |
| latitude | 0 |
| longitude | 0 |
| room_type | 0 |
| price | 0 |
| minimum_nights | 0 |
| number_of_reviews | 0 |
| last_review | 14540 |
| reviews_per_month | 14540 |
| calculated_host_listings_count | 0 |
| availability_365 | 0 |

```python
# Verificar a proporção de valores ausentes em cada coluna
(df.isnull().sum() / df.shape[0]).sort_values(ascending=False)
```

| Variável | Proporção de Valores Ausentes |
| -- | -- |
| neighbourhood_group | 1.000000 |
| reviews_per_month | 0.405222 |
| last_review | 0.405222 |
| name | 0.001729 |
| host_name | 0.001729 |
| availability_365 | 0.000000 |
| calculated_host_listings_count | 0.000000 |
| number_of_reviews | 0.000000 |
| minimum_nights | 0.000000 |
| price | 0.000000 |
| room_type | 0.000000 |
| longitude | 0.000000 |
| latitude | 0.000000 |
| neighbourhood | 0.000000 |
| host_id | 0.000000 |
| id | 0.000000 |

A partir da verificação de valores ausentes, podemos observar algumas informações importantes, como:

- A coluna `neighbourhood_group` possui 100% dos seus valores ausentes, ou seja, ela não contém nenhuma informação útil para a nossa análise. Podemos descartar essa coluna do nosso DataFrame.
- As colunas `reviews_per_month` e `last_review` possuem cerca de 40% dos seus valores ausentes, o que indica que muitos imóveis não possuem avaliações ou possuem avaliações muito antigas. Isso pode afetar a nossa análise sobre a popularidade e a qualidade dos imóveis.
- As colunas `name` e `host_name` possuem poucos valores ausentes, cerca de 0,17%, o que indica que a maioria dos imóveis e dos anfitriões possuem nomes informados. Esses valores ausentes podem ser ignorados ou substituídos por valores genéricos, como "Sem nome" ou "Anônimo".

### Análise de outliers

Outro aspecto importante da análise de dados é verificar se há outliers, ou seja, valores que fogem da normalidade e que podem distorcer as medidas estatísticas e as visualizações gráficas.

Uma forma de identificar outliers é através de histogramas, que são gráficos que mostram a distribuição de frequência dos dados. Vamos plotar os histogramas das variáveis numéricas do nosso DataFrame, usando o método `hist`.

```python
# Plotar o histograma das variáveis numéricas
df.hist(bins=15, figsize=(15,10))
plt.show()
```

![Histogramas]

A partir dos histogramas, podemos observar que:

- As variáveis `price`, `minimum_nights` e `calculated_host_listings_count` possuem valores muito altos, que se distanciam da maioria dos dados, formando uma cauda longa à direita. Isso indica a presença de outliers nessas variáveis, que podem ser imóveis com preços exorbitantes, que exigem um número mínimo de noites muito alto ou que pertencem a anfitriões com muitos imóveis na plataforma.
- As variáveis `latitude` e `longitude` possuem uma distribuição mais uniforme, sem valores extremos, o que indica que os imóveis estão bem distribuídos na cidade de São Paulo, sem concentrações em áreas específicas.
- As variáveis `number_of_reviews`, `reviews_per_month` e `availability_365` possuem uma grande quantidade de valores iguais a zero, o que indica que muitos imóveis não possuem avaliações, não recebem avaliações frequentemente ou não estão disponíveis durante o ano.

Uma outra forma de identificar outliers é através de boxplots, que são gráficos que mostram a variação dos dados em relação a uma medida de tendência central, geralmente a mediana. Os boxplots também mostram os limites inferior e superior dos dados, chamados de quartis, e os valores que estão fora desses limites, chamados de outliers.

Vamos plotar os boxplots das variáveis `price` e `minimum_nights`, que foram as que apresentaram mais outliers nos histogramas, usando o método `boxplot`.

```python
# Plotar o boxplot da variável price
df.price.plot(kind='box', vert=False, figsize=(15, 3))
plt.show()

# Ver a quantidade de valores acima de 1500 para a variável price
print("price: valores acima de 1500")
print("{} entradas".format(len(df[df.price > 1500])))
print("{:.4f}%".format((len(df[df.price > 1500]) / df.shape[0])*100))
```

![Boxplot da variável price]

price: valores acima de 1500
3363 entradas
9.3736%

```python
# Plotar o boxplot da variável minimum_nights
df.minimum_nights.plot(kind='box', vert=False, figsize=(15, 3))
plt.show()

# Ver a quantidade de valores acima de 30 para a variável minimum_nights
print("minimum_nights: valores acima de 30")
print("{} entradas".format(len(df[df.minimum_nights > 30])))
print("{:.4f}%".format((len(df[df.minimum_nights > 30]) / df.shape[0])*100))
```

![Boxplot da variável minimum_nights]

minimum_nights: valores acima de 30
209 entradas
0.5827%

A partir dos boxplots, podemos observar que:

- A variável `price` possui muitos outliers, que são os pontos acima do limite superior do boxplot, indicado pela linha horizontal no topo do gráfico. Esses outliers representam cerca de 9,37% das entradas, que são os imóveis com preços acima de 1500 reais. Esses valores podem distorcer a análise sobre o preço médio dos imóveis na cidade de São Paulo, e podem ser removidos ou substituídos por valores mais próximos da mediana.
- A variável `minimum_nights` também possui alguns outliers, que são os pontos acima do limite superior do boxplot, indicado pela linha horizontal no topo do gráfico. Esses outliers representam cerca de 0,58% das entradas, que são os imóveis que exigem um número mínimo de noites acima de 30. Esses valores podem distorcer a análise sobre o tempo médio de hospedagem na cidade de São Paulo, e podem ser removidos ou substituídos por valores mais próximos da mediana.

### Limpeza dos dados

Após identificar os valores ausentes e os outliers, vamos realizar uma limpeza dos dados, removendo ou substituindo os valores que podem prejudicar a nossa análise.

Para isso, vamos seguir os seguintes passos:

- Remover a coluna `neighbourhood_group`, que possui todos os valores ausentes.
- Substituir os valores ausentes das colunas `name` e `host_name` por "Sem nome" e "Anônimo", respectivamente.
- Substituir os valores ausentes das colunas `reviews_per_month` e `last_review` por zero, indicando que o imóvel não possui avaliações.
- Remover as entradas que possuem valores acima de 1500 para a variável `price` e acima de 30 para a variável `minimum_nights`, que são os outliers identificados nos boxplots.
- Criar uma cópia do DataFrame original, chamada `df_clean`, para armazenar os dados limpos.

```python
# Remover a coluna neighbourhood_group
df.drop('neighbourhood_group', axis=1, inplace=True)

# Substituir os valores ausentes de name e host_name por "Sem nome" e "Anônimo"
df['name'].fillna('Sem nome', inplace=True)
df['host_name'].fillna('Anônimo', inplace=True)

# Substituir os valores ausentes de reviews_per_month e last_review por zero
df['reviews_per_month'].fillna(0, inplace=True)
df['last_review'].fillna(0, inplace=True)

# Remover as entradas com valores acima de 1500 para price e acima de 30 para minimum_nights
df.drop(df[df.price > 1500].index, axis=0, inplace=True)
df.drop(df[df.minimum_nights > 30].index, axis=0, inplace=True)

# Criar uma cópia do DataFrame original com os dados limpos
df_clean = df.copy()
```

Agora que temos os dados limpos, podemos prosseguir com a nossa análise.


### Análise de correlação entre as variáveis

Uma das formas de analisar os dados é verificar se há correlação entre as variáveis, ou seja, se há uma relação entre elas, que pode ser positiva ou negativa, forte ou fraca.

A correlação pode ser medida por um coeficiente, que varia de -1 a 1, onde:

- -1 indica uma correlação negativa perfeita, ou seja, quando uma variável aumenta, a outra diminui na mesma proporção.
- 0 indica que não há correlação, ou seja, as variáveis não têm relação entre si.
- 1 indica uma correlação positiva perfeita, ou seja, quando uma variável aumenta, a outra também aumenta na mesma proporção.

Para verificar a correlação entre as variáveis do nosso DataFrame, vamos usar o método `corr`, que retorna uma matriz de correlação, e plotar um mapa de calor, usando a biblioteca seaborn.

```python
# Criar uma matriz de correlação
corr = df_clean[['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month', 'calculated_host_listings_count', 'availability_365']].corr()

# Plotar um mapa de calor a partir da matriz de correlação
sns.heatmap(corr, cmap='RdBu', fmt='.2f', square=True, linecolor='white', annot=True)
plt.show()
```

![Mapa de calor]

A partir do mapa de calor, podemos observar que:

- As variáveis que possuem maior correlação positiva são `number_of_reviews` e `reviews_per_month`, com um coeficiente de 0.54, o que indica que quanto mais avaliações um imóvel recebe, mais frequentemente ele é avaliado.
- As variáveis que possuem maior correlação negativa são `price` e `number_of_reviews`, com um coeficiente de -0.15, o que indica que quanto mais caro é um imóvel, menos avaliações ele recebe.
- As demais variáveis possuem correlações muito fracas, inferiores a 0.1 em valor absoluto, o que indica que elas não têm uma relação significativa entre si.

Continuando com a limpeza dos dados, após remover os outliers e tratar os valores ausentes, podemos prosseguir com a análise exploratória mais aprofundada, focando em insights específicos que possam ser extraídos dos dados do Airbnb.

### Distribuição dos preços de aluguel

Com os dados limpos, uma análise interessante é verificar a distribuição dos preços de aluguel. Vamos plotar um histograma para visualizar essa distribuição.

```python
# Plotar o histograma dos preços de aluguel
df_clean['price'].hist(bins=50, figsize=(15,5))
plt.xlabel('Preço')
plt.ylabel('Quantidade')
plt.title('Distribuição dos preços de aluguel')
plt.show()
```

Esse histograma nos ajudará a entender melhor a faixa de preço mais comum dos aluguéis e identificar se há uma concentração de imóveis em determinadas faixas de preço.

### Análise dos tipos de imóveis mais alugados

Outro ponto de interesse é analisar os tipos de imóveis mais alugados na plataforma. Podemos contar a quantidade de cada tipo de imóvel disponível e plotar um gráfico de barras para ilustrar esses dados.

```python
# Contar a quantidade de cada tipo de imóvel disponível
df_clean['room_type'].value_counts().plot(kind='bar', figsize=(10,5))
plt.xlabel('Tipo de Imóvel')
plt.ylabel('Quantidade')
plt.title('Quantidade de imóveis por tipo de aluguel')
plt.xticks(rotation=45)
plt.show()
```

Com esse gráfico, podemos comparar a popularidade dos diferentes tipos de aluguel, como casas/apartamentos inteiros, quartos privados e quartos compartilhados.

### Localidades mais caras de São Paulo

Uma análise valiosa para quem deseja alugar um imóvel é saber quais são as localidades mais caras da cidade. Podemos calcular o preço médio do aluguel por bairro e exibir os dez bairros mais caros.

```python
# Calcular o preço médio por bairro
df_clean.groupby('neighbourhood')['price'].mean().sort_values(ascending=False)[:10].plot(kind='bar', figsize=(15,5))
plt.xlabel('Bairro')
plt.ylabel('Preço Médio de Aluguel')
plt.title('Preço médio de aluguel por bairro em São Paulo')
plt.xticks(rotation=45)
plt.show()
```

Esse gráfico nos mostra onde estão localizados os aluguéis mais caros e pode ser útil para quem está planejando uma viagem ou busca por hospedagem na cidade.

### Relação entre preço e disponibilidade

Por fim, podemos investigar se há uma relação entre o preço do aluguel e a disponibilidade do imóvel ao longo do ano. Para isso, vamos criar um gráfico de dispersão (scatter plot) para visualizar essa possível correlação.

```python
# Plotar um gráfico de dispersão entre preço e disponibilidade
plt.figure(figsize=(10,5))
sns.scatterplot(data=df_clean, x='price', y='availability_365', alpha=0.5)
plt.xlabel('Preço')
plt.ylabel('Disponibilidade ao longo do ano')
plt.title('Relação entre preço e disponibilidade dos imóveis')
plt.show()
```

Esse gráfico pode indicar se imóveis com maior disponibilidade tendem a ter preços mais altos ou mais baixos e ajudar na tomada de decisão de potenciais locatários.

Com essas análises, concluímos nosso projeto de data science com uma exploração detalhada dos dados do Airbnb para a cidade de São Paulo. Esperamos que as informações e insights gerados sejam úteis para entender melhor o mercado de aluguel de curta duração e auxiliar em futuras decisões relacionadas a hospedagens. 😊

Eu vou continuar e finalizar o artigo. Por favor, aguarde um momento enquanto eu escrevo o artigo. 😊

Finalizando o artigo:

## Conclusão

Neste artigo, realizamos um projeto de data science completo com pandas, numpy e seaborn, usando os dados do Airbnb, a maior empresa hoteleira da atualidade, que não possui nenhum hotel.

O Airbnb é uma plataforma de hospedagem alternativa que conecta pessoas que querem viajar (e se hospedar) com anfitriões que querem alugar seus imóveis de maneira prática, segura e com bom custo-benefício.

Usamos os dados referentes à cidade de São Paulo, no Brasil, para explorar e responder algumas questões sobre o mercado de hospedagem na capital paulista, como:

- Qual é a distribuição dos preços de aluguel?
- Quais são os tipos de imóveis mais alugados?
- Quais são as localidades mais caras de São Paulo?
- Existe uma relação entre o preço e a disponibilidade dos imóveis?

Para isso, seguimos as seguintes etapas:

- Obtenção dos dados: baixamos o arquivo `listings.csv` do portal [Inside Airbnb], que contém um resumo das informações e métricas para cada imóvel disponível na cidade de São Paulo.
- Análise dos dados: realizamos uma análise exploratória dos dados, buscando entender a estrutura, a qualidade e as características dos dados que temos.
- Limpeza dos dados: realizamos uma limpeza dos dados, removendo ou substituindo os valores que podem prejudicar a nossa análise, como valores ausentes e outliers.
- Análise exploratória mais aprofundada: realizamos uma análise exploratória mais detalhada, focando em insights específicos que possam ser extraídos dos dados do Airbnb.

Com essas análises, concluímos nosso projeto de data science com uma exploração detalhada dos dados do Airbnb para a cidade de São Paulo. Esperamos que as informações e insights gerados sejam úteis para entender melhor o mercado de aluguel de curta duração e auxiliar em futuras decisões relacionadas a hospedagens. 😊

Obrigado por acompanhar este artigo até o final. Se você gostou, deixe um comentário, uma sugestão ou uma crítica.