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
- 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!