EXPLORANDO DADOS DO AIRBNB

NEW YORK | RIO DE JANEIRO

Por Hyan Dias Tavares • Nov 04, 2021

AIRBNB

RIO DE JANEIRO

NEW YORK

DADOS

Um comparativo dos mercados hoteleiros

Quando você pensa em viajar e conhecer novos lugares, qual é a primeira plataforma que vem a sua mente para alugar um alojamento? Se pensou no Airbnb, saiba que você é um dos 150 milhões de pessoas que também escolheriam ele.

O Airbnb já é considerado como a maior empresa hoteleira da atualidade. E um detalhe importante, eles não possuem nenhum hotel!

Ele conecta pessoas que querem viajar (e se hospedar) com anfitriões que querem alugar seus imóveis de maneira prática. O Airbnb fornece uma plataforma inovadora para tornar essa hospedagem alternativa.

A startup foi fundada em 2008, na Califórnia (EUA) e ganhou o mundo. E mesmo em um momento pandêmico, sua receita no primeiro trimestre de 2021 foi de US $ 887 milhões, um valor 5% maior que o primeiro trimestre de 2020.

Mas algo que leva a discussões são as ações estratégicas que o Airbnb toma para atrair novos anfitriões, principalmente quando comparado aos mercados hoteleiros do Brasil com o dos Estados Unidos.

E como bons Rebels que somos, iremos explorar os dados de ambos os mercados em busca de entender as características, diferenças e deficiências. E para isso vamos escolher duas grandes cidades famosas pelo turismo, ambas estão localizadas em litorais.

Lembrando que o nosso objetivo é introduzir você na análise de dados e mostrar algumas técnicas que poderão ser replicadas para outros cenários. Mas fique tranquilo e não se assuste, irão haver outros artigos/projetos que nos iremos debulhar mais profundamente algumas técnicas e ferramentas. Quero apenas que você consiga desenvolver a mentalidade e entender a importância do uso de dados para desenvolvimento de ações estratégicas, principalmente no marketing.

New York: The big apple

Uma das maiores cidades do mundo, conhecida pelas corridas de cavalos, pubs de jazz e o grande volume de turistas.

Ela atrai anualmente cerca de 36 milhões de visitantes, como previsto pelo NYC & Company.

New York tem:

Distritos
0
Bairros
0
Habitantes
0 M
Extensão territorial
0 km

Curiosidade: 37% dos nova-iorquinos nasceram em outros países.

A origem do seu apelido “Big Apple” gerou debates durante alguns anos, mas segundo historiadores, o nome surgiu através de uma crítica do escritor Edward S. Martin, sobre a distribuição de renda dos americanos, descrevendo como os Estados Unidos fosse uma grande árvore e os estados seus frutos. Fazendo questionar se New York era apenas mais um dos frutos dessa árvore, por que a “Grande Maçã” deveria receber uma parte desproporcional da riqueza do país?

Sei que nesse momento você está se questionando, o que isso tem relação com a análise de dados e o Airbnb?

Lembre-se que dados são apenas números, e para gerar informação é preciso conectá-los a fatos históricos e presentes”.

New York é uma cidade que cresceu impactada diretamente pelas políticas públicas e também pelas ações de corporações privadas além de ter sido capital dos Estados Unidos quando ainda era colônia britânica. E como bons analistas não escolhemos essa cidade à toa, pois essa é uma característica que se assemelha  a cidade brasileira na qual iremos compará-la, o Rio de Janeiro, que também já foi capital do brasil quando ainda era uma colônia portuguesa.

Rio de Janeiro: Cidade maravilhosa

Uma das maiores metrópoles, que atrai turistas do mundo inteiro, especialmente por suas belezas naturais, carnaval e boemia.

1.2 milhões de turistas internacionais vão ao Rio todos os anos, de acordo com o governo brasileiro.

Rio de Janeiro tem:

Distritos
0
Bairros
0
Habitantes
0 M
Extensão territorial
0 km

Curiosidade: o Rio tem a maior floresta urbana do mundo, que corresponde a 10% do seu território.

A expressão “cidade maravilhosa” ainda é alvo de muitas teorias, entre todas a mais plausível, foi quando um jornal “O Paiz” se referiu ao Rio de Janeiro durante o carnaval de 1904, expressando sua admiração pela calorosa alegria dos cidadãos. A partir desse momento muitos jornalistas, escritores, músicos e poetas começaram a usar essa expressão, que chegou a virar o hino da cidade.

E isso reflete especialmente na personalidade cultural dos moradores, são pessoas que amam e admiram sua cidade, efeito esse na qual New York também é conhecida.

Mas chega de introdução e vamos direto ao ponto. Esse é o momento que vamos utilizar algumas técnicas para carregar, tratar e analisar nossos dados.

E para essa tarefa iremos usar a linguagem de programação Python, pelos fatores de:

  • Ser uma linguagem Open-Source
  • Ter uma curva de aprendizado rápida
  • E ter muitos pacotes, que simplifica nosso trabalho.

Obtenção de dados

Para quem não sabe, o Airbnb possui um projeto na qual disponibiliza os dados das principais cidades do mundo, por meio do portal Inside Airbnb. Seu objetivo é fornecer dados que quantifiquem o impacto dos aluguéis, incentivando o desenvolvimento de soluções em Data Science que ajude comunidades residenciais e de habitação.

O primeiro passo é entrar no portal e escolher as cidades na qual você irá analisar, minha sugestão é usar os arquivos listings.csv, pois contém informações mais resumidas e focadas para nossas necessidades.

