<jupyter_start><jupyter_text>Calculadora de Alugueis> "Da coleta até a aplicação: Um estudo de caso"- toc: false- branch: master- badges: true- comments: false- categories: [fastpages, jupyter, Data exploration]- hide: false- author: <NAME>--- IntroduçãoExiste uma lenda que corre entre os matemáticos desde o século 13. Ela que chegou à nossa língua por meio do livro: O Homem que Calculava, de 1937.O autor é: <NAME>, um pseudônimo do engenheiro carioca: <NAME> e Souza (1895-1974).Conta-se que o rei da província de Telengana, no sul da Índia, não estava bem. Tinha acabado de perder um filho no campo de batalha e agora passava seus dias remoendo a tristeza.As notícias sobre a depressão do monarca espalharam-se pelo reino. Um jovem, então, foi ao palácio e pediu uma audiência. Dizia ser Lahur Sessa e que acabara de Invententar um jogo, que poderia trazer novas alegrias ao rei. Ele trazia um tabuleiro quadrado, dividido em 64 casas. Mais 32 peças, representando soldados, cavalaria, torres de defesa. Ente outros. Era um protótipode 'Chaturanga' (Que deu origem ao nosso atual 'Xadrez'). Ele então viu, jogou e adorou. Ficou tão contente que ofereceu o que ele quisesse como recompensa: ouro, terras ou um palácio. Deu sua palavra. Não importando a quantidade. O jovem disse que não lhe interessava nenhum desses luxos. Bastavam-lhe grãos de trigo. O soberano riu com soberba e logo aceitou. Foi então que o inventor revelou:Que deveria preencher cada casa do tabuleiro com o dobro da quantidade de grãos da anteriormente preenchida, até que todas as 64 estivessem completas.Então, assim se seguiu:- Casa 1ª, 1 grão de trigo;- Casa 2ª, 2 grãos de trigo;- Casa 3ª, 4 grãos de trigo;- Casa 4ª, 8 grãos de trigo;- ...- Casa 9ª, 512 grãos;- ...- Casa 18ª, 262 mil;- ...- Casa 27ª, 134 milhões;- ...- Casa 33ª, 8,5 bilhões;- ...No quadrado final, a Casa 64ª, fechava-se a conta: 18.446.744.073.709.551.615 grãos de trigo.18 sextilhões. Podemos arredondar para o número 18 seguido de 21 'zeros'.Para dar uma ideia do que esse número significa: Estima-se hoje que o número de grãos de areia na Terra seja de 18 quintilhões.  Ou 18 seguido de 18 'zeros'.Sem perceber, o monarcarca arcou com uma dívida infundada. Impossível de ser paga. Pois era o equivalente a todos os grãos de areia de mil planetas Terra. Algo mundano como um tabuleiro de 64 casas pode carregar dentro de si um número que, para os nossos cérebros, é indiscernível do infinito.  É uma história que ensina sobre investimento. Sobre atribuir valor. Arcar com escolhas e sobre arrependimento. A somatória das pequenas coisas podendo afetar o todo.Todos querem lucras como o inventor da história.Ninguém quer pagar a soma do monarca.  Sobre este notebookPortanto, um tabuleiro que ajudasse a atribuir preços justos, afim de que não mais se vangloriem os inventores ou saiam derrotados os monarcas, poderia ajudar aqueles que buscam obter, negociar ou arrendar seus bens. Entre o cenário todos os tipos possíveis, mais comum: Um imóvel.Seria possível criar uma máquina que me entregue o valor justo, competitivo ou atraente de um imóvel por meio dos dados diponíveis?Para tal, foi desenvolvido este notebook. Ele parte do zero, para um sistema que procesa as informações e entrega a classificação.Ele foi separado em diferentes estágios até sua função plena:1. Raspagem de dados2. Manipulação dos dados3. Modelagem4. Otimização5. Salvando6. Deploy Abaixo uma lista de todos os módulos usados para este projeto:<jupyter_code># requirements
"""
click==8.0.3
Flask==2.0.3
gunicorn==20.1.0
importlib-metadata==4.11.1
itsdangerous==2.0.1
Jinja2==3.0.3
joblib==1.1.0
MarkupSafe==2.0.1
numpy==1.21.5
pandas==1.3.5
python-dateutil==2.8.2
pytz==2021.3
scikit-learn==1.0.2
scipy==1.7.3
six==1.16.0
sklearn==0.0
threadpoolctl==3.1.0
typing-extensions==4.1.1
Werkzeug==2.0.3
zipp==3.7.0
"""<jupyter_output><empty_output><jupyter_text>1.Raspagem de dados Aqui usaremos a biblioteca 'Selenium' para realizar a obtenção dos dados. Por meio disso será possível acessar o site e obter informações contidas em campos do 'html' contidos em sua estrutura, visível nas ferramentas para o desenvolvedor e armazena-los em variáveis que serão usadas mais à frente.<jupyter_code># Importando de espera para não sobrecarregar o site a ser acessado:
# Importando Pandas:
from time import sleep
import pandas as pd
# Importando Selenium:
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.chrome.options import Options

