Análise e Visualização de Dados de Preços Imobiliários com Big Data

0 Introdução

Hoje compartilharemos um projeto de conclusão de curso envolvendo big data: Análise e visualização de dados de preços imobiliários com código-fonte disponível.

Compartilhamento do Projeto: veja no final do artigo!

Resultados Implementados

Projeto de Conclusão de Curso - Análise Visual de Big Data de Preços Imobiliários

1 Contexto do Projeto

O setor imobiliário é uma indústria básica e dominante que promove o crescimento econômico contínuo da China. Como entender a distribuição regional dos preços imobiliários em uma cidade ou as diferenças regionais entre cidades diferentes? Como obter dados de preços de diferentes bairros de uma cidade? Este projeto utiliza Python para coletar informações relacionadas aos preços imobiliários em uma determinada cidade, realiza limpeza dos dados brutos coletados, armazena-os em um banco de dados e utiliza ferramentas como a biblioteca pyechart para exibições visuais.

2 Coleta de Dados

2.1 Introdução ao Web Scraping

Um web crawler é um programa ou script que automaticamente coleta informações da World Wide Web seguindo regras específicas. O crawler acessa um site específico; se o acesso for bem-sucedido, ele baixa o conteúdo da página web e analisa os links obtidos através do módulo de análise do crawler, adicionando esses links como alvos futuros de captura, operando completamente sem dependência do usuário. Se o acesso falhar, o crawler seguirá estratégias pré-definidas para acessar o próximo URL. Durante todo o processo, o crawler processa automaticamente as solicitações de dados de forma assíncrona e retorna os dados coletados. Antes do início da execução do crawler, o usuário pode adicionar manualmente proxies e cabeçalhos falsificados para melhor obtenção dos dados da web. Diagrama de fluxo do crawler:

Exemplo de Código

# Exemplo do método get

import requests # Primeiro importe a biblioteca do crawler, senão não poderá chamar as funções
response = requests.get("http://httpbin.org/get")  # Método get
print( response.status_code ) # Código de status
print( response.text )



2.2 Coleta de Preços Imobiliários

Coletamos um total de 18.906 registors de imóveis residenciais usados da Lianjia em Shenzhen

  • Coleta de informações de imóveis em cada distrito administrativo;
  • Dados salvos como DataFrame;

Código Relacionado

from bs4 import BeautifulSoup  
import pandas as pd
from tqdm import tqdm
import math
import requests  
import lxml
import re
import time


district_map = {'Luohu District':'luohuqu',
            'Futian District':'futianqu',
            'Nanshan District':'nanshanqu',
            'Yantian District':'yantianqu',
            'Bao'an District':'baoanqu',
            'Longgang District':'longgangqu',
            'Longhua District':'longhuaqu',
            'Pingshan District':'pingshanqu'}


# Adiciona header para respeito mútuo
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36',
           'Referer': 'https://sz.lianjia.com/ershoufang/'}

# Cria uma nova sessão
sess = requests.session()
sess.get('https://sz.lianjia.com/ershoufang/', headers=headers)

# Exemplo de URL: https://sz.lianjia.com/ershoufang/luohuqu/pg2/
url_template = 'https://sz.lianjia.com/ershoufang/{}/pg{}/'

# Quando a expressão regular falha, retorna valor padrão (fallback)
def regex_extract(pattern, text, default=None):
    try:
        return re.findall(pattern, text)[0].strip()
    except IndexError:
        return default

# Cria um novo DataFrame para armazenar informações
housing_data = pd.DataFrame()