Atenção: O portal está em constante mudança, e existe a possibilidade do conjunto de dados utilizados ser atualizado ou removido, não estando mais disponível, o que poderá trazer erros no código.

E para resolver isso, disponibilizei os arquivos New York e Rio de Janeiro, diretamente do meu Dropbox, para que possa replicar esse processo em outros momentos.

Vamos importar todos os pacotes e módulos que iremos utilizar. Bora abrir sua IDE ou o google colab.

In [1]:

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

import seaborn as sns

from IPython.display import display

from matplotlib import pyplot

%matplotlib inline

Uma dica para quem usar o Dropbox, quando você gera um link para compartilhar o seu Dataset (csv), note que no final do link vai haver o código dl=0, altere ele para dl=1, assim você irá informar ao Dropbox que queremos o arquivo Excel e não o HTML.

Vamos importar os arquivos listings.csv para os dataframe dfNY (New York) e dfRJ (Rio de Janeiro).

Descobrindo e explorando

Esse é o momento onde vamos ter o primeiro contato com o dataframe. Precisamos entender quais informações estão contidas dentro dele, como está estruturado, o que é cada variável e assim por diante. E como sou bonzinho já vou deixar aqui o dicionário de variáveis.

id – O número de identificação do imóvel.

name – Nome da propriedade anunciada.

hot_id – O número de identificação do proprietário (anfitrião) do imóvel.

neighbourhood_group – É um conjunto de grupos de bairros.

latitude – Coordenada de Latitude do imóvel.

longitude – Coordenada de Longitude do imóvel.

room_type – O tipo de quarto oferecido.

price – Preço por pernoite do imóvel a ser alugado na moeda local.

minimum_nights – Noites mínimas para locação.

number_of_reviews – Quantidade de avaliações que o imóvel recebeu.

last_review – Data da última avaliação.

reviews_per_month – Quantidade de avaliações por mês.

calculated_host_listings_count – Quantidade de imóveis do mesmo anfitrião.

availability_365 – Número total de dias em que o anúncio está disponível durante o ano.

number_of_reviews_ltm – Quantidade de avaliação nos últimos 12 meses.

license – Esta coluna não contém nenhum valor válido.

Vamos investigar os dados de cada dataframe e analisar as 5 primeiras entradas com os comandos.

In [3]:

display(dfNY.head(5))

display(dfRJ.head(5))

Out [3]:

New York