# Definindo url a ser usada:
url = 'https://www.zapimoveis.com.br/aluguel/imoveis/rj+rio-de-janeiro/?gclid=EAIaIQobChMIr87tpubZ9QIVDwuRCh2R_QFZEAAYAyAAEgLqgPD_BwE&utm_referrer=https%3A%2F%2Fwww.google.com%2F'

# Entrando na página:
driver = webdriver.Chrome(executable_path='chromedriver')
driver.get(url)

# Esperar o carregamento da página:
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, "simple-card__price"))
    )
except TimeoutException:
    print('O carregamento da página demorou muito tempo')
# pegar a lista de cards:
cards = driver.find_elements_by_class_name('card-container')

# criar um dataframe:
df = pd.DataFrame(columns=[
    'preco', 
    'condominio', 
    'endereço', 
    'area', 
    'quartos',
    'vagas', 
    'banheiros'
    ]
)
    
# criar um dataframe:
df = pd.DataFrame(columns=[
    'preco', 
    'condominio', 
    'endereço', 
    'area', 
    'quartos',
    'vagas', 
    'banheiros'
    ]
)
len_df = len(df)
i = 0
while len_df < 10000:
    # scroll down:
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    sleep(1)
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    sleep(1)
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    # pegar a lista de cards:
    cards = driver.find_elements_by_class_name('card-container')

    for card in cards:
        # search for itemprop="floorSize" in card[1]:
        try:
            floor_size = card.find_elements_by_class_name('js-areas')[0].text
        except:
            break
        try:
            bedrooms = card.find_elements_by_class_name('js-bedrooms')[0].text
        except Exception:
            bedrooms = 0
        try:
            parking_spaces = card.find_elements_by_class_name('js-parking-spaces')[0].text
        except Exception:
            parking_spaces = 0
        try:
            bathrooms = card.find_elements_by_class_name('js-bathrooms')[0].text
        except Exception:
            bathrooms = 0
        price = card.find_element_by_class_name('simple-card__price').text
        try:
            condominio = card.find_element_by_class_name('card-price__value').text
        except Exception:
            condominio = 0
       
        address = card.find_element_by_class_name('simple-card__address').text

        # print('price:', price, 'condominio:', condominio, 'address:', address)

        # print('floor_size:', floor_size, 'bedrooms:', bedrooms, 'parking_spaces:', parking_spaces, 'bathrooms:', bathrooms)
        
        # adicionar os dados ao dataframe:
        df = df.append({
            'preco': price,
            'condominio': condominio,
            'endereço': address,
            'area': floor_size,
            'quartos': bedrooms,
            'vagas': parking_spaces,
            'banheiros': bathrooms
        }, ignore_index=True)
    len_df = len(df)
    print('len_df:', len_df, '/10000')
    # display(df)
    sleep(3)
    # click in button with class pagination__button--next
    url = f'https://www.zapimoveis.com.br/aluguel/imoveis/rj+rio-de-janeiro/?pagina={(i+2)}&onde=,Rio%20de%20Janeiro,Rio%20de%20Janeiro,,,,,CITY,BR%3ERio%20de%20Janeiro%3ENULL%3ERio%20de%20Janeiro,-22.906847,-43.172897&transacao=Aluguel&tipo=Im%C3%B3vel%20usado'
    driver.get(url)
    i += 1
    sleep(3)