for district_name, district_code in district_map.items():
    # Obtém o número de registros imobiliários no distrito
    start_url = 'https://sz.lianjia.com/ershoufang/{}/'.format(district_code)
    html_content = sess.get(start_url).text
    property_count = re.findall('共找到<span> (.*?) </span>套.*二手房', html_content)[0].strip()
    print('💚{}: Total de imóveis usados 「{}」 unidades'.format(district_name, property_count))
    time.sleep(1)
    # Limite de páginas 🚫 Cada distrito pode obter no máximo 100 páginas com 3000 imóveis
    max_pages = int(math.ceil(min(3000, int(property_count)) / 30.0))
    for page_idx in tqdm(range(max_pages), desc=district_name):
        html_content = sess.get(url_template.format(district_code, page_idx+1)).text
        soup = BeautifulSoup(html_content, 'lxml')
        property_elements = soup.find_all(class_="info clear")
        
        for element in property_elements:
            property_info = {}
            # Distrito Administrativo
            property_info['district'] = district_name
            # Título da propriedade
            property_info['title'] = regex_extract('target="_blank">(.*?)</a><!--', str(element))
            # Nome do condomínio
            property_info['community'] = regex_extract('xiaoqu.*?target="_blank">(.*?)</a>', str(element))
            # Localização
            property_info['location'] = regex_extract('<a href.*?target="_blank">(.*?)</a>.*?class="address">', str(element))
            # Informações fiscais, como imóvel há mais de 5 anos
            property_info['tax_info'] = regex_extract('class="taxfree">(.*?)</span>', str(element))
            # Preço total
            property_info['total_price'] = float(regex_extract('class="totalPrice"><span>(.*?)</span>万', str(element)))
            # Preço unitário
            property_info['unit_price'] = float(regex_extract('data-price="(.*?)"', str(element)))
            
            # Correspondência das informações de tags da propriedade, divididas por |
            # Inclui informações como área, orientação, decoração, etc.
            features = re.findall('class="houseIcon"></span>(.*?)</div>', str(element))[0].strip().split('|')
            property_info['property_type'] = features[0].strip()
            property_info['property_size'] = float(features[1].replace('平米', ''))
            property_info['orientation'] = features[2].strip()
            property_info['decoration'] = features[3].strip()
            
            # Armazena no DataFrame
            if housing_data.empty:
                housing_data = pd.DataFrame(property_info, index=[0])
            else:
                housing_data = housing_data.append(property_info, ignore_index=True)
            
                


Processo de Coleta

3 Análise Visual de Dados

3.1 ECharts

ECharts (Enterprise Charts) é uma ferramenta de visualização de dados open source desenvolvida pelo Baidu, com base na leve biblioteca Canvas ZRender. Compatível com quase todos os navegadores comuns, permite sua ampla utilização tanto em clientes PC quanto mobile. O ECharts ajuda os desenvolvedores a integrar dados dos usuários e criar gráficos visuais personalizados de forma inovadora. Suporta diversos tipos de gráficos como linhas (áreas), colunas (barras), dispersão (bolhas), candlestick, pizza (anéis), podendo ser executado em projetos Java Web através da importação de bibliotecas JS.

Instalação em python

pip install pyecharts


3.2 Gráficos Visuais Relevantes

Gráfico de Dispersão Área-Preço Total