idnamehost_idhost_nameneighbourhood_groupneighbourhoodlatitudelongituderoom_typepriceminimum_nightsnumber_of_reviewslast_reviewreviews_per_monthcalculated_host_listings_countavailability_365number_of_reviews_ltmlicense
35136Spacious Brooklyn Duplex, Patio + Garden7378RebeccaBrooklynSunset Park4066265-7399454Entire home/apt275522021-08-08 00:00:000.0212041NaN
02595Skylit Midtown Castle2845JenniferManhattanMidtown4075356-7398559Entire home/apt15030482019-11-04 00:00:000.3333400NaN
13831Whole flr w/private bdrm, bath & kitchen(pls r...4869LisaRoxanneBrooklynBedford-Stuyvesant4068494-7395765Entire home/apt7614082021-06-29 00:00:005.03120858NaN
45178Large Furnished Room Near B'way8967ShunichiManhattanMidtown4076457-7398317Private room6824902021-08-14 00:00:003.64124317NaN
25121BlissArtsSpace!7356GaronBrooklynBedford-Stuyvesant4068535-7395512Private room6030502016-06-05 00:00:000.5413650NaN

Rio de Janeiro

idnamehost_idhost_nameneighbourhood_groupneighbourhoodlatitudelongituderoom_typepriceminimum_nightsnumber_of_reviewslast_reviewreviews_per_monthcalculated_host_listings_countavailability_365number_of_reviews_ltmlicense
017878Very Nice 2Br in Copacabana w. balcony, fast WiFi68997MatthiasNaNCopacabana-2296599-4317940Entire home/apt35042652021-05-21 00:00:002.07131412NaN
124480Nice and cozy near Ipanema Beach, w/ home office99249GoyaNaNIpanema-2298405-4320189Entire home/apt2973852017-04-22 00:00:000.861300NaN
225026Beautiful Modern Decorated Studio in Copa102840VivianeNaNCopacabana-2297735-4319105Entire home/apt16072382019-04-27 00:00:001.8622660NaN
335636Cosy flat close to Ipanema beach153232PatriciaNaNIpanema-2298839-4319232Entire home/apt27121812019-12-06 00:00:001.9211510NaN
435764COPACABANA SEA BREEZE - RIO - 20 X Superhost153691Patricia Miranda & PauloNaNCopacabana-2298107-4319136Entire home/apt12133712019-06-15 00:00:003.0513035NaN

Entrada e atributos

Precisamos entender qual o volume de dados que possuímos para ambos os dataframes. Lembrando que estamos usando uma versão com dados resumidos, se quiser fazer uma análise mais profunda, sugiro utilizar os arquivos listings.csv.gz.

In [4]:

print(f'New York\nEntradas: {dfNY.shape[0]}\nVariáveis: {dfNY.shape[1]}\n')

print(f'Rio de Janeiro\nEntradas: {dfRJ.shape[0]}\nVariáveis: {dfRJ.shape[1]}\n')

Out [4]:

New York

Entradas: 36923

Variáveis: 18

 

Rio de Janeiro

Entradas: 23414

Variáveis: 18

New York possui um volume de entradas superior ao do Rio de Janeiro, provavelmente pelo fato de apresentar uma população maior, além de receber mais turistas. Mas essa diferença não será significativa para a nossa análise. Já que iremos observar mais os comportamentos e frequências do que suas intensidades.

Os atributos dos dados ou tipos primitivos, são os formatos dos dados no qual a linguagem (Python) irá interpretar. E te apresentarei 3 que são os mais importantes no momento.

  • string: para conjunto de caracteres (“zero” – “pyh30” – “20”).
  • int: números inteiros (0 – 9 – 80).
  • float: número real (0,92 – 1,25 – 1500,5).

O python interpreta que tudo é um objeto (object), ou seja, quando não se sabe o atributo, ele entende que aquilo é uma string. E para examinarmos os atributos das nossas variáveis bastas digitar.

In [5]:

display(dfNY.dtypes)

Out [5]:

Tipo dos dados por variáveis
id                                                            int64
name                                                   object
host_id                                                  int64
host_name                                        object
neighbourhood_group                  object
neighbourhood                                object
latitude                                              float64
longitude                                          float64
room_type                                          object
price                                                       int64
minimum_nights                               int64
number_of_reviews                           int64
last_review                                         object
reviews_per_month                        float64
calculated_host_listings_count      int64
availability_365                                    int64
number_of_reviews_ltm                   int64
license                                                float64
dtype:   object

Todos os dados parecem fazer sentido aos seus atributos. Uma exceção é a variável last_review que são datas, mas nosso dataframe entende que ele é uma string. Para isso precisamos mudar ele para o atributo datatime64, que é um atributo específico para datas.

In [6]:

dfNY.last_review = pd.to_datetime(dfNY.last_review, format="%Y-%m-%d")

dfRJ.last_review = pd.to_datetime(dfRJ.last_review, format="%Y-%m-%d")

Se você é esperto, já deve ter notado que o price do Rio de Janeiro é diferente do New York, pelo fato de um país usar a moeda em Dólar e o outro em Real. Para ter um comparativo mais justo e equalizado, é preciso converter o price de New York de Dólar para Real, então faremos isso usando a média das cotações de câmbio de cada ano.

Desta forma, criamos uma nova coluna com apenas os anos da última avaliação, e usando a função mask, relacionamos como restrição a data para usar a cotação média daquele ano respectivo.

In [7]:

import datetime as dt

dfNY['year'] = dfNY.last_review.dt.year

dfNY.price = dfNY.price.mask(dfNY.year <= 2011, (dfNY.price * 1.674))

dfNY.price = dfNY.price.mask(dfNY.year == 2012, (dfNY.price * 1.954))

dfNY.price = dfNY.price.mask(dfNY.year == 2013, (dfNY.price * 2.157))

dfNY.price = dfNY.price.mask(dfNY.year == 2014, (dfNY.price * 2.353))

dfNY.price = dfNY.price.mask(dfNY.year == 2015, (dfNY.price * 3.331))

dfNY.price = dfNY.price.mask(dfNY.year == 2016, (dfNY.price * 3.489))

dfNY.price = dfNY.price.mask(dfNY.year == 2017, (dfNY.price * 3.190))

dfNY.price = dfNY.price.mask(dfNY.year == 2018, (dfNY.price * 3.654))

dfNY.price = dfNY.price.mask(dfNY.year == 2019, (dfNY.price * 3.943))

dfNY.price = dfNY.price.mask(dfNY.year == 2020, (dfNY.price * 5.155))

dfNY.price = dfNY.price.mask(dfNY.year == 2021, (dfNY.price * 5.352))

Valores ausentes

Tratar os valores ausentes corretamente é uma das partes importantes da análise de dados. Os valores ausentes podem ser representados de muitas maneiras, entre elas como nulos, células vazias, com o valor NAN ou um valor artificial como 9999.

E para identificar a quantidade de valores ausentes de cada dataframe, usaremos o isnull().sum(). E também criaremos uma lista com os dados para podermos compará-los usando o comando pd.DataFrame.

In [8]:

variaveis = ['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',

      'number_of_reviews_ltm',

      'license']




vz = []

dado = []

for i in variaveis:

  dado.append(dfNY[i].isnull().sum() / dfNY[i].shape[0])

  dado.append(dfRJ[i].isnull().sum() / dfRJ[i].shape[0])

  vz.append(dado[:])

  dado.clear()

vz  




pd.DataFrame(vz, columns=['New York', 'Rio de Janeiro'], index=variaveis)

Out [8]:

New YorkRio de Janeiro
id0.0000000.000000
name0.0003520.000897
host_id0.0000000.000000
host_name0.0030060.000769
neighbourhood_group0.0000001000000
neighbourhood0.0000000.000000
latitude0.0000000.000000
longitude0.0000000.000000
room_type0.0000000.000000
price0.0000000.000000
minimum_nights0.0000000.000000
number_of_reviews0.0000000.000000
last_review0.2517670.356240
reviews_per_month0.2517670.356240
calculated_host_listings_count0.0000000.000000
availability_3650.0000000.000000
number_of_reviews_ltm0.0000000.000000
license10000001000000
  • As variáveis name e host_name tem aproximadamente menos de 0,3% dos valores ausentes.
  • O neighbourhood_group do dataframe do Rio de Janeiro e o licence de ambos os dataframe estão com 100% dos seus valores faltantes.
  • O last_review e reviews_per_month estão com 25,17% dos valores ausentes no dataset do New York e 35,62% no dataset do Rio.

É muito importante fazermos a limpeza desses dados ausentes e deixar apenas valores que serão úteis.

Como as variáveis name e host_name, possuem um percentual baixo de valores ausentes, nós iremos eliminar essas linhas, já que não irá interferir na análise. E para isso iremos criar um novo dataframe com os nomes de dfNY_clean (dados limpos do New York) e dfRJ_clean (dados limpos do Rio de Janeiro).

In [9]:

dfNY_clean = dfNY.dropna(subset=['name', 'host_name'], axis=0)

dfRJ_clean = dfRJ.dropna(subset=['name', 'host_name'], axis=0)

Já para o reviews_per_month e last_review, o percentual de valores ausentes é alto e com certeza eliminar eles impactaria nos resultados. Por esse fator iremos substituir os valores ausentes pela mediana de cada variável.

In [10]:

#reviews per month NY

rpm_ny_median = dfNY_clean.reviews_per_month.median()

dfNY_clean = dfNY_clean.fillna({"reviews_per_month": rpm_ny_median})




#last_review NY

lr_ny_median = dfNY_clean['last_review'].astype('datetime64[ns]').quantile(0.5, interpolation="midpoint")

dfNY_clean = dfNY_clean.fillna({"last_review": lr_ny_median})




#reviews per mouth RJ

rpm_rj_median = dfRJ_clean.reviews_per_month.median()

dfRJ_clean = dfRJ_clean.fillna({"reviews_per_month": rpm_rj_median})




#last review RJ

lr_rj_median = dfRJ_clean['last_review'].astype('datetime64[ns]').quantile(0.5, interpolation="midpoint")

dfRJ_clean = dfRJ_clean.fillna({"last_review": lr_ny_median})

Distribuição das variáveis

Quando falamos de distribuição de variáveis, temos sempre o objetivo de identificar outliers (ou Pontos discrepantes), que são dados que se diferenciam drasticamente de todos os outros. Em outras palavras, um outlier é um valor que foge da normalidade e que pode causar anomalias nos resultados obtidos, como subir excessivamente o valor da média aritmética de um conjunto de dados.

E para identificarmos os outliers, iremos plotar o gráfico de boxplot, para poder observar a distribuição dos valores.

Iremos analisar o price e o minimum_nights, já que essas duas variáveis são as mais importantes a serem observadas.

In [11]:

dx0 = ['price', 'minimum_nights']




for n in dx0:

    data_a = dfNY_clean[n]

    data_b = dfRJ_clean[n]

    data_2d=[data_a,data_b]

    plt.boxplot(data_2d, vert=False, labels=["New York", "Rio de Janeiro"])

    plt.title(n)

    plt.show()

Out [11]:

O aviso que aparece na hora de plotar o boxplot é originado pelo fato do dataframe do New York ser maior (quantidade de entradas) que o do Rio de Janeiro, criando uma sinalização de alerta, mas não quer dizer que há um erro, já que a função plt.boxplot da ênfase em usar sempre a mesma quantidade de dados para comparar.

Note que para ambas as variáveis e dataframes existem valores discrepantes, é um pouco óbvio notar que não existe realmente um imóvel que possua um price (preço) de R$ 600.000 por noite no Rio de Janeiro, provavelmente é um erro de cadastro ou do sistema.

Isso ocorre também com o minimum_nights, pois é quase improvável existir ofertas de imóveis onde o usuário tenha que ficar no mínimo 3 anos hospedado.

Esses valores (outliers) interferem na média e desvio padrão da amostra, deixando mais complicado identificar um padrão ou tirar uma informação relevante.

Remoção dos outliers

Existem alguns métodos para remover os outliers, como o métodos baseados em distância e o baseado no desvio padrão, entre outros. 

Vamos utilizar o conceito do boxplot, uma técnica mais genérica, que identifica outliers todos os pontos que estão fora dos quartis superior e inferior [25% – 75%]. Só lembrando que esse não é o método mais eficiente. 

Mas para dar início precisamos analisar os dados estatísticos, como a média, desvio padrão, mediana e seus 1° e 3° quartil. Utilizando o comando describe().

In [12]:

# New York

dfNY_clean[['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month', 'calculated_host_listings_count', 'availability_365']].describe()




# Rio de Janeiro

dfRJ_clean[['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month', 'calculated_host_listings_count', 'availability_365']].describe()

Out [12]:

New York

priceminimum_nightsnumber_of_reviewsreviews_per_monthcalculated_host_listings_countavailability_365
count367990000003679900000036799000000367990000003679900000036799000000
mean6016886562213011223047827119978913442920123594255
std11007697392794375949455410353431745067787138273265
min0.00000010000000.0000000.01000010000000.000000
0.25200000000300000010000000.18000010000000.000000
0.53930000003000000040000000.440000100000061000000
0.75706464000300000002000000010000003000000264000000
max5352000000012500000001006000000163190000307000000365000000

Rio de Janeiro

priceminimum_nightsnumber_of_reviewsreviews_per_monthcalculated_host_listings_countavailability_365
count233750000002337500000023375000000233750000002337500000023375000000
mean7117395945283209140957860.5150497236791229120171
std493963246620863285332848450.75114221707342130198335
min0.00000010000000.0000000.01000010000000.000000
0.2515000000010000000.0000000.160000100000090000000
0.5270000000200000020000000.2700001000000264000000
0.755480000004000000110000000.4800003000000362000000
max621850000000100000000048600000025520000187000000365000000

Observando os dados podemos confirmar algumas hipóteses:

  • A variável price do Rio de Janeiro possui 75% dos valores abaixo de RS 548,00 porém seu valor máximo é R$ 621.850,00
  • A variável price do New York possui 75% dos valores abaixo de R$ 706,46 porém seu valor máximo é R$ 53.520,00
  • E o 3° quartil (75% dos valores) da minimum_nights no Rio de janeiro e New York está abaixo de 4 e 30 dias, respectivamente.

Agora que confirmamos quais os valores acima dos limites do 3° quartil, iremos removê-los. Vamos também arredondar para cima esse valor, com o intuito de garantir que apareça bem o limite superior do nosso boxplot. Só dando ênfase, estamos apenas analisando o price e o minimum_nigths

Para fazer essa limpeza, iremos criar um novo dataframe o dfNY_out (dados sem outliers New York) e o dfRJ_out (dados sem outliers Rio de Janeiro).

In [13]:

# New York

dfNY_out = dfNY_clean.copy()

dfNY_out.drop(dfNY_out[dfNY_out.price > 1100].index, axis=0, inplace=True)

dfNY_out.drop(dfNY_out[dfNY_out.minimum_nights > 65].index, axis=0, inplace=True)

# Rio de Janeiro

dfRJ_out = dfRJ_clean.copy()

dfRJ_out.drop(dfRJ_out[dfRJ_out.price > 600].index, axis=0, inplace=True)

dfRJ_out.drop(dfRJ_out[dfRJ_out.minimum_nights > 4].index, axis=0, inplace=True)

Basta agora reproduzir o boxplot como o anterior, mas desta vez utilizando os novos dataframes {cod [11]}. E vamos ver claramente que não haverá pontos discrepantes.

Out [14]:

Feito tudo isso, agora podemos ter uma visão mais clara dos nossos dados e enfim fazer um comparativo entre New York e Rio de Janeiro. Para esse propósito, iremos analisar a distribuição através de um histograma.

In [15]:

dx = ['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month',
      'calculated_host_listings_count', 'availability_365']

for n in dx:
 if dfNY_out[n].max() >= dfRJ_out[n].max():
    maior = int(dfNY_out[n].max())
  else:
    maior = int(dfRJ_out[n].max())
 bins = np.linspace(0, maior, 15)
  pyplot.hist(dfRJ_out[n], bins, alpha=0.5, label='Rio de Janeiro')
  pyplot.hist(dfNY_out[n], bins, alpha=0.5, label='New York')
  pyplot.legend(loc='upper right')
 pyplot.title(n
  pyplot.show()

Out [15]:

Esse é o momento mais aguardado, analisar os resultados. Não vamos gerar no primeiro momento insights, apenas constatar alguns números. Então bora lá.

  • A distribuição (desvio padrão) e média do price em New York é maior que no Rio de Janeiro.
  • No Rio de Janeiro o minimum_nights está em um intervalo de 1 a 5 dias, enquanto em New York varia entre 25 e 30 dias, além de também apresentar demandas para 1 a 5 dias.
  • O availability_365 ou o tempo de anúncio do imóvel no Rio de janeiro fica quase 365 dias disponíveis, enquanto que em New York os anúncios em geral ficam apenas por 30 dias.

Correlacionando as variáveis

Estudar a correlação que existe entre as variáveis pode ser muito útil, se identificado algum fator. A correlação mede a direção e o grau de associação linear entre as variáveis, ou seja, quando uma variável pode influenciar outra. E para interpretar os dados gerados na correlação, precisamos saber.

  • A intensidade da relação é um valor entre 0 e 1, sendo que cada vez mais próximo de 1 maior é a sua correlação
  • Se for um valor positivo, ela é uma correlação proporcional, ou seja, se uma variável aumentar a outra aumenta também.
  • Se for um valor negativo, ela será uma correlação inversamente proporcional, ou seja, se uma variável aumentar a outra diminui.

Para gerar a correlação usamos a função corr() e para plotar um mapa de calor usamos a função sns.heatmap(). Vamos começar por New York.

In [16]:

corr = dfNY_out[['price', 'minimum_nights', 'number_of_reviews', 'reviews_per_month',
    'calculated_host_listings_count', 'availability_365']].corr()

sns.heatmap(corr, cmap='RdBu', fmt='.2f', square=True, linecolor='white', annot=True);

Out [16]:

Iremos repetir o processo {cod [16}, mas desta vez vamos usar o dataframe do Rio de Janeiro

Out [17]:

As correlações não apresentaram muita intensidade, com exceção as variaveis number_of_reviews e reviews_per_month, que na qual é o mesmo valor, só que uma delas tem uma relação com o tempo. Nada que não nos surpreendesse.

Analisando os imóveis mais alugados

Quando falamos em compreender as características do mercado hoteleiro de ambas as cidades, precisamos entender quais os tipos de imóveis mais ofertados. 

O Airbnb classifica seus imóveis em 4 categorias (room_type), na qual o anfitrião deve escolher, para disponibilizar aos usuários, são eles:

  • Entire home/apt: Casa ou apartamento inteiro (todos os cômodos)
  • Private room: Quarto privado
  • Shared room: Quarto compartilhado com outras pessoas
  • Hotel room: Quarto de hotel

Para gerar esse comparativo, vamos fazer ele em duas etapas, a primeira é criar uma lista com o percentual de cada categoria para cada dataframe. E após isso, criaremos um histograma horizontal e colocaremos lado a lado cada cidade com seus respectivos percentuais de cada tipo de imóvel ofertado.

In [18]:

var = ['Entire home/apt',
       'Private room',
       'Shared room',
       'Hotel room']

dado_var = {}
for i in var:
  dado_var[i] = [dfNY_out.loc[dfNY_out.room_type == i].shape[0] / dfNY_out.room_type.shape[0] , dfRJ_out.loc[dfRJ_out.room_type == i].shape[0] / dfRJ_out.room_type.shape[0]]

ima = pd.DataFrame(dado_var, index=[
'New York', 'Rio de Janeiro'])
ima.plot(kind="barh",stacked=True,figsize=(6,4), color=['c', 'm', 'y', 'orange'])
plt.legend(loc="lower left",bbox_to_anchor=(0.8,1.0))
plt.show()

Out [18]:

Fica claro entender que New York tem uma disponibilidade dos tipos imóveis bem equiparadas entre o modelo Entire home/apte e o private room, chegando a um percentual próximo de 50% cada.

Já no Rio de Janeiro, nota-se que a disponibilidade é maior para Entire home/apt (67,6%).

Localidades mais caras

Entender a importância da localização na valorização do imóvel é um fator que contribui muito na recorrência do aluguel e na lucratividade do mesmo. Para especialistas imobiliários, o valor de um imóvel está ligado a:

  • Infraestrutura do bairro.
  • Tamanho do imóvel.
  • Segurança.
  • Conveniências próximas.
  • Entre outros aspectos.

Mesmo sendo um especialista não é nada fácil precificar. Mas podemos chegar bem próximo de entendermos os valores que já são negociados no momento. 

New York

Para isso vamos ver a média dos valores comercializados em cada bairro e ordenar por ordem decrescente, do mais caro para o mais barato.

In [19]:

dfNY_out.groupby(['neighbourhood']).price.mean().sort_values(ascending=False)[:10]

Out [19]:

neighbourhood

Neponsit                           1070.40

Belle Harbor                      984.34

Fort Wadsworth               800.00

Lighthouse Hill                  773.25

Dongan Hills                      752.03

Howland Hook                   741.25

Oakwood                            665.36

Breezy Point                       642.15

Douglaston                        638.67

Grymes Hill                         637.52

Name: price, dtype: float64

O nosso dataframe possui a variável neighbourhood.group, utilizando ela vamos conseguir ter uma visão mais abrangente, realista e entregando de uma forma que qualquer leigo em New York consegue entender. Por exemplo, muito mais pessoas entende o que é Manhattan, Queens e Brooklyn do que a diferença entre Flushing, Astoria, Hell’s Kitchen e Tribecca.

In [20]:

dfNY_out.groupby(['neighbourhood_group']).price.mean().sort_values(ascending=False)[:10]

Out [20]:

neighbourhood_group

Manhattan                  444.00

Staten Island               425.03

Brooklyn                       389.08

Bronx                             337.36

Queens                         334.24

Name: price, dtype: float64

Observe que a diferença não é tão grande entre Belle Harbor, Gerritsen Beach e Neposit que são os bairros mais caros.

Tirando o fato que os três estão bem próximos um do outro e localizado perto Marine Parkway Bridge. Todas elas possuem poucos imóveis para serem locados, assim gerando um preço mais elevado, “relação demanda e oferta”.

Outro aspecto a se observar é fazermos uma correlação visual (mapa de calor) entre a localização geográfica versus preço. Mas para fazer um gráfico bonito, vamos usar o Folium, que é um pacote que permite a visualização de dados em um mapa de folheto interativo.

Para podermos utilizar o folium com mais performance, introduziremos os primeiros 16 mil dados do dataframe, pois valores acima dessa quantidade irão acarretar sobrecarga no processamento, não gerando a visualização do gráfico. E também utilizaremos o pacote branco, para criar uma legenda dos valores de preços em relação a tonalidade de cores em nosso mapa.

In [21]:

import folium
import branca

colormap = branca.colormap.linear.YlOrRd_09.scale(0, 1100)
colormap = colormap.to_step(index = [0, 275, 550, 825, 1100])
colormap.caption = 'Preços dos imóveis'

m = folium.Map(location=[40.691895, -73.902734], tiles="stamentoner", zoom_start=11)

lon = []
lat = []
value = []

data= {'lon': lon, 'lat': lat, 'value': value}
for n in range(0, dfNY_out.shape[0]):
 lon.append(dfNY_out.longitude.values[n])
 lat.append(dfNY_out.latitude.values[n])
 value.append(dfNY_out.price.values[n])

for i in range(0, 16000):
 preco = data['value'][i]
 if preco <= 275:
   print = '#f1f8d0'
 elif preco > 275 and preco <= 550:
   print = '#efc271'
 elif preco > 825 and preco <= 1100:
   print = '#e35d4d'
 else:
   print = '#8b2a40'
 folium.CircleMarker(
     location=[data['lat'][i], data['lon'][i]],
     radius= 2,
     popup='Laurelhurst Park',
     color= print,
     line_color= print,
     fill_color=print,
     fill=True).add_to(m)
colormap.add_to(m)
m

Out [21]:

E analisando o nosso mapa e o neighbourhood.group, identificamos que há uma alta demanda em Manhattan, sendo seus preços e quantidade de ofertas um pouco mais altos quando comparado a outros distritos. 

Não é à toa que Manhattan é a menina dos olhos de New York. É um dos lugares mais lindos do mundo, lá você encontra o Central Park, a Times Square, o Empire State Building e os grandes arranha-céus.

Ao sul de Manhattan está localizado o maior centro financeiro do mundo, que foi importante para a fundação da cidade, além de ser um dos pilares econômicos do país. Lá você pode encontrar o Wall Street, ou seja a rua onde fica localizada a bolsa de valores e outras empresas do mercado financeiro.

Rio de Janeiro

Agora vamos reproduzir os mesmos passos anteriores do neibourhood mas com os dados do Rio de Janeiro {Cod [19]}.

Out [22]:

neighbourhood

Ribeira                                500.00

Barros Filho                       500.00

Cascadura                          452.50

Pavuna                                383.50

Cavalcanti                          350.00

Paciência                           346.00

Higienópolis                      328.57

Leblon                                 320.05

Moneró                               309.00

Manguinhos                      300.00

Name: price, dtype: float64

Os dados do Rio de Janeiro não apresentam valores na coluna do neighbourhood.group, mas isso não será problema, basta inserir eles utilizando uma condição que relacionará o nome do bairro com a zona na qual fica.

In [23]:

zona_sul = ['Botafogo', 'Catete', 'Copacabana', 'Cosme Velho', 'Flamengo', 'Gávea', 'Glória', 'Humaitá', 'Ipanema','Jardim Botânico', 'Lagoa', 'Laranjeiras', 'Leblon', 'Leme', 'São Conrado', 'Urca', 'Vidigal', 'Rocinha']

zona_norte = ['Alto da Boa Vista', 'Andaraí', 'Grajaú', 'Maracanã', 'Praça da Bandeira', 'Tijuca', 'Vila Isabel', 'Água Santa', 'Cachambi', 'Del Castilho', 'Encantado', 'Engenho de Dentro', 'Engenho Novo', 

              'Higienópolis', 'Jacaré', 'Jacarezinho', 'Lins de Vasconcelos', 'Manguinhos', 'Maria da Graça', 'Méier', 'Piedade', 'Pilares', 'Riachuelo', 'Rocha', 'Sampaio', 'São Francisco Xavier', 'Todos os Santos', 

              'Bonsucesso', 'Bancários', 'Cacuia', 'Cidade Universitária', 'Cocotá', 'Galeão', 'Jardim Carioca', 'Jardim Guanabara', 'Maré', 'Moneró', 'Olaria', 'Pitangueiras', 'Portuguesa', 'Praia da Bandeira', 

              'Ramos', 'Ribeira', 'Tauá', 'Zumbi', 'Acari', 'Anchieta','Barros Filho', 'Bento Ribeiro', 'Brás de Pina', 'Campinho', 'Cavalcanti', 'Cascadura', 'Coelho Neto', 'Colégio', 'Complexo do Alemão', 'Cordovil', 

              'Costa Barros', 'Engenheiro Leal', 'Engenho da Rainha', 'Guadalupe', 'Honório Gurgel', 'Inhaúma', 'Irajá', 'Jardim América', 'Madureira', 'Marechal Hermes', 'Oswaldo Cruz', 'Parada de Lucas', 'Parque Anchieta', 

              'Parque Colúmbia', 'Pavuna', 'Penha', 'Penha Circular', 'Quintino Bocaiuva', 'Ricardo de Albuquerque', 'Rocha Miranda', 'Tomás Coelho', 'Turiaçu', 'Vaz Lobo', 'Vicente de Carvalho', 'Vigário Geral', 

              'Vila da Penha', 'Vila Kosmos', 'Vista Alegre', 'Freguesia (Ilha)']

zona_oeste = ['Anil', 'Barra da Tijuca', 'Camorim', 'Cidade de Deus', 'Curicica', 'Freguesia (Jacarepaguá)', 'Gardênia Azul', 'Grumari', 'Itanhangá', 'Jacarepaguá', 'Joá', 'Praça Seca', 'Pechincha', 'Rio das Pedras', 

               'Recreio dos Bandeirantes', 'Tanque', 'Taquara', 'Vargem Grande', 'Vargem Pequena', 'Vila Valqueire', 'Jardim Sulacap','Bangu', 'Campo dos Afonsos', 'Deodoro', 'Gericinó', 'Jabour', 'Magalhães Bastos', 

               'Padre Miguel', 'Realengo', 'Santíssimo', 'Senador Camará', 'Vila Kennedy', 'Vila Militar','Barra de Guaratiba', 'Campo Grande', 'Cosmos', 'Guaratiba', 'Inhoaíba', 'Paciência', 'Pedra de Guaratiba', 'Santa Cruz', 

               'Senador Vasconcelos', 'Sepetiba']

zona_centro = ['São Cristóvão', 'Benfica', 'Caju', 'Catumbi', 'Centro', 'Cidade Nova', 'Estácio', 'Gamboa', 'Lapa', 'Mangueira', 'Paquetá', 'Rio Comprido', 'Santa Teresa', 'Santo Cristo', 'Saúde', 'Vasco da Gama']

for s in zona_sul:

    dfRJ_out.neighbourhood_group = dfRJ_out.neighbourhood_group.mask(dfRJ_out.neighbourhood == s, 'Zona Sul')

for n in zona_norte:

    dfRJ_out.neighbourhood_group = dfRJ_out.neighbourhood_group.mask(dfRJ_out.neighbourhood == n, 'Zona Norte')

for o in zona_oeste:

    dfRJ_out.neighbourhood_group = dfRJ_out.neighbourhood_group.mask(dfRJ_out.neighbourhood == o, 'Zona Oeste')

for c in zona_centro:

    dfRJ_out.neighbourhood_group = dfRJ_out.neighbourhood_group.mask(dfRJ_out.neighbourhood == c, 'Centro')

dfRJ_out.groupby(['neighbourhood_group']).price.mean().sort_values(ascending=False)[:10]

Out [23]:

neighbourhood_group

Zona Oeste             261.39

Zona Sul                 247.96

Centro                     187.87

Zona Norte             179.89

Name: price, dtype: float64

O Rio de Janeiro é uma cidade turística, e quando avaliamos quais os bairros mais caros, percebemos que não aparece nenhum dos mais famosos, como Copacabana, Ipanema e Leme.

Podemos atribuir ao mesmo fator que analisamos em New York, no caso, os bairros mais caros possuem entre 1 a 2 ofertas de imóveis para serem alugados, ou seja, a média dos preços dos bairros está ligado diretamente a essas poucas ofertas.

Para reproduzir o nosso mapa, usaremos o mesmo código anterior {Cod [21]}, mas além de usar o dataframe do Rio, também mudaremos as escalas [0, 150, 300, 450, 600] e o location [-22.930925, -43.414593].

Out [24]:

Um fator interessante no mapa, é que os imóveis mais próximos das praias são os que aparentam ter maior preço médio, principalmente comparado a zona norte e centro.

Vou dar destaque as praias do Leblon e Ipanema, com seus barzinhos, espaços para esportes e a vista incrível para o Morro Dois Irmãos, que por sinal quem tiver a oportunidade de visitar, vale muito a pena, um dos lugares mais lindos que já fui.

A zona Oeste podemos destacar as praias da Tijuca, que é um lugar ideal para mergulhar, surfar e passear com a família. O motivo que o torna mais caro que a zona Sul (Copacabana Leblon, Ipanema …), por exemplo, é o fato de haver mais casas do que hotéis. Pois essa relação de braço de ferro entre hotéis e o Airbnb ajuda a harmonizar os preços e deixar mais próximo da realidade para as pessoas.

Resumo final da ópera

Para todo o processo de análise de dados é fundamental entender e explorar os dados do dataframe, identificar os valores nulos e os outliers. São passos que nos permitiram fazer um comparativo entre New York e Rio de Janeiro.

Ambas as cidades possuem muitas semelhanças, entre tanto, alguns comportamentos (nos dados) foi notado, entre eles:

 

Ticket médio

O ticket médio representa o valor médio gasto nos pedidos, quanto maior for o valor, mais os clientes estão gastando nos pedidos. É o indicador usado para avaliar o comportamento e satisfação dos clientes.

In [25]:

ticktNY = ( dfNY_out.price * dfNY_out.minimum_nights ).sum() / dfNY_out.shape[0]
ticktRJ = ( dfRJ_out.price * dfRJ_out.minimum_nights ).sum() / dfRJ_out.shape[0]
Ticket médio
R$ 0
Ticket médio
R$ 0

New York tem um Ticket médio muito maior que o Rio de Janeiro, fato esse não apenas influenciado pelo seus preços serem maior, mas também por ter a média do mínimo de noites aproxima de 30 dias, enquanto que no Rio, varia entre é 5 dias, valores esse 6 vezes menor que New York.

 

 

Tempo de exposição do anúncio

É uma métrica de desempenho das plataformas de marketplaces, que determina o tempo que um anúncio fica exposto na plataforma. Quanto maior o tempo de exposição, mais possibilidade de engajamento e conversão

Rio de Janeiro
0 dias
New York
0 dias

É fácil notar que no Rio de Janeiro tem um tempo de exposição dos anúncios maior que o de New York, isso não quer dizer que o Rio converte mais clientes, mas é um indício que os anfitriões precisam deixar mais tempo o anúncio para converter. Outra hipótese é que seja um fator característico dos anfitriões, ou seja, os proprietários dos imóveis no Rio de Janeiro não moram lá, consequentemente deixam seus imóveis o ano inteiro para gerar lucratividade, e podemos embasar esse argumento pelo fato dos tipos de imóveis mais alugados no Rio ser casas ou apartamentos inteiros.

Gerando soluções

Para nós que trabalhamos com marketing, essas são informações valiosas, que nos ajudariam a desenvolver soluções para esses anfitriões, como:

Para os anfitriões do Rio de Janeiro, podemos oferecer uma solução para campanhas de marketing customizada que tenham o objetivo de aumentar a frequência de locação dos imóveis.

Já para quem é de New York, pensamos em oferecer um recurso que ajude a precificar melhor seus imóveis de acordo com a sua localização, garantindo o máximo de lucratividade versus o tempo de exposição do anúncio.

Sei que foi uma caminhada longa nesse artigo, mas esse é o trabalho de quem vê o mundo através dos dados e assim gera inteligência com uma base forte. Então, meu caro marketeiro.

Prontos para começar do zero?

Arquivo Completo no Github

Deixe seu comentário

Oi, sou Hyan e aqui você vai encontrar tudo sobre marketing e tecnologia, assuntos esses na qual eu me dedico a aprender e me desafiar todas as manhãs.

CATEGORIAS

Airbnb • Marketing • imóveis • Analise • DataMarketing • Dados • Rio de Janeiro • New Yrok • Ausentes • Price • Mapa • Ticket médio • Anúncio

CRÉDITOS

Produção: Zero.ai

Texto: Hyan Dias Tavares

Revisão: Rafael Duarte

Revisão: Sílvia B. Canever

Ilustração: Hyan Dias Tavares

Inspiração: Sigmoidal

NEWSLATTER