# get unique rows:
df.drop_duplicates(keep='first', inplace=True)
df.to_csv('lista_de_alugueis.csv', index=False)<jupyter_output><empty_output><jupyter_text>2. Manipulação dos dados<jupyter_code>import pandas as pd

df = pd.read_csv('lista_de_alugueis.csv')
df.head(15)
# remove all characters except numbers on 'preco', 'condominio' and 'area' columns:
df['preco'] = df['preco'].str.replace(r'[^0-9]', '')
df['condominio'] = df['condominio'].str.replace(r'[^0-9]', '')
df['area'] = df['area'].str.replace(r'[^0-9]', '')

df.head(1)
df['preco_total'] = pd.to_numeric(df['preco']) + pd.to_numeric(df['condominio'])
df.head(5)
for index, row in df.iterrows():
    if ', Rio de Janeiro' in row['endereço']:
        df.loc[index, 'endereço'] = row['endereço'].replace(', Rio de Janeiro', '')
    else:
        df.loc[index, 'endereço'] = row['endereço'].split(',')[1]

df.head(5)
# change 'endereco' column to 'bairro':
df['bairro'] = df['endereço']
df.drop('endereço', axis=1, inplace=True)
# remove all ' ' from 'bairro' column:
df['bairro'] = df['bairro'].str.replace(' ', '')
df.head(1)
# rename preco_total column to 'aluguel':
df.rename(columns={'preco_total': 'aluguel'}, inplace=True)

df = df[['aluguel', 'bairro', 'area', 'quartos', 'vagas', 'banheiros']]
# for each bairro create column with the name of bairro and 1 if the row has bairro name, 0 otherwise:
dummies = pd.get_dummies(df, columns=['bairro'], drop_first=False, sparse=True)
dummies = pd.concat([df['bairro'], dummies], axis=1)
dummies
# organize columns and save to csv:
dummies.to_csv('lista_de_alugueis_processada.csv', index=False)<jupyter_output><empty_output><jupyter_text>3. Modelagem<jupyter_code>import pandas as pd
import numpy as nd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
# import sklearn logistic regression
from sklearn.linear_model import LogisticRegression
# import sklearn k-nearst neighbors
from sklearn.neighbors import KNeighborsClassifier
# import sklearn support vector machine
from sklearn.svm import SVC
# import sklearn naive bayes
from sklearn.naive_bayes import GaussianNB
# import sklearn decision tree
from sklearn.tree import DecisionTreeClassifier
# import sklearn random forest
from sklearn.ensemble import RandomForestClassifier
alugueis = pd.read_csv('lista_de_alugueis_processada.csv')
alugueis.head(5)
alugueis.shape
alugueis.isnull().sum()
def var_summary(x):
    return pd.Series([x.count(), x.isnull().sum(), x.sum(), x.mean(), x.median(),  x.std(), x.var(), x.min(), x.dropna().quantile(0.01), x.dropna().quantile(0.05),x.dropna().quantile(0.10),x.dropna().quantile(0.25),x.dropna().quantile(0.50),x.dropna().quantile(0.75), x.dropna().quantile(0.90),x.dropna().quantile(0.95), x.dropna().quantile(0.99),x.max()], 
                  index=['N', 'NMISS', 'SUM', 'MEAN','MEDIAN', 'STD', 'VAR', 'MIN', 'P1' , 'P5' ,'P10' ,'P25' ,'P50' ,'P75' ,'P90' ,'P95' ,'P99' ,'MAX'])

numerical_features = ['aluguel', 'area', 'quartos', 'vagas', 'banheiros']
alugueis[numerical_features].apply(lambda x: var_summary(x)).T
alugueis.dtypes
# separate categorical and numerical alugueis
categorical_features = ['bairro']
numerical_features = ['area', 'quartos', 'banheiros', 'vagas', 'aluguel']
sns.set_style('whitegrid')
# plot one histogram for each numerical feature
for feature in numerical_features:
    sns.distplot(alugueis[feature], hist=False, label=feature)
    plt.show()