scatter_plot = (Scatter(init_opts=opts.InitOpts(theme='dark'))
           .add_xaxis(housing_data['property_size'])
           .add_yaxis("Preço Imobiliário", housing_data['total_price'])
           .set_series_opts(label_opts=opts.LabelOpts(is_show=False),
                           markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max", name="Valor Máximo"),]))
           .set_global_opts(
               legend_opts=opts.LegendOpts(is_show=False),
               title_opts=opts.TitleOpts(title="Shenzhen - Gráfico de Dispersão Preço Total vs Área"),
               xaxis_opts=opts.AxisOpts(
                   name='Área',
                   # Define o eixo como tipo numérico
                   type_="value", 
                   # Não mostra linhas divisórias
                   splitline_opts=opts.SplitLineOpts(is_show=False)),
               yaxis_opts=opts.AxisOpts(
                   name='Preço Total',
                   name_location='middle',
                   # Define o eixo como tipo numérico
                   type_="value",
                   # Padrão é False indicando início em 0
                   is_scale=True,
                   splitline_opts=opts.SplitLineOpts(is_show=False),),
               visualmap_opts=opts.VisualMapOpts(is_show=True, type_='color', min_=100, max_=1000)
    ))

scatter_plot.render_notebook() 


Preço Médio por Distrito

temp = housing_data.groupby(['district'])['unit_price'].mean().reset_index()
data_pairs = [(row['district'], round(row['unit_price']/10000, 1)) for _, row in temp.iterrows()]

map_chart = (Map(init_opts=opts.InitOpts(theme='dark'))
        .add("Preço Médio de Usados", data_pairs, 'Shenzhen', is_roam=False)
        .set_series_opts(label_opts=opts.LabelOpts(is_show=True))
        .set_global_opts(
            title_opts=opts.TitleOpts(title="Preço Médio de Imóveis Usados por Distrito em Shenzhen"),
            legend_opts=opts.LegendOpts(is_show=False),
            tooltip_opts=opts.TooltipOpts(formatter='{b}:{c} milhões'),
            visualmap_opts=opts.VisualMapOpts(min_=3, max_=10)
        )
       )

        
map_chart.render_notebook()


Top 10 Locais com Preços Médios Mais Altos

temp = housing_data.groupby(['location'])['unit_price'].mean().reset_index()
data_pairs = sorted([(row['location'], round(row['unit_price']/10000, 1))
                    for _, row in temp.iterrows()], key=lambda x: x[1], reverse=True)[:10]

bar_chart = (Bar(init_opts=opts.InitOpts(theme='dark'))
       .add_xaxis([x[0] for x in data_pairs])
       .add_yaxis('Preço Médio de Usados', [x[1] for x in data_pairs])
       .set_series_opts(label_opts=opts.LabelOpts(is_show=True, font_style='italic'),
                            itemstyle_opts=opts.ItemStyleOpts(
                                color=JsCode("""new echarts.graphic.LinearGradient(0, 1, 0, 0, 
                                             [{
                                                 offset: 0,
                                                 color: 'rgb(0,206,209)'
                                             }, {
                                                 offset: 1,
                                                 color: 'rgb(218,165,32)'
                                             }])"""))
                            )
       .set_global_opts(
           title_opts=opts.TitleOpts(title="Top 10 Locais com Preço Médio Mais Alto em Shenzhen"),
           legend_opts=opts.LegendOpts(is_show=False),
           tooltip_opts=opts.TooltipOpts(formatter='{b}:{c} milhões'))
      )

bar_chart.render_notebook()


Distribuição de Tipos de Imóveis

temp = housing_data.groupby(['property_type'])['district'].count().reset_index()
data_pairs = sorted([(row['property_type'], row['district'])
                    for _, row in temp.iterrows()], key=lambda x: x[1], reverse=True)[:10]

pie_chart = (Pie(init_opts=opts.InitOpts(theme='dark'))
       .add('', data_pairs,
            radius=["30%", "75%"],
            rosetype="radius")
       .set_global_opts(title_opts=opts.TitleOpts(title="Distribuição de Tipos de Imóveis Usados em Shenzhen"),
                       legend_opts=opts.LegendOpts(is_show=False),)
       .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {d}%"))
      )

pie_chart.render_notebook()


Nuvem de Palavras

word_collection = []
exclude_words = ['Jardim','Proprietário','Venda']
text_string =  str(''.join([item for item in housing_data['title'] if isinstance(item, str)]))

words = psg.cut(text_string)
for word_obj in words:
    if len(word_obj.word)==1:
        pass
    elif word_obj.flag in ('m', 'x'):
        pass
    elif word_obj.word in exclude_words:
        pass
    else:
        word_collection.append(word_obj.word)
   
data_pairs = collections.Counter(word_collection).most_common(100)


wc_chart = (WordCloud()
      .add("", data_pairs, word_size_range=[20, 100], shape='triangle')
      .set_global_opts(title_opts=opts.TitleOpts(title="Nuvem de Palavras - Descrição de Imóveis"))
    )

wc_chart.render_notebook()


4 Outras Análises

O conjunto de dados Ames contém 2.930 registros do escritório de avaliação de Ames. Este conjunto de dados possui 23 variáveis categóricas nominais, 23 variáveis ordinais, 14 variáveis discretas e 20 variáveis contínuas (além de 2 identificadores de observação adicionais) - totalizando 82 características. As explicações de cada variável podem ser encontradas no arquivo codebook.txt incluído. Esta informação foi usada para calcular os valores avaliados de propriedades residenciais individuais vendidas em Ames, Iowa, entre 2006 e 2010. Um ruído foi adicionado aos preços de venda reais, então os preços não correspondem aos registros oficiais.

Divididos em conjuntos de treino e teste, com 2000 e 930 observações respectivamente. Os preços de venda reais são mantidos no conjunto de teste. Além disso, os dados de teste são divididos em conjuntos público e privado.

Este exercício deve ser realizado com os seguintes objetivos:

  • Entender o Problema: Observar o significado de cada característica variável e sua importância para o problema
  • Estudar Características Principais: Ou seja, a variável objetivo final ---- preço imobiliário
  • Estudar Outras Variáveis: Investigar as relações entre múltiplas variáveis e seu impacto no "preço imobiliário"
  • Limpeza Básica de Dados: Tratar dados ausentes, outliers e dados categóricos
  • Modelagem: Estabelecer um modelo para prever o valor das casas e prever com precisão os preços imobiliários

4.1 Importação das Bibliotecas Relevantes

  1. Importar pacotes python relevantes

​

import numpy as np

import pandas as pd
from pandas.api.types import CategoricalDtype

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn import linear_model as lm
from sklearn.model_selection import train_test_split
from sklearn.model_selection import KFold

# Configurações de plotagem
plt.rcParams['figure.figsize'] = (12, 9)
plt.rcParams['font.size'] = 12


4.2 Importação dos Conjuntos de Treinamento e Teste

​

train_dataset = pd.read_csv("ames_train.csv")
test_dataset = pd.read_csv("ames_test.csv")
pd.set_option('display.max_columns', None)
# Mostrar todas as linhas
pd.set_option('display.max_rows', None)
# Definir comprimento máximo do valor para 100, padrão é 50
pd.set_option('max_colwidth',100)
train_dataset.head(7)


4.3 Observação das Relações entre Características Principais e Preço de Venda

Este conjunto de dados possui 46 variáveis categóricas e 34 variáveis numéricas, organizadas em uma planilha Excel para filtrar variáveis intimamente relacionadas com os preços imobiliários. Das quais selecionamos as seguintes variáveis relacionadas aos preços:

Variáveis Categóricas:

  • Utilities: Utilidades disponíveis (eletricidade, gás, água)
  • Heating (Nominal): Tipo de aquecimento
  • Central Air (Nominal): Presença de ar condicionado central
  • Garage Type (Nominal): Localização da garagem
  • Neighborhood (Nominal): Localização física dentro da cidade de Ames (bairro no mapa)
  • Overall Qual (Ordinal): Avaliação geral do material e acabamento da casa

Variáveis Numéricas:

  • Lot Area (Continuous): Área do terreno (pés quadrados)
  • Gr Liv Area (Continuous): Área habitável acima do solo em pés quadrados
  • Total Bsmt SF (Continuous): Área total do porão
  • TotRmsAbvGrd (Discrete): Número total de cômodos acima do solo

Análise da variável mais importante "SalePrice"

​

train_dataset['SalePrice'].describe()


As estatísticas descritivas acima mostram média, desvio padrão, valor mínimo, percentil 25%, percentil 50%, percentil 75%, valor máximo, etc., e SalePrice não tem dados inválidos ou não numéricos.

​

# Plota histograma de "SalePrice"
sns.distplot(train_dataset['SalePrice'])
# Calcula curtose e assimetria
print("Assimetria: %f" % train_dataset['SalePrice'].skew())
print("Curtose: %f" % train_dataset['SalePrice'].kurt())


Do histograma podemos ver que "SalePrice" segue distribuição normal, com curtose de 4.838055 e assimetria de 1.721408, mais aguda que a distribuição normal, com assimetria positiva, cauda longa à direita.

2. Variáveis Categóricas

(1) Utilities vs SalePrice

Utilities (Ordinal): Tipo de utilidades disponíveis

AllPub Todas as utilidades públicas (E,G,W,& S)

NoSewr Eletricidade, Gás e Água (Tanque Séptico)

NoSeWa Apenas Eletricidade e Gás

ELO Apenas Eletricidade

​

# Variáveis Categóricas
#1.Utilities 
var = 'Utilities'
data = pd.concat([train_dataset['SalePrice'], train_dataset[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000)


Da figura podemos ver que casas com instalações completas (água, eletricidade, gás) têm preços geralmente mais altos

(2) Heating vs SalePrice

Heating (Nominal): Tipo de aquecimento

Floor Aquecedor de piso

GasA Aquecimento a gás forçado

GasW Aquecimento a água ou vapor a gás

Grav Aquecedor gravitacional

OthW Aquecimento a água ou vapor diferente de gás

Wall Aquecedor de parede

​

#2.Heating
var = 'Heating'
data = pd.concat([train_dataset['SalePrice'], train_dataset[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000)


Da figura podemos ver que casas com GasA, GasW têm preços mais altos, e casas com GasA têm variação de preço maior, casas com preços mais altos geralmente têm sistema de aquecimento GasA.

(3) Central_Air vs SalePrice

​

#3.Central_Air
var = 'Central_Air'
data = pd.concat([train_dataset['SalePrice'], train_dataset[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000)


Casas com ar condicionado central oferecem melhor experiência ao usuário, por isso geralmente têm preços mais altos, casas com preços mais altos geralmente têm ar condicionado central.

(4) Garage_type vs SalePrice

Garage Type (Nominal): Localização da garagem

2Types Mais de um tipo de garagem

Attchd Anexada à casa

Basment Garagem no porão

BuiltIn Incorporada (Garagem parte da casa - tipicamente tem cômodo acima da garagem)

CarPort Abrigo para carro

Detchd Separada da casa

NA Sem garagem

​

#4.Garage_type
var = 'Garage_Type'
data = pd.concat([train_dataset['SalePrice'], train_dataset[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000)


Quanto mais conveniente a garagem, geralmente maior o preço da casa, garagens próximas à casa e integradas à casa têm preços mais altos.

(5) Neighborhood vs SalePrice

Neighborhood refere-se ao bairro específico dentro da cidade de Ames, casas mais próximas de áreas comerciais movimentadas, zonas turísticas, parques tecnológicos, zonas universitárias têm preços mais altos

​

#5.Neighborhood
fig, axes = plt.subplots(nrows=2)

sns.boxplot(
    x='Neighborhood',
    y='SalePrice',
    data=train_dataset.sort_values('Neighborhood'),
    ax=axes[0]
)

sns.countplot(
    x='Neighborhood',
    data=train_dataset.sort_values('Neighborhood'),
    ax=axes[1]
)

# Desenha preço mediano
axes[0].axhline(
    y=train_dataset['SalePrice'].median(), 
    color='red',
    linestyle='dotted'
)

# Rotula as barras com contagens
for patch in axes[1].patches:
    x = patch.get_bbox().get_points()[:, 0]
    y = patch.get_bbox().get_points()[1, 1]
    axes[1].annotate(f'{int(y)}', (x.mean(), y), ha='center', va='bottom')
    
# Formata eixos x
axes[1].set_xticklabels(axes[1].xaxis.get_majorticklabels(), rotation=90)
axes[0].xaxis.set_visible(False)

# Reduz espaço entre os gráficos
plt.subplots_adjust(hspace=0.01)


Dos resultados acima podemos ver que os dados da coluna Neighborhood em nosso conjunto de treinamento não são uniformes, NAmes tem 299 registros, enquanto Blueste tem apenas 4, Gilbert tem 6, GmHill tem 2, isso torna os dados menos precisos.

(6) Overall Qual vs SalePrice

Avaliação geral mais alta deve resultar em preço mais alto da casa

​

#Overall Qual 
var = 'Overall_Qual'
data = pd.concat([train_dataset['SalePrice'], train_dataset[var]], axis=1)
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000)


3. Variáveis Numéricas

(1) Lot Area vs SalePrice

​

# Variáveis Numéricas
#1.Lot Area
sns.jointplot(
    x='Lot_Area', 
    y='SalePrice', 
    data=train_dataset,
    stat_func=None,
    kind="reg",
    ratio=4,
    space=0,
    scatter_kws={
        's': 3,
        'alpha': 0.25
    },
    line_kws={
        'color': 'black'
    }
)


Parece não haver tendência clara, os pontos estão concentrados na parte inicial, não muito dispersos

(2) Gr_Liv_Area vs SalePrice

Gr_Liv_Area representa a área da casa construída sobre o terreno

Supomos que devem estar positivamente correlacionados, ou seja, maior área da casa, preço mais alto

​

sns.jointplot(
    x='Gr_Liv_Area', 
    y='SalePrice', 
    data=train_dataset,
    stat_func=None,
    kind="reg",
    ratio=4,
    space=0,
    scatter_kws={
        's': 3,
        'alpha': 0.25
    },
    line_kws={
        'color': 'black'
    }
)


Resultado: De fato mostram relação linear positiva, encontramos outliers acima de 5000 em Gr_ Liv_ Area

Escreve função para remover outliers acima de 5000 em Gr_ Liv_ Area

​

def filter_outliers(dataset, column, lower_bound=-np.inf, upper_bound=np.inf):
    """
    Entrada:
      dataset (data frame): tabela a ser filtrada
      column (string): coluna com outliers numéricos
      lower_bound (numeric): observações com valores abaixo serão removidas
      upper_bound (numeric): observações com valores acima serão removidas
    
    Saída:
      dataframe winsorizado com outliers removidos
    """
    dataset=dataset[(dataset[column]>lower_bound)&(dataset[column]<upper_bound)]
    return dataset

filtered_data = filter_outliers(train_dataset, 'Gr_Liv_Area', upper_bound=5000)


Plota novamente

De fato mostram relação linear positiva

(3) Total_Bsmt_SF vs SalePrice

​

#3.Total Bsmt SF
sns.jointplot(
    x='Total_Bsmt_SF', 
    y='SalePrice', 
    data=train_dataset,
    stat_func=None,
    kind="reg",
    ratio=4,
    space=0,
    scatter_kws={
        's': 3,
        'alpha': 0.25
    },
    line_kws={
        'color': 'black'
    }
)


(4) TotRms_AbvGrd vs SalePrice

​

#4.TotRmsAbvGrd
sns.jointplot(
    x='TotRms_AbvGrd', 
    y='SalePrice', 
    data=train_dataset,
    stat_func=None,
    kind="reg",
    ratio=4,
    space=0,
    scatter_kws={
        's': 3,
        'alpha': 0.25
    },
    line_kws={
        'color': 'black'
    }
)


4. Plota Matriz de Correlação

​

# Plota matriz de correlação
correlation_matrix = train_dataset.corr()
f, ax = plt.subplots(figsize=(40, 20))
sns.heatmap(correlation_matrix, vmax=0.8,square=True,cmap="PiYG",center=0.0)


Entre as variáveis numéricas, Overall_Qual (avaliação geral da casa), Year_Built (ano de construção), Year_Remod/Add (ano de reforma), Mas Vnr Area (área de revestimento da fachada), Total_ Bsmt_ SF (área total do porão), 1stFlr_SF (área total do primeiro andar), *Gr_ Liv_Area (área habitável acima do solo), Garage_Cars (capacidade da garagem), Garage_Area (área da garagem) estão todas positivamente correlacionadas

Finalmente selecionamos Year_Built entre Year_Built (ano de construção) e Year_Remod/Add (ano de reforma), Gr_ L iv_Area entre 1stFlr_SF (área total do primeiro andar) e Gr_ L iv_Area (área habitável acima do solo), e Garage_Cars (capacidade da garagem) entre Garage_Cars (capacidade da garagem) e Garage_Area (área da garagem).

6. Modelagem

Existem vários métodos de regressão no sklearn, regressões lineares generalizadas estão concantradas na biblioteca linear_model, como regressão linear ordinária, Lasso, regressão ridge, etc.; além diso, há outros métodos de regressão não linear, como SVM kernel, métodos ensemble, regressão bayesiana, regressão K-vizinhos, árvore de decisão regressão, regressão floresta aleatória, etc., testando vários algoritmos

(1) Carrega pacotes relevantes

​

# Modelagem de dados
from sklearn import preprocessing
from sklearn import linear_model, svm, gaussian_process
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
import numpy as np


(2) Verifica valores ausentes em cada coluna

​

  # Verifica valores ausentes em cada coluna
    print(train_dataset.Overall_Qual.isnull().any())
    print(train_dataset.Gr_Liv_Area.isnull().any())
    print(train_dataset.Garage_Cars.isnull().any())
    print(train_dataset.Total_Bsmt_SF.isnull().any())
    print(train_dataset.Year_Built.isnull().any())
    print(train_dataset.Mas_Vnr_Area.isnull().any())


Descobrimos que Total_Bsmt_SF e Mas_Vnr_Area têm valores ausentes

​

   # Preenche valores ausentes com média
    train_dataset.Total_Bsmt_SF=train_dataset.Total_Bsmt_SF.fillna(train_dataset.Total_Bsmt_SF.mean())
    train_dataset.Mas_Vnr_Area=train_dataset.Mas_Vnr_Area.fillna(train_dataset.Mas_Vnr_Area.mean())
    print(train_dataset.Total_Bsmt_SF.isnull().any())
    print(train_dataset.Mas_Vnr_Area.isnull().any())


(3) Modelagem

​

   # Obtém dados
    from sklearn import metrics
    selected_cols = ['Overall_Qual','Gr_Liv_Area', 'Garage_Cars','Total_Bsmt_SF', 'Year_Built','Mas_Vnr_Area']
    x = train_dataset[selected_cols].values
    y = train_dataset['SalePrice'].values
    X_train,X_test, y_train, y_test = train_test_split(x, y, test_size=0.33, random_state=42)
    
    regressor = RandomForestRegressor(n_estimators=400)
    regressor.fit(X_train, y_train)
    y_pred = regressor.predict(X_test)
    Calcula MSE:
    print(metrics.mean_squared_error(y_test,y_pred))


(4) Plota gráfico de dispersão dos resultados preditos

​

import numpy as np
x = np.random.rand(660)
plt.scatter(x,y_test, alpha=0.5)
plt.scatter(x,y_pred, alpha=0.5,color="G")


(5) Carrega dados do conjunto de teste

​

test_dataset=pd.read_csv("ames_test.csv")
test_dataset.head(5)


Verifica valores ausentes

​

# Verifica valores ausentes em cada coluna
print(test_dataset.Overall_Qual.isnull().any())
print(test_dataset.Gr_Liv_Area.isnull().any())
print(test_dataset.Garage_Cars.isnull().any())
print(test_dataset.Total_Bsmt_SF.isnull().any())
print(test_dataset.Year_Built.isnull().any())
print(test_dataset.Mas_Vnr_Area.isnull().any())


​ ​

# Preenche valores ausentes com média
test_dataset.Garage_Cars=test_dataset.Garage_Cars.fillna(test_dataset.Garage_Cars.mean())
print(test_dataset.Garage_Cars.isnull().any())


(6) Previsão dos preços imobiliários no conjunto de teste

​

    # Previsão
    selected_cols = ['Overall_Qual','Gr_Liv_Area', 'Garage_Cars','Total_Bsmt_SF', 'Year_Built','Mas_Vnr_Area']
    x_test_values= test_dataset[selected_cols].values
    test_predictions=regressor.predict(x_test_values)
    # Escreve arquivo
    predictions_df = pd.DataFrame(test_predictions, columns=['SalePrice'])
    results = pd.concat([test_dataset['Id'], predictions_df], axis=1)
    results.to_csv('./Predictions.csv', index=False)

  test_dataset.Garage_Cars=test_dataset.Garage_Cars.fillna(test_dataset.Garage_Cars.mean())
    print(test_dataset.Garage_Cars.isnull().any())


(6) Previsão dos preços imobiliários no conjunto de teste

​

# Previsão
selected_cols = ['Overall_Qual','Gr_Liv_Area', 'Garage_Cars','Total_Bsmt_SF', 'Year_Built','Mas_Vnr_Area']
x_test_values= test_dataset[selected_cols].values
test_predictions=regressor.predict(x_test_values)
# Escreve arquivo
predictions_df = pd.DataFrame(test_predictions, columns=['SalePrice'])
results = pd.concat([test_dataset['Id'], predictions_df], axis=1)
results.to_csv('./Predictions.csv', index=False)


5 Conclusão

Compartilhamento do Projeto: veja no final do artigo!

Tags: Python data-analysis web-scraping visualization echarts

Publicado em 10-6 04:58