# for each categorical_features, find the count of '1's:
bairros = []
for feature in categorical_features:
    bairros.append([feature, alugueis[feature].sum()])

# order list by bairros[1] in descending order
bairros.sort(key=lambda x: x[1], reverse=True)
bairros
avg_rents = alugueis.groupby('bairro').mean().reset_index()[['bairro', 'aluguel']]
avg_rents['aluguel'] = [round(r) for r in avg_rents.aluguel]
avg_rents.sort_values(by=['aluguel'], ascending=False, inplace=True)

# plot boxplot for each bairro
sns.barplot(x='bairro', y='aluguel', data=avg_rents.head(15))
# rotate x-axis labels
plt.xticks(rotation=90)
plt.show()<jupyter_output><empty_output><jupyter_text>Os preço medio em bairros acima como Guadalupe, Pavuna e Santo Cristo se justificam por terem muitos imóveis inteiros em aluguel, como galpões e prédios.<jupyter_code># correlation matrix
corr = alugueis[numerical_features].corr()
plt.figure(figsize=(6,6))
sns.heatmap(corr, cmap='RdBu_r', annot=True, vmax=1, vmin=-1)
plt.show()<jupyter_output><empty_output><jupyter_text>fatores como area, banheiro e vagas aparentam ter um efeito maior no preço do aluguel. Porém sem dúvida o bairro do imóvel também tem um peso.Fiquei curioso em entender como o numero de quartos não se correlaciona com o preço, e irei plotar um gráfico para verificar:<jupyter_code># See linear regression plot for quartos and aluguel:
sns.lmplot(x='quartos', y='aluguel', data=alugueis)
plt.show()<jupyter_output><empty_output><jupyter_text>Os galpões parecem de alguma maneira afetar essa variável, penso em remover os imóveis que não possuem nenhum quarto de nossa análise, abaixo considerarei essa opção<jupyter_code># remove from alugueis all rows with 0 quartos and apply var summary
alugueis_modificada = alugueis[alugueis.quartos != 0]
alugueis_modificada[numerical_features].apply(lambda x: var_summary(x)).T
# See linear regression plot for quartos and aluguel:
sns.lmplot(x='quartos', y='aluguel', data=alugueis_modificada)
plt.show()
# correlation matrix
corr = alugueis_modificada[numerical_features].corr()
plt.figure(figsize=(6,6))
sns.heatmap(corr, cmap='RdBu_r', annot=True, vmax=1, vmin=-1)
plt.show()<jupyter_output><empty_output><jupyter_text>Como a matriz de correlação aparenta fazer um pouco mais de sentido, criarei o modelo com base em alugueis_modificada<jupyter_code># separe os dados em treino e teste
train_set, test_set = train_test_split(alugueis, test_size=0.2, random_state=1)
features = train_set.drop(['bairro'], axis=1).columns.tolist()

# add all models imported above
models = [
    LogisticRegression(),
    KNeighborsClassifier(),
    SVC(),
    GaussianNB(),
    DecisionTreeClassifier(),
    RandomForestClassifier()
]

# create a list of model names
model_names = [
    'Logistic Regression',
    'K-Nearest Neighbors',
    'Support Vector Machine',
    'Naive Bayes',
    'Decision Tree',
    'Random Forest'
]

# create a dataframe to store the results
results = pd.DataFrame(columns=['Model', 'Score'])

# loop through the models
for model, name in zip(models, model_names):
    # train the model
    model.fit(train_set[features], train_set['aluguel'])
    # make predictions
    predictions = model.predict(test_set[features])
    # calculate the score
    score = model.score(test_set[features], test_set['aluguel'])
    # store the results
    results = results.append({'Model': name, 'Score': score}, ignore_index=True)

results<jupyter_output><empty_output><jupyter_text>4. Otimização<jupyter_code>#import gridsearchcv
from sklearn.model_selection import GridSearchCV

# hyperparameter tuning for decision tree classifier:
# create a list of hyperparameters
hyperparameters = {
    'min_samples_leaf': [1, 2, 4, 8, 16, 32, 64],
    'min_samples_split': [2, 5, 10, 15, 20],
    'criterion': ['gini', 'entropy'],
    'max_features': [None, "auto", "sqrt", "log2"],
    'class_weight': [None, 'balanced']

}

def decision_tree_classifier(hyperparameters):
    # create a decision tree classifier
    clf = DecisionTreeClassifier()
    # create a grid search object
    gs = GridSearchCV(clf, hyperparameters, cv=5, n_jobs=-1)
    # fit the data
    gs.fit(train_set[features], train_set['aluguel'])
    # return the grid search object
    return gs

# get results:
gs = decision_tree_classifier(hyperparameters)
print('Best Score is ',gs.best_score_)
print(gs.best_params_, 'are the params')
def var_summary(x):
    return pd.Series([x.count(), x.isnull().sum(), x.sum(), x.mean(), x.median(),  x.std(), x.var(), x.min(), x.dropna().quantile(0.01), x.dropna().quantile(0.05),x.dropna().quantile(0.10),x.dropna().quantile(0.25),x.dropna().quantile(0.50),x.dropna().quantile(0.75), x.dropna().quantile(0.90),x.dropna().quantile(0.95), x.dropna().quantile(0.99),x.max()], 
                  index=['N', 'NMISS', 'SUM', 'MEAN','MEDIAN', 'STD', 'VAR', 'MIN', 'P1' , 'P5' ,'P10' ,'P25' ,'P50' ,'P75' ,'P90' ,'P95' ,'P99' ,'MAX'])


# see the list of predictions in comparison with the test set
predictions = gs.predict(test_set[features])

# create a dataframe to compare predictions with 'aluguel'
compare = pd.DataFrame(test_set['aluguel'])
compare['predictions'] = predictions
compare['error'] = compare['aluguel'] - compare['predictions']
compare['percent_error'] = ((compare['error'] / compare['aluguel'] ) * 100)
compare.apply(lambda x: var_summary(x)).T<jupyter_output><empty_output><jupyter_text>A media do erro na previsão é de 0,07%, com desvio padrão de 4.5 pontos percentuais, o que sifnifica que em 95% das previsões o valor do aluguel tem uma diferença de menos de 1% para o valor real de um apartamento nas condições apresentadas 5. Salvando<jupyter_code>from sklearn import model_selection, datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split

import pickle
import pandas as pd
alugueis = pd.read_csv('lista_de_alugueis_processada.csv')
alugueis.head(5)
# separe os dados em treino e teste
train_set, test_set = train_test_split(alugueis, test_size=0.2, random_state=1)
features = train_set.drop(['bairro'], axis=1).columns.tolist()
# save features list t csv
features_list = pd.DataFrame(features)
features_list.to_csv('features_list.csv', index=False)
#Precisei diminuir max depth de 28 para 11 para que heroku app tenha menos que 1GB de memória

model = RandomForestClassifier(n_estimators=198, min_samples_split=2, min_samples_leaf=1, max_features='sqrt', max_depth=11, bootstrap=True)
model.fit(train_set[features].drop(['aluguel'], axis=1), train_set['aluguel'])
    
filename = "calculadora-de-aluguel-model.joblib"

joblib.dump(model, filename)
# Prevendo o aluguel de 10 imóveis
imovel = test_set[ ['bairro'] + features].head(10)
imovel
filename = "calculadora-de-aluguel-model.joblib"

loaded_model = joblib.load(filename)
result = loaded_model.predict(test_set[features].drop(['aluguel'], axis=1).head(10))
print(result.tolist())<jupyter_output><empty_output><jupyter_text>6.Deploy Abaixo se encontra a solução com o passo a passo para final importada para o formato legivel via [Heroku](https://medium.com/data-hackers/deploy-flask-api-using-heroku-d5c7128481b7).Esta é uma plataforma em nuvem, como o conceito de platform as a service (PaaS) que suporta várias linguagens de programação. Entre elas o Python.Para se contruir um modelo igual, é necessário também o cadastro no [Git](https://git-scm.com/), a fim de realizar o controle de versionamento do seu código. Portanto é necessário antes de implementar o modelo, seguir com sua instalação completamnte. No terminal do Git, abra a pasta do projeto:>   cd \users\desktop\flask\{coloque o nome de seu arquivo.py aqui}Em seguida, digite o código abaixo para fazer login no Heroku:>   heroku loginNote que depois disso, aparecerá a mensagem abaixo:>   heroku: Press any key to open up the browser to login or q to exit:Pressione qualquer tecla para fazer login, em seguida, ele abrirá uma janela, com o site do Heroku para inserir email e senha. Realize seu login aqui.Feito isso, no terminal, você receberá a mensagem abaixo:>   Opening browser to https://cli-auth.heroku.com/auth/cli/browser/>   b166712b-6219-4430-9f61-2ccef9cdbc83>   Logging in... done>   Logged in as <EMAIL>Agora vamos ativar o ambiente virtual (aqui no caso para Windowns):>   venv\Scripts\activateÉ interessante verificar se todas as bibliotecas necessárias para executar o seu projeto estão instaladas; para isso use o comando abaixo para listar todas elas:>   pip freezeOutro ponto importante é instalar o Gunicorn, ele será usado como nosso servidor WSGI Python:>   pip install gunicornO Heroku precisa conhecer as dependências do nosso aplicativo para que no momento do deploy crie o ambiente corretamente, utilizei o pip freeze apontando para requirements.txt:>   pip freeze > requirements.txtAgora, criaremos o arquivo Procfile, onde será gravado o comando que o Heroku deve usar para executar nosso aplicativo. Basicamente, o mesmo comando que usaríamos para executar o aplicativo localmente. o mesmo deve permanecer na raiz do projeto.>   echo "web: gunicorn app:app" > ProcfileAgora vamos criar um repositório no diretório atual usando o comando git init:>   git initVamos criar um arquivo chamado .gitignore, nele colocaremos todos os arquivos que não queremos que sejam lidos o seu conteúdo, para o nosso cenário colocaremos apenas nosso ambiente virtual “venv”.Vamos adicionar todos os arquivos ao nosso repositório usando git add:>   git add .Agora vamos criar nosso commit inicial:>   git commit -m "initial commit"Agora vamos criar nosso aplicativo no Heroku usando o comando heroku apps: create [app name], neste caso, eu chamo meu aplicativo:>   heroku apps:create app nameAssim que criada, a mensagem abaixo será impressa:>   Creating ⬢ app name... donehttps://app name.herokuapp.com/ | https://git.heroku.com/app name.gitObserve que a URL do API e do repositório git foi retornada na mensagem acima para onde nosso aplicativo foi enviado.Para o deploy nosso aplicativo, basta enviar as confirmações do repositório local para o repositório heroku, usando o comando git push heroku master:>   git push heroku masterEm seguida, aparece uma mensagem abaixo:remote: Verifying deploy... done.To https://git.heroku.com/app name.git<jupyter_code>#salvando modelo
from sklearn import model_selection, datasets
from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib
from sklearn.model_selection import train_test_split

import pickle
import pandas as pd

alugueis = pd.read_csv('lista_de_alugueis_processada.csv')

# separe os dados em treino e teste
train_set, test_set = train_test_split(alugueis, test_size=0.2, random_state=1)
features = train_set.drop(['bairro'], axis=1).columns.tolist()

# save features list t csv
features_list = pd.DataFrame(features)
features_list.to_csv('features_list.csv', index=False)

#Precisei diminuir max depth de 28 para 11 para que heroku app tenha menos que 1GB de memória
model = RandomForestClassifier(n_estimators=198, min_samples_split=2, min_samples_leaf=1, max_features='sqrt', max_depth=11, bootstrap=True)
model.fit(train_set[features].drop(['aluguel'], axis=1), train_set['aluguel'])
    
filename = "calculadora-de-aluguel-model.joblib"

joblib.dump(model, filename)
#testando modelo
# Prevendo o aluguel de 10 imóveis
imovel = test_set[ ['bairro'] + features].head(10)
imovel

filename = "calculadora-de-aluguel-model.joblib"

loaded_model = joblib.load(filename)
result = loaded_model.predict(test_set[features].drop(['aluguel'], axis=1).head(10))
print(result.tolist())
#app calculadora.py
from curses import pair_content
from flask import Flask, render_template, request
import pandas as pd
from sklearn.externals import joblib
import sys


app = Flask(__name__)

@app.route('/')
def index():
    return render_template('calculadora-front-end.html')

@app.route('/calcular', methods=['POST'])
def calcular():
    area = request.form['area']
    bairro = request.form['bairro']
    quartos = request.form['quartos']
    vagas = request.form['vagas']
    banheiros = request.form['banheiros']
    features = pd.read_csv('features_list.csv')['0'].to_list()

    payload = pd.DataFrame(columns=features)

    # make all the bairro_ values in the payload 0
    for feature in features:
        if 'bairro_' in feature:
            payload.loc[0, f'{feature}'] = 0

    payload.loc[0, 'area'] = area
    payload.loc[0,'bairro'] = bairro
    payload.loc[0,'quartos'] = quartos
    payload.loc[0,'vagas'] = vagas
    payload.loc[0,'banheiros'] = banheiros
    payload.loc[0,f'bairro_{bairro}'] = 1

    # passing values to model and getting the prediction
    filename = "calculadora-de-aluguel-model.joblib"

    loaded_model = joblib.load(filename)
    result = loaded_model.predict(payload[features].drop(['aluguel'], axis=1).head(10))
    
    return render_template('aluguel_calculado.html', aluguel=result[0])

if __name__ == '__main__':
    app.run(debug=True)
#template: calculadora-front-end.html

<!-- #######  YAY, I AM THE SOURCE EDITOR! #########-->
<h1 style="color: #5e9ca0;">Calculadora de Aluguel da cidade do Rio de Janeiro</h1>
<h2 style="color: #2e6c80;">Adicione abaixo caracteristicas do apartamento e receba o valor do aluguel!</h2>
<!-- Make all text above in the same color pallete: -->
<h4 style="color: #25405f;">
    <form action="{{ url_for('calcular') }}" method="post">
        <p><strong>&Aacute;rea (m<sup>2</sup>):</strong></p>
        <p><input name="area" type="number" value='65'/></p>
        <p><strong>Quartos:&nbsp;</strong></p>
        <p><input name="quartos" type="number" value='2'/></p>
        <p><strong>Vagas:&nbsp;</strong></p>
        <p><input name="vagas" type="number" value='1'/></p>
        <p><strong>Banheiros:&nbsp;</strong></p>
        <p><input name="banheiros" type="number" value='1'/></p>
        <p><strong>Bairro:&nbsp;</strong></p>
        <p><input id="bairros" list="bairros-list" name="bairro" type="text" /></p>
            <datalist id="bairros-list">
                <option value="Abolição">
                <option value="Anchieta">
                <option value="Andaraí">
                <option value="Anil">
                <option value="Arpoador">
                <option value="Bancários">
                <option value="Bangu">
                <option value="BarradaTijuca">
                <option value="BarrosFilho">
                <option value="Benfica">
                <option value="BentoRibeiro">
                <option value="Bonsucesso">
                <option value="Botafogo">
                <option value="BrazdePina">
                <option value="BrásdePina">
                <option value="Cachambi">
                <option value="Cacuia">
                <option value="Caju">
                <option value="Camorim">
                <option value="Campinho">
                <option value="CampoGrande">
                <option value="Cascadura">
                <option value="Castelo">
                <option value="Catete">
                <option value="Catumbi">
                <option value="Cavalcânti">
                <option value="Centro">
                <option value="CidadeNova">
                <option value="CoelhoNeto">
                <option value="Colégio">
                <option value="Copacabana">
                <option value="Cordovil">
                <option value="CosmeVelho">
                <option value="Cosmos">
                <option value="Curicica">
                <option value="DelCastilho">
                <option value="Encantado">
                <option value="EngenheiroLeal">
                <option value="EngenhoDaRainha">
                <option value="EngenhoDeDentro">
                <option value="EngenhoNovo">
                <option value="Estacio">
                <option value="Flamengo">
                <option value="Freguesia">
                <option value="Freguesia-Jacarepaguá">
                <option value="Fátima">
                <option value="Gamboa">
                <option value="Glória">
                <option value="Grajaú">
                <option value="Grumari">
                <option value="Guadalupe">
                <option value="Guaratiba">
                <option value="Gávea">
                <option value="Higienópolis">
                <option value="HonórioGurgel">
                <option value="Humaitá">
                <option value="IlhadoGovernador">
                <option value="Inhaúma">
                <option value="Inhoaíba">
                <option value="Ipanema">
                <option value="Irajá">
                <option value="Itanhangá">
                <option value="Jacarepaguá">
                <option value="Jacaré">
                <option value="JardimAmérica">
                <option value="JardimBotânico">
                <option value="JardimCarioca">
                <option value="JardimGuanabara">
                <option value="JardimOceanico">
                <option value="JardimSulacap">
                <option value="Lagoa">
                <option value="Lapa">
                <option value="Laranjeiras">
                <option value="Leblon">
                <option value="Leme">
                <option value="LinsdeVasconcelos">
                <option value="Madureira">
                <option value="MagalhãesBastos">
                <option value="Manguinhos">
                <option value="Maracanã">
                <option value="MarechalHermes">
                <option value="MariadaGraça">
                <option value="Moneró">
                <option value="Méier">
                <option value="Olaria">
                <option value="OswaldoCruz">
                <option value="Paciência">
                <option value="ParadadeLucas">
                <option value="Pavuna">
                <option value="Pechincha">
                <option value="Penha">
                <option value="PenhaCircular">
                <option value="Piedade">
                <option value="Pilares">
                <option value="Pitangueiras">
                <option value="Portuguesa">
                <option value="PraiadaBandeira">
                <option value="PraçaSeca">
                <option value="PraçadaBandeira">
                <option value="QuintinoBocaiúva">
                <option value="Ramos">
                <option value="Realengo">
                <option value="RecreioDosBandeirantes">
                <option value="Riachuelo">
                <option value="Ribeira">
                <option value="RicardodeAlbuquerque">
                <option value="RioComprido">
                <option value="Rocha">
                <option value="RochaMiranda">
                <option value="Sampaio">
                <option value="SantaCruz">
                <option value="SantaTeresa">
                <option value="SantoCristo">
                <option value="Santíssimo">
                <option value="Saúde">
                <option value="SenadorCamará">
                <option value="SenadorVasconcelos">
                <option value="Sepetiba">
                <option value="SãoConrado">
                <option value="SãoCristóvão">
                <option value="SãoFranciscoXavier">
                <option value="Tanque">
                <option value="Taquara">
                <option value="Tauá">
                <option value="Tijuca">
                <option value="TodososSantos">
                <option value="TomásCoelho">
                <option value="Turiaçu">
                <option value="Urca">
                <option value="VargemGrande">
                <option value="VargemPequena">
                <option value="VicentedeCarvalho">
                <option value="Vidigal">
                <option value="VigárioGeral">
                <option value="VilaIsabel">
                <option value="VilaKosmos">
                <option value="VilaValqueire">
                <option value="ViladaPenha">
                <option value="VistaAlegre">
                <option value="ÁguaSanta">
            </datalist>
    <!--- Adicione botão de calcular, que envia dados acima inseridos para back-end.py -->
        <input type="submit" value="Calcular">

    </form>
</h3>
</body>
</html>
#template: aluguel_calculado.html

<!-- set tittle "Aluguel Calculado" -->
<h1 style="color: #5e9ca0;">Calculadora de Aluguel da cidade do Rio de Janeiro</h1>
<!-- Add the value of aluguel who it is in aluguel variable: -->
<h2 style="color: #2e6c80;">Valor do Aluguel: R$ {{ aluguel }},00</h2>
<!-- Add back button: -->
<p><a href="{{ url_for('index') }}">Voltar</a></p><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1196644690005262, 'fraction_numerical': 0.01628130126597951, 'mean_word_length': 3.5749079580855283, 'pattern_counts': {'":': 0, '<': 254, '<?xml version=': 0, '>': 274, 'https://': 8, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '146290', 'license': 'Apache-2.0', 'n_tokens_mistral': 11419, 'n_tokens_neox': 10822, 'n_words': 2845, 'path': '_notebooks/2022_03_02_Calculadora_de_Alugueis.ipynb', 'repo_name': 'Vinicius-L-R-Matos/-Repositorio-DS', 'size': '32348'}