diff --git "a/app.py" "b/app.py" --- "a/app.py" +++ "b/app.py" @@ -1,3 +1,7 @@ +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# 1) IMPORTAÇÃO DAS BIBLIOTECAS +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + import pandas as pd import gradio as gr from gradio import components @@ -14,13 +18,21 @@ import sklearn from sklearn.preprocessing import MinMaxScaler from sklearn.ensemble import ExtraTreesRegressor import xlsxwriter -#%matplotlib inline - -#--------------------------------------------------FUNÇÕES ASSESSÓRIAS--------------------------------------------------------# +from docx import Document +from docx.shared import Pt +from docx.enum.text import WD_PARAGRAPH_ALIGNMENT +from docx.shared import Inches +from num2words import num2words +from datetime import datetime +%matplotlib inline + +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# 2) FUNÇÕES ACESSÓRIAS +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # função para conversão da escala das variáveis: def aplicar_operacao(df, scv, col_index): - if scv == 'x': + if scv == 'x' or scv == '-': pass elif scv == 'lnx': df.iloc[:, col_index] = round(np.log(df.iloc[:, col_index]), 8) @@ -45,6 +57,8 @@ def renomeia_colunas(df_dados, posicao_coluna, scv): new_column_name = old_column_name # Inicializa com o mesmo nome da coluna original if scv == 'x': pass + elif scv == '-': + pass elif scv == 'lnx': new_column_name = 'ln(' + old_column_name + ')' elif scv == '1/x': @@ -68,11 +82,12 @@ def criar_grafico_dispersao(df, x_column, y_column, hover_name, trendline_color) correlacao = df[x_column].corr(df[y_column]) # Criando o gráfico de dispersão com a linha de tendência - fig = px.scatter(df, x=x_column, y=y_column, hover_name=hover_name, trendline="ols", height=300) + fig = px.scatter(df, x=x_column, y=y_column, hover_name=hover_name, trendline="ols", height=250) # Definindo a cor de fundo e do papel fig.update_layout( plot_bgcolor='rgb(240, 240, 240)', paper_bgcolor='rgb(240, 240, 240)', + showlegend=False ) # Definindo a cor dos pontos @@ -88,25 +103,57 @@ def criar_grafico_dispersao(df, x_column, y_column, hover_name, trendline_color) font=dict(color="black") ) return fig - -#--------------------------------------------FUNÇÃO PRINCIPAL DE GERAÇÃO DE MODELOS--------------------------------------------# + +# função que cria uma coluna cos as extrapolações +def calc_extrapola(df_1, df_2): + # Inicializar a coluna 'extrapola' com strings vazias + df_1['extrapola'] = "" + + for col in df_1.columns[:-1]: # Excluir a coluna 'extrapola' da iteração + if col in df_2.columns: # Verifica se a coluna existe nos limites + # Acessa os valores de limite direto por posição na coluna correspondente + min_val = df_2[col][0] + max_val = df_2[col][1] + # Cálculo de extrapolação para cada coluna + temp_extrapola = df_1[col].apply( + lambda x: f"{col}: +{((x - max_val) / max_val) * 100:.2f}%" if x > 2 * max_val else + f"{col}: -{((min_val - x) / min_val) * 100:.2f}%" if min_val != 0 and x < 0.5 * min_val else "" + ) + # Concatenar informações de extrapolação na coluna 'extrapola' com verificação para adicionar espaço + df_1['extrapola'] = df_1.apply( + lambda row: row['extrapola'] + (" " if row['extrapola'] else "") + temp_extrapola[row.name] if temp_extrapola[row.name] else row['extrapola'], + axis=1 + ) + + # Remove o espaço extra no final de cada entrada e trata casos onde não há extrapolação + df_1['extrapola'] = df_1['extrapola'].str.rstrip() + # Preenche as células sem extrapolação com "sem extrapolação" + df_1.loc[df_1['extrapola'] == '', 'extrapola'] = 'sem extrapolação' + + return df_1 + + +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# 3) FUNÇÃO PRINCIPAL P/ GERAÇÃO DO MODELO +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # função para a regressão linear def gera_model(planilha, name_model, v_d, scv_d, - v_1, scv_1, v_2, scv_2, - v_3, scv_3, v_4, scv_4, - v_5, scv_5, v_6, scv_6, - v_7, scv_7, v_8, scv_8, - v_9, scv_9, v_10, scv_10, - v_11, scv_11, v_12, scv_12, - v_13, scv_13, v_14, scv_14, - v_15, scv_15, v_16, scv_16, - out): - - # ---------------------------------Planilha------------------------------# - - list - + scv_1, scv_2, scv_3, scv_4, + scv_5, scv_6, scv_7, scv_8, + scv_9, scv_10, scv_11, scv_12, + scv_13, scv_14, scv_15, scv_16, + out, + laudo="-",data_ref=None, data_laudo=None, + nome="-", prof="-", ent="-", uf="RS", reg="-", + lograd="-", munic="-", tipo_imo="-", solic="-", finalidade="-", objetivo="-", press="-", + infra="Água Potável", serv="Coleta de Lixo", uso="Residencial", pad_reg="-", tipo_via="-", obs_gerais="-", + per="Sem destaque", ofe="Sem destaque", liq="Sem destaque", dia="-"): + + + # IMPORTRAÇÃO DA PLANILHA # Carregando os dados df_dados = pd.read_excel(planilha.name) df_dados = df_dados.round(4) @@ -114,43 +161,101 @@ def gera_model(planilha, name_model, v_d, scv_d, # Convertendo os cabeçalhos para strings df_dados.columns = [str(col) for col in df_dados.columns] + # Convertendo as colunas onde estão o valor total e o valor unitário para float df_dados[df_dados.columns[1]] = df_dados[df_dados.columns[1]].astype(float) df_dados[df_dados.columns[2]] = df_dados[df_dados.columns[2]].astype(float) - df_original = df_dados.copy() - df_avalia = pd.DataFrame() + df_original = df_dados.copy() ################################### OUTPUT ########################################## + + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 1: + # Criação do "df_avalia" para extrair o "df_limites_var" e o "df_dados_utilizados" por meio da seleção de variáveis + # Motivo: necessidade de extração tanto dos nomes das variáveis quanto dos limites a partir do dataframe inicial. + # -----------------------------------------------------------------------------------------------------------------# + # Dataframe para criação de uma planilha de modelo para avaliação + df_avalia = pd.DataFrame() # Iterar sobre as colunas do DataFrame df_filtrado - df_avalia[df_original.columns[0]] = df_original.iloc[:, 0] - - # Iterar sobre os índices das colunas do DataFrame df_original - for i in range(3, len(df_original.columns)): + for i, col in enumerate(df_dados.columns): # Verificar se a coluna atual deve ser adicionada com base na condição e se ela existe no DataFrame - if ((i + 1) <= len(df_original.columns)) and \ - ((i + 1) in [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]): - col = df_original.columns[i] - df_avalia[col] = df_original[col] + if (i == 3 and scv_1 != "-") or \ + (i == 4 and scv_2 != "-") or \ + (i == 5 and scv_3 != "-") or \ + (i == 6 and scv_4 != "-") or \ + (i == 7 and scv_5 != "-") or \ + (i == 8 and scv_6 != "-") or \ + (i == 9 and scv_7 != "-") or \ + (i == 10 and scv_8 != "-") or \ + (i == 11 and scv_9 != "-") or \ + (i == 12 and scv_10 != "-") or \ + (i == 13 and scv_11 != "-") or \ + (i == 14 and scv_12 != "-") or \ + (i == 15 and scv_13 != "-") or \ + (i == 16 and scv_14 != "-") or \ + (i == 17 and scv_15 != "-") or \ + (i == 18 and scv_16 != "-"): + if i < len(df_dados.columns): + df_avalia[col] = df_dados.iloc[:, i] + + # Dataframe para os valores máximos e mínimos por variável + # Adicionar a coluna de índice 0 de df_dados em df_avalia (para comparação com os outliers) + df_limites_var = df_avalia.copy() + df_limites_var[df_dados.columns[0]] = df_dados.iloc[:, 0] + + # Dataframe para os dados efeticamente utilizados sem conversão de escala + df_dados_utilizados = df_avalia.copy() + # Obter o nome e os dados da primeira coluna de df_dados + first_column_name = df_dados.columns[0] + first_column_data = df_dados.iloc[:, 0] + # Inserir a nova coluna no início de df_dados_utilizados + df_dados_utilizados.insert(0, first_column_name, first_column_data) + + - # ---------------------------Nome das variáveis--------------------------# + # NOME DAS VARIÁVEIS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 2: + # Utiliza o "df_original" que é uma cópia do df_dados para criar uma lista com os nomes das colunas originais + # -----------------------------------------------------------------------------------------------------------------# - # Obtenha os nomes das colunas, excluindo a primeira ou a segunda + # Obtenha os nomes das colunas, excluindo a primeira ou a segunda if v_d == "Valor total": nomes_colunas = df_original.drop(columns=[df_original.columns[0], df_original.columns[2]]).columns else: nomes_colunas = df_original.drop(columns=[df_original.columns[0], df_original.columns[1]]).columns - # Crie a lista de strings com os cabeçalhos formatados - colunas = [f'Var dependente = {nomes_colunas[0]}'] + [f'Var {i} = {coluna}' for i, coluna in enumerate(nomes_colunas[1:], start=1)] + # Crie a lista de strings com os cabeçalhos formatados, incluindo os valores mínimos e máximos + colunas = [f'Var dependente = {nomes_colunas[0]}'] + + for i, coluna in enumerate(nomes_colunas[1:], start=1): + min_val = df_original[coluna].min() + max_val = df_original[coluna].max() + valores_unicos = df_original[coluna].unique() + + # Verifica se os valores únicos são apenas 0 e 1 + if set(valores_unicos).issubset({0, 1}): + colunas.append(f'Var {i} = {coluna} (Min: {min_val}, Max: {max_val}) - dicotômica - somente escala "x"') + else: + colunas.append(f'Var {i} = {coluna} (Min: {min_val}, Max: {max_val})') + # Transformando a lista em uma string separada por vírgula - string_colunas = ", ".join(colunas) + string_colunas = "\n".join(colunas)################################### OUTPUT ########################################## + + + + # CONVERSÃO DE ESCALAS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 3: + # Utiliza o "df_dados" para aplicar a função de conversão das escalas + # -----------------------------------------------------------------------------------------------------------------# - #-----------------------------------Escalas------------------------------# # dados if v_d == "Valor total": aplicar_operacao(df_dados, scv_d, 1) else: aplicar_operacao(df_dados, scv_d, 2) + aplicar_operacao(df_dados, scv_1, 3) aplicar_operacao(df_dados, scv_2, 4) aplicar_operacao(df_dados, scv_3, 5) @@ -167,9 +272,15 @@ def gera_model(planilha, name_model, v_d, scv_d, aplicar_operacao(df_dados, scv_14, 16) aplicar_operacao(df_dados, scv_15, 17) aplicar_operacao(df_dados, scv_16, 18) + + - #----------------------------Renomear colunas----------------------------# - + # RENOMEAR OS CABEÇALHOS DAS COLUNAS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 4: + # Utiliza o "df_dados" para aplicar a função que renomeia as colunas conforme a escala utilizada + # -----------------------------------------------------------------------------------------------------------------# + #dados if v_d == "Valor total": renomeia_colunas(df_dados, 1, scv_d) @@ -191,55 +302,61 @@ def gera_model(planilha, name_model, v_d, scv_d, renomeia_colunas(df_dados, 16, scv_14) renomeia_colunas(df_dados, 17, scv_15) renomeia_colunas(df_dados, 18, scv_16) + + - #----------------Manipulação das linhas (dados / outiliers----------------# + # MANIPULAÇÃO DAS LINHAS - RETIRADA DOS OUTLIERS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 5: + # 1) Criar os "dados_out" que são os dados removidos (é a caixa de texto de remoção dos dados na interface) + # 2) Cria o datafre de outliers, "df_outliers" excluindo os "dados_out" + # 3) Remove do dataframe "df_limites_var" os outliers para chegar num novo "df_limites_var" e nos máximos e mínimos + # 4) O "df_dados_utilizados" busca retirar os outliers do dataframe inicial (ver Comenário 1) + # 5) Criação do "df_filtrado" a partir da retirada dos outliers do "df_dados" + # 6) Contagem final da quantidade de linhas do "df_outliers" + # -----------------------------------------------------------------------------------------------------------------# # Convertendo a entrada em uma lista de inteiros dados_out = [int(num.strip()) for num in out.split(",") if num.strip()] # Filtrando o DataFrame para obter os outliers df_outliers = df_dados[df_dados.iloc[:, 0].isin(dados_out)] - - # Removendo os outliers do DataFrame original + + # Removendo os outliers do DataFrame df_limites_var para calcular os valores mínimos e máximos de cada variável + df_limites_var = df_limites_var[~df_dados.iloc[:, 0].isin(dados_out)] + # Selecionar colunas excluindo a primeira coluna (índice 0) + limites = df_limites_var.columns[:-1] + # Calcular o valor mínimo e máximo para cada coluna selecionada + minimos = df_limites_var[limites].min() + maximos = df_limites_var[limites].max() + # Criar o DataFrame df_limites_var com os valores mínimos e máximos + df_limites_var = pd.DataFrame({'Min': minimos, 'Max': maximos}) + # Se desejar transpor para que as colunas sejam 'Min' e 'Max', e os índices sejam as colunas originais do df_dados + df_limites_var_final = df_limites_var.transpose() + + #df_limites_var_final.to_excel("df_limites_var_final.xlsx", index=False) #################### OUTPUT ################## + + # Removendo os outliers do Dataframe para os dados efeticamente utilizados sem conversão de escala + df_dados_utilizados = df_dados_utilizados[~df_dados.iloc[:, 0].isin(dados_out)] + + # Removendo os outliers do DataFrame original mas que teve escalas convertidas (este será trabalhado até a regressão) df_filtrado = df_dados[~df_dados.iloc[:, 0].isin(dados_out)] + #df_filtrado.to_excel("df_filtrado.xlsx", index=False) #################### Linha de verificação ##################### # Resetando o índice de ambos os DataFrames df_filtrado.reset_index(drop=True, inplace=True) - df_outliers.reset_index(drop=True, inplace=True) + df_outliers.reset_index(drop=True, inplace=True) ############################### OUTPUT ############################## # Contagem de linhas no DataFrame resultante num_outliers = df_outliers.shape[0] - #----------------Manipulação das Colunas (variáveis)-----------------------# - # Variáveis independentes - X = pd.DataFrame() - - # Iterar sobre as colunas do DataFrame df_filtrado - for i, col in enumerate(df_filtrado.columns): - # Verificar se a coluna atual deve ser adicionada com base na condição e se ela existe no DataFrame - if (i == 3 and v_1) or \ - (i == 4 and v_2) or \ - (i == 5 and v_3) or \ - (i == 6 and v_4) or \ - (i == 7 and v_5) or \ - (i == 8 and v_6) or \ - (i == 9 and v_7) or \ - (i == 10 and v_8) or \ - (i == 11 and v_9) or \ - (i == 12 and v_10) or \ - (i == 13 and v_11) or \ - (i == 14 and v_12) or \ - (i == 15 and v_13) or \ - (i == 16 and v_14) or \ - (i == 17 and v_15) or \ - (i == 18 and v_16): - if i < len(df_filtrado.columns): - X[col] = df_filtrado.iloc[:, i] - - #X.to_excel("X.xlsx", index=False) ---> Linha de verificação - - #---------------------------Gráficos de dispersão--------------------------# + + # GRÁFICOS DE DISPERSÃO + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 6: + # Gráficos de dispersão por variável para análise inicial de pontos discrepantes + # -----------------------------------------------------------------------------------------------------------------# fig_v1 = None fig_v2 = None @@ -258,102 +375,151 @@ def gera_model(planilha, name_model, v_d, scv_d, fig_v15 = None fig_v16 = None - if v_1: + + #################### OUTPUT ################## + if scv_1 != "-": if v_d == "Valor total": fig_v1 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[3], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v1 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[3], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_2: + if scv_2 != "-": if v_d == "Valor total": fig_v2 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[4], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v2 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[4], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_3: + if scv_3 != "-": if v_d == "Valor total": fig_v3 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[5], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v3 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[5], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_4: + if scv_4 != "-": if v_d == "Valor total": fig_v4 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[6], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v4 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[6], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_5: + if scv_5 != "-": if v_d == "Valor total": fig_v5 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[7], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v5 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[7], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_6: + if scv_6 != "-": if v_d == "Valor total": fig_v6 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[8], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v6 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[8], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_7: + if scv_7 != "-": if v_d == "Valor total": fig_v7 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[9], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v7 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[9], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_8: + if scv_8 != "-": if v_d == "Valor total": fig_v8 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[10], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v8 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[10], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_9: + if scv_9 != "-": if v_d == "Valor total": fig_v9 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[11], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v9 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[11], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_10: + if scv_10 != "-": if v_d == "Valor total": fig_v10 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[12], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v10 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[12], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_11: + if scv_11 != "-": if v_d == "Valor total": fig_v11 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[13], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v11 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[13], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_12: + if scv_12 != "-": if v_d == "Valor total": fig_v12 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[14], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v12 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[14], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_13: + if scv_13 != "-": if v_d == "Valor total": fig_v13 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[15], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v13 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[15], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_14: + if scv_14 != "-": if v_d == "Valor total": fig_v14 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[16], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v14 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[16], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_15: + if scv_15 != "-": if v_d == "Valor total": fig_v15 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[17], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v15 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[17], df_filtrado.columns[2], df_filtrado.columns[0], "orange") - if v_16: + if scv_16 != "-": if v_d == "Valor total": fig_v16 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[18], df_filtrado.columns[1], df_filtrado.columns[0], "orange") else: fig_v16 = criar_grafico_dispersao(df_filtrado, df_filtrado.columns[18], df_filtrado.columns[2], df_filtrado.columns[0], "orange") + + + # MANIPULAÇÃO DAS COLUNAS - ESCOLHA DAS VARIÁVEIS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 7: + # Utiliza o "df_filtrado" (s/ outiliers) para criação do "X" (vars indep) será utilizado na regressão linear + # -----------------------------------------------------------------------------------------------------------------# + + # Variáveis independentes + X = pd.DataFrame() - #--------------------------Regressão Linerar------------------------------# + # Iterar sobre as colunas do DataFrame df_filtrado + for i, col in enumerate(df_filtrado.columns): + # Verificar se a coluna atual deve ser adicionada com base na condição e se ela existe no DataFrame + if (i == 3 and scv_1 != "-") or \ + (i == 4 and scv_2 != "-") or \ + (i == 5 and scv_3 != "-") or \ + (i == 6 and scv_4 != "-") or \ + (i == 7 and scv_5 != "-") or \ + (i == 8 and scv_6 != "-") or \ + (i == 9 and scv_7 != "-") or \ + (i == 10 and scv_8 != "-") or \ + (i == 11 and scv_9 != "-") or \ + (i == 12 and scv_10 != "-") or \ + (i == 13 and scv_11 != "-") or \ + (i == 14 and scv_12 != "-") or \ + (i == 15 and scv_13 != "-") or \ + (i == 16 and scv_14 != "-") or \ + (i == 17 and scv_15 != "-") or \ + (i == 18 and scv_16 != "-"): + if i < len(df_filtrado.columns): + X[col] = df_filtrado.iloc[:, i] + + #X.to_excel("X.xlsx", index=False) ################################ Linha de verificação ########################### + + n_vars = len(X.columns) + + # REGRESSÃO LINEAR + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 8: + # Utiliza o "X"(vars indep) que será utilizado na regressão linear e o 'y' conforme a escolha da da (var dep) + # -----------------------------------------------------------------------------------------------------------------# + # Variável dependente if v_d == "Valor total": y = df_filtrado.iloc[:, 1:2] else: y = df_filtrado.iloc[:, 2:3] - #y.to_excel("y.xlsx", index=False) ---> Linha de verificação + #y.to_excel("y.xlsx", index=False) ################################ Linha de verificação ########################### - #---------------------ExtraTreesRegressor--------------------# + + + # EXTRATREESREGRESSIOR + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 9: + # Inserção no código para a implementação do algorítmo de importância das variáveis + # -----------------------------------------------------------------------------------------------------------------# scaler_x = MinMaxScaler() scaler_y = MinMaxScaler() - + input_scaler = scaler_x.fit(X) output_scaler = scaler_y.fit(y) @@ -366,31 +532,32 @@ def gera_model(planilha, name_model, v_d, scv_d, model = ExtraTreesRegressor() model.fit(x_norm,new_y) - - # Criando o gráfico de influência das variáveis + feat_importances = pd.Series(model.feature_importances_, index=X.columns) - #feat_importances.nlargest(16).plot(kind='barh', color = 'orange') - #plt.title('Influência das Variáveis') - #plt.xlabel('Importância') - #plt.ylabel('Variáveis') - #plt.gca().set_facecolor('#f0f0f5') - #plt.tight_layout() - #plt.grid(True) - - # Salvar o gráfico como imagem - #plt.savefig('influencia_variaveis.png') + # Converter para uma lista de tuplas + feat_importances_list = [(feature, round(importance * 100, 2)) for feature, importance in feat_importances.items()] + # Ordenar a lista em ordem decrescente de importância + feat_importances_list.sort(key=lambda x: x[1], reverse=True) + + # MODELO + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 10: + # 1) Adicionando uma constante no X + # 2) Inicializando o modelo e ajustando o modelo aos dados + # 3) Resultados diversos + # 4) Equação do modelo + # -----------------------------------------------------------------------------------------------------------------# - #----------------------------Modelo----------------------------# # Adicionando uma constante às variáveis independentes (intercepto) X = sm.add_constant(X) # Inicializando o modelo de regressão linear modelo = sm.OLS(y, X) - # Ajustando o modelo aos dados resultado = modelo.fit() + # Resultados # Calculando os resíduos do modelo residuos = resultado.resid # Calculando Desvio Padrão dos Resíduos @@ -439,20 +606,75 @@ def gera_model(planilha, name_model, v_d, scv_d, # Calcular a distância de Cook distancia_cook = resultado.get_influence().cooks_distance[0] + # Exibindo estatísticas do modelo + resultado_summary = resultado.summary() + resultado_html = resultado.summary().tables[1].as_html() ########################## OUTPUT ############################### + resultados_vars = pd.DataFrame(resultado.summary().tables[1].data[1:], columns=resultado.summary().tables[1].data[0]) + resultados_vars['P>|t|'] = pd.to_numeric(resultados_vars['P>|t|'], errors='coerce') + + # ENQUADRAMENTOS NOS GRAUS DE FUNDAMENTAÇÃO + # -----------------------------------------------------------------------------------------------------------------# + # Item 2 da tabela Item 9.2.1 da NBR 14.653-2 + if num_observacoes >= 6 * (n_vars + 1): + tab2 = "Grau III" + elif num_observacoes >= 4 * (n_vars + 1): + tab2 = "Grau II" + elif num_observacoes >= 3 * (n_vars + 1): + tab2 = "Grau I" + else: + tab2 = "Fora dos critérios" + + # Item 5 da tabela Item 9.2.1 da NBR 14.653-2 + def classificar(valor): + if valor > 0.3: + return "Fora dos critérios" + elif valor > 0.2: + return "Grau I" + elif valor > 0.1: + return "Grau II" + else: + return "Grau III" + + resultados_vars['Classificação'] = resultados_vars['P>|t|'].apply(classificar) + + # Determinar o grau único levando em consideração todas as variáveis + def determinar_grau_unico(classificacoes): + if "Fora dos critérios" in classificacoes: + return "Fora dos critérios" + elif "Grau I" in classificacoes: + return "Grau I" + elif "Grau II" in classificacoes: + return "Grau II" + else: + return "Grau III" + + tab5 = determinar_grau_unico(resultados_vars['Classificação']) + + + # Item 6 da tabela Item 9.2.1 da NBR 14.653-2 + if nivel_significancia <= 0.01 : + tab6 = "Grau III" + elif nivel_significancia <= 0.02 : + tab6 = "Grau II" + elif nivel_significancia <= 0.05 : + tab6 = "Grau I" + else: + tab6 = "Fora dos critérios" + + + # String com os resultados + ################################### OUTPUT ########################################## resultados_gerais = f""" Desvio Padrão: {desvio_padrao_residuos} - Estatística F: {estatistica_F} - Nível de Significância do Modelo: {nivel_significancia} - - R²: {r_squared} - R² ajustado: {r_squared_adjusted} - Correlação: {coef_correlacao} + Estatística F: {estatistica_F} / Nível de Significância Modelo: {nivel_significancia} + R²: {r_squared} / R² ajustado: {r_squared_adjusted} / Correlação: {coef_correlacao} Número de observações: {num_observacoes} Número de dados não utilizados: {num_outliers} - + Número de variáveis utilizadas: {n_vars} + Importância Variáveis em % (ExtraTreesRegressor): {feat_importances_list} + ------------------------------------------------------ Testes de normalidade: - 1) Comparação (curva normal): Ideal 68% - aceitável de 64% a 75% Ideal 90% - aceitável de 88% a 95% @@ -465,8 +687,12 @@ def gera_model(planilha, name_model, v_d, scv_d, - Valor-p: {p_value} - Assimetria (Skewness): {skewness} - Curtose (Kurtosis): {kurtosis} + ------------------------------------------------------ + Fundamentação - Quant. min. dados (Item 2 tab 9.2.1 NBR 14.653-2): {tab2} + Fundamentação - Signif. Regressores (Item 5 tab 9.2.1 NBR 14.653-2): {tab5} + Fundamentação - Signif. Modelo (Item 6 tab 9.2.1 NBR 14.653-2): {tab6} """ - + # Equação do modelo if v_d == "Valor total": equacao_modelo = df_filtrado.columns[1] + '=' @@ -483,40 +709,72 @@ def gera_model(planilha, name_model, v_d, scv_d, equacao_modelo += f" {coeficiente:.8f} * {nome_coluna} +" # Remover o último sinal de adição - equacao_modelo = equacao_modelo[:-1] - # Exibindo estatísticas do modelo - resultado_summary = resultado.summary() - resultado_html = resultado.summary().tables[1].as_html() - # Obtenha as estatísticas do modelo em formato de DataFrame - #resultado_summary_df = pd.DataFrame(resultado_summary.tables[1]) + equacao_modelo = equacao_modelo[:-1] ################################### OUTPUT ########################################## - #----------------------------df_final (regressão)----------------------------# + + # DATAFRAME RESULTANTE DA REGRESSÃO "df_final" + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 11: + # 1) Concatenando o "X" e o "y" para a criação do "df_final" e na sequência acrescentando o índice do "df_filtrado" + # 2) Cria 'df_exporta_modelo' que será a aba no excel que servirá para salvar os parâmntros do modelo + # -----------------------------------------------------------------------------------------------------------------# # Adicionando a primeira coluna de df_filtrado ao início de df_final ordem = df_filtrado[[df_filtrado.columns[0]]].copy() df_final = pd.concat([ordem, y, X], axis=1) - # Exporta modelo + # Dataframe que servirá para 'salvar' os parâmtros do modelo em um arqivo .xlsx df_exporta_modelo = df_final.copy() + # Retirandso a coluna da constante do "df_final" df_final = df_final.drop(columns=['const']) + + + + # MATRIZ DE CORRELAÇÕES + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 12: + # Utilizando o "df_final" para a criação da matriz de correlações + # -----------------------------------------------------------------------------------------------------------------# + + # Calculando correlações + correlation_matrix = df_final.corr() + # Removendo a primeira coluna, assumindo que seja a primeira + correlation_matrix = correlation_matrix.iloc[1:, 1:] + + - #--------------------df_final (adiciona o erro_padronizado)------------------# - + # ADICIONANDO O ERRO PADRONIZADO + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 13: + # 1) Adicionando o erro padronizado ao "df_final" + # 2) Criando o 'df_maiores_que_2' com os outliers (são os dados imputados na textbox. Ver o item 1) do Comentário 5 + # 3) Criação da listagem que com os outliers que podem ser copiadas e coladas no textbox p/ retirar dados + # -----------------------------------------------------------------------------------------------------------------# # Adicionando a coluna de erro padronizado ao df_final df_final['Erro Padronizado'] = erro_padronizado - #-------------------df_maiores_que_2 (possíveis outliers)--------------------# - # Criar DataFrame apenas com os dados cujo erro padronizado é maior que 2 df_maiores_que_2 = df_final[abs(df_final['Erro Padronizado']) > 2] - df_maiores_que_2['Erro Abs'] = abs(df_maiores_que_2['Erro Padronizado']) + df_maiores_que_2['Erro Abs'] = abs(df_maiores_que_2['Erro Padronizado']) ################### OUTPUT ################## # Listagem de pontos com resíduos > 2 - Listagem_df_maiores_que_2 = ", ".join(map(str, df_maiores_que_2.iloc[:, 0].tolist())) + Listagem_df_maiores_que_2 = ", ".join(map(str, df_maiores_que_2.iloc[:, 0].tolist())) ############ OUTPUT ############ - #------------df_correl (Valores Ajustados x Preços Observados)---------------# + + + # VALORES AJUSTADOS X PREÇOS OBSERVADOS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 14: + # 1) Calculando os valores de 'X'. Ver o item 1) do comentário 10 + # 2) Adicionando estes valores ao 'df_final' + # 3) A partir do 'df_final' é criado o 'df_correl' somente com as colunas 'Observados' e 'Calculados' + # 4) Criação de uma cópia do 'df_correl', antes de desfazer a conversão das escalas, para plotagem de um gráfico + # 5) Desfazendo a conversão das escalas para concatenar ao 'df_final' + # 6) Criando a coluna 'Diferença %' no 'df_correl' + # 7) Faznedo o merge do 'df_final' e do 'df_correl' + # -----------------------------------------------------------------------------------------------------------------# # Obtendo os valores previstos # Dados @@ -524,40 +782,71 @@ def gera_model(planilha, name_model, v_d, scv_d, # Adicionando os valores previstos como uma nova coluna ao df_final df_final['Valores Ajustados'] = round(valores_previstos, 8) + # Criando uma dataframe para os Valores Ajustados x Preços Observados if v_d == "Valor total": df_correl = df_final[[df_filtrado.columns[0], df_filtrado.columns[1], 'Valores Ajustados']] - df_correl = df_correl.rename(columns={df_filtrado.columns[1]: 'Preços Observados'}) + df_correl = df_correl.rename(columns={df_filtrado.columns[1]: 'Observados'}) + df_correl = df_correl.rename(columns={'Valores Ajustados': 'Calculados'}) else: df_correl = df_final[[df_filtrado.columns[0], df_filtrado.columns[2], 'Valores Ajustados']] - df_correl = df_correl.rename(columns={df_filtrado.columns[2]: 'Preços Observados'}) + df_correl = df_correl.rename(columns={df_filtrado.columns[2]: 'Observados'}) + df_correl = df_correl.rename(columns={'Valores Ajustados': 'Calculados'}) + # Criação de uma cópia do 'df_correl' df_correl_grafico = df_correl.copy() + # Desfazendo a conversão da escala if scv_d == 'lny': - df_correl['Valores Ajustados'] = round(np.exp(df_correl['Valores Ajustados']), 8) - df_correl['Preços Observados'] = round(np.exp(df_correl['Preços Observados']), 8) + df_correl['Calculados'] = round(np.exp(df_correl['Calculados']), 8) + df_correl['Observados'] = round(np.exp(df_correl['Observados']), 8) elif scv_d == '1/y': - df_correl['Valores Ajustados'] = round(1 / df_correl['Valores Ajustados'], 8) - df_correl['Preços Observados'] = round(1 / df_correl['Preços Observados'], 8) + df_correl['Calculados'] = round(1 / df_correl['Calculados'], 8) + df_correl['Observados'] = round(1 / df_correl['Observados'], 8) elif scv_d == 'y²': - df_correl['Valores Ajustados'] = round(np.sqrt(df_correl['Valores Ajustados']), 8) - df_correl['Preços Observados'] = round(np.sqrt(df_correl['Preços Observados']), 8) + df_correl['Calculados'] = round(np.sqrt(df_correl['Calculados']), 8) + df_correl['Observados'] = round(np.sqrt(df_correl['Observados']), 8) else: pass # Nenhuma transformação é necessária - df_correl['Diferença %'] = round(((df_correl['Valores Ajustados']/df_correl['Preços Observados'])-1)*100, 8) + # Criando uma coluna de diferença percentual + ################################### OUTPUT ########################################## + df_correl['Diferença %'] = round(((df_correl['Calculados']/df_correl['Observados'])-1)*100, 8) + + + # Usando a primeira coluna de cada DataFrame como chave para o merge + ################################### OUTPUT ########################################## + df_final_2 = pd.merge(df_final, df_correl, left_on=df_final.columns[0], right_on=df_correl.columns[0], how='left') - #-------------------------------Modelo para EXCEL---------------------------# + + + # ARQUIVO EXCEL + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 15: + # 1) Cria um output de planilha do excel vazio e: + # 2) Acrescenta 'df_original': planilha original de dados (todas as variáveis, sem conversão de escala e todos os dados) + # 3) Acrescenta 'df_dados_utilizados': somente as variáveis e os dados utilizado (sem conversão de escala) + # 4) Acrescenta 'df_outliers': dados retidados do modelo + # 5) Acrescenta 'df_correl': Obs x Calc + # 6) Cria um aba no arquivo com o nome 'Resultados' e acrescenta todos os resultados estatísticos + # 7) Acrescenta o 'df_exporta_modelo' com o nome 'Model'. Ver item 2) do Comentáro 11. Serve p/ carregar modelo futuramente + # 8) Cria uma aba chamada 'avaliando' que serve de modelo para quando este modelo cfora carregado novamente + # -----------------------------------------------------------------------------------------------------------------# - output_file = 'modelo.xlsx' - output_file = output_file.replace('modelo', name_model) + current_date = datetime.now().strftime("%d%b%y").lower() + + output_file = 'modelo.xlsx' ################################### OUTPUT ########################################## + output_file = f"{name_model}_model_{current_date}.xlsx" with pd.ExcelWriter(output_file, engine='xlsxwriter') as writer: - # Salve o DataFrame 'DADOS INICIAIS' na planilha 'relatório' + # Salve o DataFrame 'DADOS INICIAIS' na planilha df_original.to_excel(writer, sheet_name='Dados Originais', index=False) - # Salve o DataFrame 'DADOS NÃO UTILIZADOS' na planilha 'relatório' - df_outliers.to_excel(writer, sheet_name='Dados Não utilizados', index=False) - # Salve o DataFrame 'PLANILHA OBS X CALC' na planilha 'relatório' + # Salve o DataFrame 'DADOS UTILIZADOS' na planilha + df_dados_utilizados.to_excel(writer, sheet_name='Dados Utilizados', index=False) + # Salve o DataFrame 'DADOS NÃO UTILIZADOS' na planilha + df_outliers.to_excel(writer, sheet_name='Dados Não utilizados', index=False) + # Salve o DataFrame 'MÁXIMOS E MÍNIMOS' na planilha + df_limites_var_final.to_excel(writer, sheet_name='Fronteiras', index=False) + # Salve o DataFrame 'PLANILHA OBS X CALC' na planilha df_correl.to_excel(writer, sheet_name='Obs x Calc', index=False) # String com os resultados @@ -570,83 +859,253 @@ def gera_model(planilha, name_model, v_d, scv_d, 'Correlação': [coef_correlacao], 'Número de observações': [num_observacoes], 'Número de dados não utilizados': [num_outliers], - '- Estatística Jarque-Bera': [jarque_bera_test], - '- Valor-p': [p_value], - '- Assimetria (Skewness)': [skewness], - '- Curtose (Kurtosis)': [kurtosis], + 'Número de variáveis utilizadas': [n_vars], + '1) Comparação (curva normal 68% 90% 65%)': [perc_resid], + '2) Teste Kolmogorov-Smirnov (KS)': [ks_test], + '3) Estatística do teste': [jarque_bera_test], + '- Valor-p': [p_value], + '- Assimetria (Skewness)': [skewness], + '- Curtose (Kurtosis)': [kurtosis], + 'Fundamentação - Quant. min. dados (Item 2 tab 9.2.1 NBR 14.653-2)': [tab2], + 'Fundamentação - Signif. Regressores (Item 5 tab 9.2.1 NBR 14.653-2)': [tab5], + 'Fundamentação - Signif. Modelo (Item 6 tab 9.2.1 NBR 14.653-2)': [tab6] }) + # Transponha o DataFrame resultados = resultados.T.reset_index() # Defina os nomes das colunas do novo DataFrame - resultados.columns = ['Nome da Coluna', 'Valor'] - resultados.to_excel(writer, sheet_name='Resultados', index=False) + resultados.columns = ['Resultado', 'Valor'] + resultados.to_excel(writer, sheet_name='Result_gerais', index=False) + + # Salve o DataFrame 'RESULTADOS VARS' na planilha + resultados_vars.to_excel(writer, sheet_name='Result_vars', index=False) - # Salve o DataFrame 'DADOS PARA REGRESSÃO' na planilha 'relatório' + # Salve o DataFrame 'DADOS PARA REGRESSÃO' na planilha df_exporta_modelo.to_excel(writer, sheet_name='Model', index=False) # Salve o DataFrame 'PLANILHA MODELO PARA AVALIAÇÃO' na planilha 'relatório' - df_avalia.to_excel(writer, sheet_name='Avalia', index=False) + df_avalia_copy = df_avalia.copy() + df_avalia_copy = df_avalia_copy.iloc[0:0] + df_avalia_copy.to_excel(writer, sheet_name='avaliando', index=False) + + + + # PONTOS INFLUENCIANTES + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 16: + # 1) Por meio da distância de cook, calcula-se os pontos influeniantes + # -----------------------------------------------------------------------------------------------------------------# + + limite_cook = 1 + pontos_influentes = [] + for i, cook_dist in enumerate(distancia_cook): + if cook_dist > limite_cook: + pontos_influentes.append(df_final.iloc[i, 0]) # Usando a primeira coluna como rótulo + + # Transformando a lista em uma string separada por vírgula + string_pontos_influentes = ", ".join(map(str, pontos_influentes)) ##################### OUTPUT ##################### + + - #----------------------------------Avaliação--------------------------------# + # GRÁFICOS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 17: + # 1) Gráfico de resíduos padronizados + # 2) Histograma de resíduos + # 3) Pontos influenciantes + # 4) Gráfico de Valores ajustados x Preços observados + # 5) Gráfico do ExtraTreesRegessor - influência das variáveis. Ver Comentário 9 + # 6) Matriz de correlações + # -----------------------------------------------------------------------------------------------------------------# + + # Gráfico dos resíduos padronizados + fig, ax1 = plt.subplots(figsize=(8, 5)) + ax1.scatter(df_final['Valores Ajustados'], erro_padronizado, color='orange', alpha=0.6) + ax1.axhline(y=0, color='black', linestyle='--', linewidth=1) # Linha zero + ax1.axhline(y=2, color='red', linestyle='-', linewidth=1) # Linhas vermelhas em ±2 + ax1.axhline(y=-2, color='red', linestyle='-', linewidth=1) + ax1.set_title('Gráfico de Resíduos Padronizados') + ax1.set_xlabel('Valores Ajustados') + ax1.set_ylabel('Resíduos Padronizados') + ax1.grid(True) + for i, txt in enumerate(df_final.iloc[:, 0]): + if abs(erro_padronizado[i]) > 2: + ax1.annotate(txt, (df_final['Valores Ajustados'][i], erro_padronizado[i]), xytext=(5, 5), + textcoords='offset points', fontsize=12, color='darkred') + fig.savefig('residuos_padronizados.png') + plt.close(fig) # Fecha a figura para que o próximo gráfico seja independente + + # Histograma dos resíduos padronizados + fig, ax2 = plt.subplots(figsize=(8, 5)) + sns.histplot(erro_padronizado, kde=True, color='orange', alpha=0.6, ax=ax2) + ax2.set_title('Histograma dos Resíduos Padronizados') + ax2.set_xlabel('Resíduos Padronizados') + ax2.set_ylabel('Frequência') + ax2.grid(True) + fig.savefig('histograma_residuos_padronizados.png') + plt.close(fig) + + # Gráfico da distância de Cook + fig, ax3 = plt.subplots(figsize=(8, 5)) + ax3.plot(distancia_cook, marker='o', linestyle='None', color='orange') + ax3.axhline(y=1, color='red', linestyle='--', linewidth=1) + ax3.set_title('Gráfico da Distância de Cook') + ax3.set_xlabel('Número da Observação') + ax3.set_ylabel('Distância de Cook') + ax3.grid(True) + for i, valor in enumerate(distancia_cook): + if valor > 1: + ax3.annotate(str(i), (i, valor), xytext=(5, 5), textcoords='offset points', fontsize=12, color='darkred') + fig.savefig('distancia_cook.png') + plt.close(fig) + + # Gráfico Valores Ajustados vs Preços Observados + fig, ax4 = plt.subplots(figsize=(8, 5)) + x_values = df_correl_grafico['Observados'] + y_values = df_correl_grafico['Calculados'] + slope, intercept = np.polyfit(x_values, y_values, 1) + ax4.scatter(x_values, y_values, color='black') + ax4.plot(x_values, slope * x_values + intercept, color='orange', linestyle='--', linewidth=2) + ax4.set_title('Valores Ajustados vs Preços Observados') + ax4.set_xlabel('Preços Observados') + ax4.set_ylabel('Valores Ajustados') + ax4.grid(True) + fig.savefig('valores_ajustados_vs_observados.png') + plt.close(fig) + + # Matriz de correlações + fig, ax6 = plt.subplots(figsize=(8, 5)) + ax6.set_title('Matriz de Correlação') + palette = sns.light_palette("orange", as_cmap=True) + sns.heatmap(correlation_matrix, annot=True, cmap=palette, linewidths=0.3, ax=ax6, annot_kws={"size": 6}, + cbar_kws={"shrink": 0.8}) + fig.savefig('matriz_correlacao.png') + plt.close(fig) + ################################### OUTPUT ########################################## + + + # AVALIAÇÃO + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 18: + # 1) No momento de gerar modelo é é possível, por meio da aba "avaliando" da planilha imputada, fazer uma avalaição + # 2) Criadas duas cópias do "df_aval". + # -----------------------------------------------------------------------------------------------------------------# try: # Carregando o(s) avaliando(s) df_aval = pd.read_excel(planilha.name, 'avaliando') - df_aval_original = df_aval.copy() # avaliando(s) - if v_d == "Valor total": - aplicar_operacao(df_aval, scv_d, 1) - else: - aplicar_operacao(df_aval, scv_d, 2) - aplicar_operacao(df_aval, scv_1, 3) - aplicar_operacao(df_aval, scv_2, 4) - aplicar_operacao(df_aval, scv_3, 5) - aplicar_operacao(df_aval, scv_4, 6) - aplicar_operacao(df_aval, scv_5, 7) - aplicar_operacao(df_aval, scv_6, 8) - aplicar_operacao(df_aval, scv_7, 9) - aplicar_operacao(df_aval, scv_8, 10) - aplicar_operacao(df_aval, scv_9, 11) - aplicar_operacao(df_aval, scv_10, 12) - aplicar_operacao(df_aval, scv_11, 13) - aplicar_operacao(df_aval, scv_12, 14) - aplicar_operacao(df_aval, scv_13, 15) - aplicar_operacao(df_aval, scv_14, 16) - aplicar_operacao(df_aval, scv_15, 17) - aplicar_operacao(df_aval, scv_16, 18) - + + df_aval_final = df_aval.copy() + df_aval_original = pd.DataFrame() + + + + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 19: + # 1) O 'df_aval_final' serve como agregador das informações, mantendo a forma original para posterior apresentação + # -----------------------------------------------------------------------------------------------------------------# + # Para criar um dataframe final sem as escalas convertidas e apenas com as variáveis escolhidas + for i, col in enumerate(df_aval_final.columns): + # Verificar se a coluna atual deve ser adicionada com base na condição e se ela existe no DataFrame + if (i == 0 and scv_1 != "-") or \ + (i == 1 and scv_2 != "-") or \ + (i == 2 and scv_3 != "-") or \ + (i == 3 and scv_4 != "-") or \ + (i == 4 and scv_5 != "-") or \ + (i == 5 and scv_6 != "-") or \ + (i == 6 and scv_7 != "-") or \ + (i == 7 and scv_8 != "-") or \ + (i == 8 and scv_9 != "-") or \ + (i == 9 and scv_10 != "-") or \ + (i == 10 and scv_11 != "-") or \ + (i == 11 and scv_12 != "-") or \ + (i == 12 and scv_13 != "-") or \ + (i == 13 and scv_14 != "-") or \ + (i == 14 and scv_15 != "-") or \ + (i == 15 and scv_16 != "-"): + + if i < len(df_aval_final.columns): + df_aval_original[col] = df_aval_final.iloc[:, i] + + #df_aval_original.to_excel("df_aval_original.xlsx") ##################### Linha de verificação ################## + #df_var_ext = calc_extrapola(df_aval_original, df_limites_var) ############# Linha de verificação ############### + + + + # VERIFICAÇÃO DA EXTRAPOLAÇÃO DSA VARIÁVEIS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 20: + # 1) A partir do 'df_aval_original' cria-se a coluna "extrapola" pela função 'calc_extrapola' + # -----------------------------------------------------------------------------------------------------------------# + # Aplicação da função para criação de coluna com estrapolação das variáveis + calc_extrapola(df_aval_original, df_limites_var_final) + + + + # DATAFRAME PARA IMPUTAR NO MODELO + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 21: + # 1) A partir do 'df_aval' faz-se a conversão das escalas + # 2) Criação do 'X_aval' (variáveis independentes dos dados) + # 3) Agregando os valores previstos no 'df_aval_original' + # 4) Cálculo do Campo de Arbítrio e Intervalo de Confiança de 80%, agregando as colunas ao 'df_aval_original' + # 5) Cálculo da 'Precisão' e criação de coluna no 'df_aval_original' + # -----------------------------------------------------------------------------------------------------------------# + # alterar escalas (para rodar o modelo) + aplicar_operacao(df_aval, scv_1, 0) + aplicar_operacao(df_aval, scv_2, 1) + aplicar_operacao(df_aval, scv_3, 2) + aplicar_operacao(df_aval, scv_4, 3) + aplicar_operacao(df_aval, scv_5, 4) + aplicar_operacao(df_aval, scv_6, 5) + aplicar_operacao(df_aval, scv_7, 6) + aplicar_operacao(df_aval, scv_8, 7) + aplicar_operacao(df_aval, scv_9, 8) + aplicar_operacao(df_aval, scv_10, 9) + aplicar_operacao(df_aval, scv_11, 10) + aplicar_operacao(df_aval, scv_12, 11) + aplicar_operacao(df_aval, scv_13, 12) + aplicar_operacao(df_aval, scv_14, 13) + aplicar_operacao(df_aval, scv_15, 14) + aplicar_operacao(df_aval, scv_16, 15) + + # Criando um dataframe apenas com as variáveis escolhidas e com as escalas convertidas. X_aval = pd.DataFrame() - - # Iterar sobre as colunas do DataFrame df_filtrado + # Iterar sobre as colunas do DataFrame para fazer a predição de valor for i, col in enumerate(df_aval.columns): # Verificar se a coluna atual deve ser adicionada com base na condição e se ela existe no DataFrame - if (i == 3 and v_1) or \ - (i == 4 and v_2) or \ - (i == 5 and v_3) or \ - (i == 6 and v_4) or \ - (i == 7 and v_5) or \ - (i == 8 and v_6) or \ - (i == 9 and v_7) or \ - (i == 10 and v_8) or \ - (i == 11 and v_9) or \ - (i == 12 and v_10) or \ - (i == 13 and v_11) or \ - (i == 14 and v_12) or \ - (i == 15 and v_13) or \ - (i == 16 and v_14) or \ - (i == 17 and v_15) or \ - (i == 18 and v_16): + if (i == 0 and scv_1 != "-") or \ + (i == 1 and scv_2 != "-") or \ + (i == 2 and scv_3 != "-") or \ + (i == 3 and scv_4 != "-") or \ + (i == 4 and scv_5 != "-") or \ + (i == 5 and scv_6 != "-") or \ + (i == 6 and scv_7 != "-") or \ + (i == 7 and scv_8 != "-") or \ + (i == 8 and scv_9 != "-") or \ + (i == 9 and scv_10 != "-") or \ + (i == 10 and scv_11 != "-") or \ + (i == 11 and scv_12 != "-") or \ + (i == 12 and scv_13 != "-") or \ + (i == 13 and scv_14 != "-") or \ + (i == 14 and scv_15 != "-") or \ + (i == 15 and scv_16 != "-"): + if i < len(df_aval.columns): X_aval[col] = df_aval.iloc[:, i] + + + # Adicionando a constante + X_aval.insert(0, 'const', 1) ############################# Linha de verificação ############################### - X_aval.insert(0, 'const', 1) - - # Avaliando(s) + # Avaliando(s) no modelo para predição de valor valores_previstos_aval = resultado.predict(X_aval) df_aval_original['VALOR'] = round(valores_previstos_aval, 8) + # Desfazendo a conversão das escalas if scv_d == 'lny': df_aval_original['VALOR'] = round(np.exp(df_aval_original['VALOR']), 8) elif scv_d == '1/y': @@ -692,109 +1151,261 @@ def gera_model(planilha, name_model, v_d, scv_d, df_aval_original.loc[(df_aval_original['TOTAL_IC_%'] > 30) & (df_aval_original['TOTAL_IC_%'] <= 40), 'PRECISÃO'] = "Grau II" df_aval_original.loc[(df_aval_original['TOTAL_IC_%'] > 40) & (df_aval_original['TOTAL_IC_%'] <= 50), 'PRECISÃO'] = "Grau I" df_aval_original.loc[df_aval_original['TOTAL_IC_%'] > 50, 'PRECISÃO'] = "Fora dos critérios" - - # Retirando as colunas valor total e valor unitário - df_aval_original = df_aval_original.drop(df_aval_original.columns[[1, 2]], axis=1) - # Salve o DataFrame 'result' em uma planilha - df_aval_original.to_excel("planilha_aval.xlsx", index=False) + + # Criação de um índice para os avaliandos + df_aval_original.insert(0, 'nº_aval', range(1, len(df_aval_original) + 1)) + + + # DATA FRAME COM AS EXTRAPOLAÇÕES + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 22: + # 1) Cria o 'df_resultado' a partir do uma cópia do 'df_aval_original' + # 2) A partir do uma cópia do 'df_resultado', cria-se o 'X_ext' (na fronteira), para aplicação no modelo + # 3) Reisere-se os valor previstos (convertendos as escalas) em uma coluna do 'df_resultado' + # 4) Reisere-se os valor previstos (convertendos as escalas) na coluna 'VALOR_ext' do 'df_aval_original' + # -----------------------------------------------------------------------------------------------------------------# + #if not df_aval_original.empty: + # Copiar o DataFrame original + df_resultado = df_aval_original.copy() + + # Filtrar os dados onde 'extrapola' não é 'sem extrapolação' + df_resultado = df_resultado[df_resultado['extrapola'] != 'sem extrapolação'] + + # Separar a coluna 'nº_aval' antes de fazer qualquer seleção de colunas + numeracao = df_resultado['nº_aval'] + + # Excluir a coluna 'nº_aval' temporariamente para o processamento + df_resultado = df_resultado.drop(columns=['nº_aval']) + + # Encontre o índice da coluna 'extrapola' + indice_extrapola = df_resultado.columns.get_loc('extrapola') + # Selecione todas as colunas até a coluna 'extrapola' + df_resultado = df_resultado.iloc[:, :indice_extrapola] + + # Loop para ajustar os valores conforme os limites + for index, row in df_resultado.iterrows(): + for col in df_resultado.columns: + valor = row[col] + limite_min = df_limites_var_final.iloc[0][col] + limite_max = df_limites_var_final.iloc[1][col] + + # Substituir se o valor for menor que o limite mínimo + if valor < limite_min: + df_resultado.at[index, col] = limite_min + # Substituir se o valor for maior que o limite máximo + elif valor > limite_max: + df_resultado.at[index, col] = limite_max + + # Reinsere a coluna 'nº_aval' no DataFrame + df_resultado['nº_aval'] = numeracao.values + + # Reorganiza as colunas para garantir que 'nº_aval' seja a primeira + cols = ['nº_aval'] + [col for col in df_resultado.columns if col != 'nº_aval'] + df_resultado = df_resultado[cols] + + # Exibir o resultado final + X_ext = df_resultado.copy() + X_ext = X_ext.iloc[:, 1:] + + # alterar escalas (para rodar o modelo) + aplicar_operacao(X_ext, scv_1, 0) + aplicar_operacao(X_ext, scv_2, 1) + aplicar_operacao(X_ext, scv_3, 2) + aplicar_operacao(X_ext, scv_4, 3) + aplicar_operacao(X_ext, scv_5, 4) + aplicar_operacao(X_ext, scv_6, 5) + aplicar_operacao(X_ext, scv_7, 6) + aplicar_operacao(X_ext, scv_8, 7) + aplicar_operacao(X_ext, scv_9, 8) + aplicar_operacao(X_ext, scv_10, 9) + aplicar_operacao(X_ext, scv_11, 10) + aplicar_operacao(X_ext, scv_12, 11) + aplicar_operacao(X_ext, scv_13, 12) + aplicar_operacao(X_ext, scv_14, 13) + aplicar_operacao(X_ext, scv_15, 14) + aplicar_operacao(X_ext, scv_16, 15) + + X_ext.insert(0, 'const', 1) ############################### Linha de verificação ################################ + + # Avaliando(s) + valores_previstos_ext = resultado.predict(X_ext) + df_resultado['VALOR'] = round(valores_previstos_ext, 8) + + if scv_d == 'lny': + df_resultado['VALOR'] = round(np.exp(df_resultado['VALOR']), 8) + elif scv_d == '1/y': + df_resultado['VALOR'] = round(1 / df_resultado['VALOR'], 8) + elif scv_d == 'y²': + df_resultado['VALOR'] = round(np.sqrt(df_resultado['VALOR']), 8) + else: + pass # Nenhuma transformação é necessária + df_resultado ################################ Linha de verificação ################################ + + + df_aval_original['VALOR_fronteira'] = round(valores_previstos_ext, 8) + + if scv_d == 'lny': + df_aval_original['VALOR_fronteira'] = round(np.exp(df_aval_original['VALOR_fronteira']), 8) + elif scv_d == '1/y': + df_aval_original['VALOR_fronteira'] = round(1 / df_aval_original['VALOR_fronteira'], 8) + elif scv_d == 'y²': + df_aval_original['VALOR_fronteira'] = round(np.sqrt(df_aval_original['VALOR_fronteira']), 8) + else: + pass # Nenhuma transformação é necessária + + + # Salve o DataFrame 'result' em uma planilha + df_aval_original.to_excel("planilha_aval.xlsx", index=True) ####################### OUTPUT ####################### + except: # Se a aba não existir, crie um DataFrame vazio df_aval_original = pd.DataFrame() # Salve o DataFrame em uma planilha - df_aval_original.to_excel("planilha_aval.xlsx", index=False) - - #-----------------------------------------------Gráficos-------------------------------------------------# + df_aval_original.to_excel("planilha_aval.xlsx", index=True) + + # LAUDO + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 27: + # 1) Cria as strings patra as seções do laudo + # 2) Gera documento em word + # -----------------------------------------------------------------------------------------------------------------# + + # criação de strings para os relatórios da interface e do word + + trabalho = f""" + Identificação do trabalho técnico: {laudo} + Data de referência do laudo: {data_ref} + Data de elaboração do laudo: {data_laudo} + """ - # Criando subplots - fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, 1, figsize=(15, 20)) - - # Gráfico dos resíduos padronizados - ax1.scatter(df_final['Valores Ajustados'], erro_padronizado, color='orange', alpha=0.6) - ax1.axhline(y=0, color='black', linestyle='--', linewidth=1) # Linha zero - ax1.axhline(y=2, color='red', linestyle='-', linewidth=1) # Linhas vermelhas em ±2 - ax1.axhline(y=-2, color='red', linestyle='-', linewidth=1) - ax1.set_title('Gráfico de Resíduos Padronizados') - ax1.set_xlabel('Valores Ajustados') - ax1.set_ylabel('Resíduos Padronizados') - ax1.grid(True) + dados_resp = f""" + Responsável Técnico: {nome} + Profissão: {prof} + Entidade de Classe: {ent} {uf} + Número do registro: {reg} + """ + ##### + introd = f""" + Logradouro e número: {lograd} + Município: {munic} + Tipo de imóvel: {tipo_imo} + Solicitante: {solic} + Finalidade: {finalidade} + Objetivo: {objetivo} + Pressupostos, Ressalvas e Fatores Limitantes: {press} + """ + ##### + regiao = f""" + Infraestrutura: {str(infra).replace("[", "").replace("]", "").replace("'", "")} + Serviços públicos: {str(serv).replace("[", "").replace("]", "").replace("'", "")} + Uso: {uso} + Padrão predominante na região: {pad_reg} + Tipo de via de acesso: {tipo_via} + Outras observações: {obs_gerais} + """ + ##### + diag = f""" + Performance: {per} + Nível de Ofertas do Segmento: {ofe} + Liquidez: {liq} + Outras informações: {dia} + """ + metodologia = f""" + Para a verificação do valor locativo mensal, foi utilizado o Método Comparativo de Dados de Mercado, conforme preconiza a NBR 14653-2:2011, Norma Brasileira de Avaliação de Bens- Imóveis Urbanos. Definido como aquele pelo qual o valor de um bem é determinado por comparação com outros de características semelhantes, através de tratamento técnico dos atributos dos elementos comparáveis, constituintes da amostra utilizada. + Os elementos amostrais tomados como referência, embora comparáveis ao imóvel avaliando, possuem características distintas devido à típica heterogeneidade do produto oferecido pelo mercado de imóveis. Torna-se imprescindível, então, a homogeneização dos dados amostrais. Entende-se por homogeneização o tratamento dispensado aos dados objetivando retirar as discrepâncias existentes entre as características de cada imóvel tomado como referência as do imóvel avaliando. A fim de que se alcance um grau maior de precisão nos trabalhos avaliatórios a NBR 14653-2:2011, Norma Brasileira de Avaliação de Bens - Imóveis Urbanos, recomenda que a homogeneização deve ser baseada em processos de inferência estatística, ao invés de utilizar fatores determinísticos e ponderações de ordem subjetiva, que implicam em uma sensível perda do nível de precisão dos trabalhos avaliatórios. +O mercado imobiliário não se vincula diretamente a índices econômicos e não segue um mesmo padrão em toda a cidade. Sendo assim, o comportamento das variáveis explicativas do valor apresenta oscilações diferenciadas em regiões distintas e em determinados intervalos de tempo, as quais podem contribuir de forma variada no preço final dos imóveis, de acordo com suas peculiaridades. Portanto, empregou-se a regressão múltipla para a homogeneização dos dados. Esta é a técnica adequada quando se deseja estudar o comportamento de uma variável, dita dependente, em relação a outras variáveis, ditas independentes, que são responsáveis por sua formação. - # Histograma dos resíduos padronizados - sns.histplot(erro_padronizado, kde=True, color='orange', alpha=0.6, ax=ax2) - ax2.set_title('Histograma dos Resíduos Padronizados') - ax2.set_xlabel('Resíduos Padronizados') - ax2.set_ylabel('Frequência') - ax2.grid(True) + """ + + ##### + assinatura = f""" + Data: {data_laudo} + {nome} | {prof} + {ent}-{uf} {reg} + """ - # Gráfico da distância de Cook - ax3.plot(distancia_cook, marker='o', linestyle='None', color='orange') - ax3.axhline(y=1, color='red', linestyle='--', linewidth=1) - ax3.set_title('Gráfico da Distância de Cook') - ax3.set_xlabel('Número da Observação') - ax3.set_ylabel('Distância de Cook') - ax3.grid(True) + # Gerando documento em word + doc = Document() + doc.add_heading('Relatório de Avaliação de Imóvel', level=1) + + sections = [ + (trabalho, "Trabalho Técnico"), + (dados_resp, "Informações do Responsável Técnico"), + (introd, "Introdução"), + (regiao, "Características da Região"), + (diag, "Diagnóstico de Mercado"), + (metodologia, "Metodologia"), + (resultados_gerais, "Resultados Gerais Modelo"), + ("", "Análise Gráfica"), + (assinatura, ""), + ] - # Gráfico Valores Ajustados vs Preços Observados - # Extrair os valores dos dados - x_values = df_correl_grafico['Preços Observados'] - y_values = df_correl_grafico['Valores Ajustados'] - # Calcular a linha de tendência (regressão linear) - slope, intercept = np.polyfit(x_values, y_values, 1) + for content, title in sections: + doc.add_heading(title, level=2) + if title == "Resultados Gerais do Modelo": + # Adiciona a tabela do DataFrame + table = doc.add_table(rows=1, cols=len(resultados_gerais.columns)) + hdr_cells = table.rows[0].cells + for i, column_name in enumerate(resultados_gerais.columns): + paragraph = hdr_cells[i].paragraphs[0] + run = paragraph.runs[0] if paragraph.runs else paragraph.add_run() + run.text = str(column_name) + run.font.size = Pt(12) # Tamanho da fonte para o cabeçalho da tabela + + for index, row in resultados_gerais.iterrows(): + row_cells = table.add_row().cells + for i, value in enumerate(row): + paragraph = row_cells[i].paragraphs[0] + run = paragraph.runs[0] if paragraph.runs else paragraph.add_run() + run.text = str(value) + run.font.size = Pt(10) # Define o tamanho da fonte para 8 para os dados da tabela + elif title == "Análise Gráfica": + # Adiciona os gráficos ao documento + doc.add_picture('residuos_padronizados.png', width=Inches(6)) + doc.add_picture('histograma_residuos_padronizados.png', width=Inches(6)) + doc.add_picture('distancia_cook.png', width=Inches(6)) + doc.add_picture('valores_ajustados_vs_observados.png', width=Inches(6)) + doc.add_picture('matriz_correlacao.png', width=Inches(6)) + else: + p = doc.add_paragraph() + run = p.add_run(content) + run.font.size = Pt(12) + if title == "": # Seção de assinatura + p.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT + else: + p.alignment = WD_PARAGRAPH_ALIGNMENT.LEFT - # Plotar o gráfico de dispersão no eixo ax4 - ax4.scatter(x_values, y_values, color='black') - # Plotar a linha de tendência no eixo ax4 - ax4.plot(x_values, slope * x_values + intercept, color='orange', linestyle='--', linewidth=2) - # Adicionar título e rótulos dos eixos em ax4 - ax4.set_title('Valores Ajustados vs Preços Observados') - ax4.set_xlabel('Preços Observados') - ax4.set_ylabel('Valores Ajustados') - ax4.grid(True) + doc.save('relatorio_avaliacao.doc') - # Criando o gráfico de influência das variáveis - feat_importances.nlargest(16).plot(kind='barh', color='orange', ax=ax5) - ax5.set_title('Influência das Variáveis') - ax5.set_xlabel('Importância') - ax5.set_ylabel('Variáveis') - ax5.grid(True) - # Ajustando a posição dos subplots - plt.tight_layout() - - # Exibindo os subplots - plt.show() - #----------------------------------------------Pontos Influenciantes-------------------------------------------------# - - # Listagem de pontos discrepantes - #limite_cook = 4 / (len(df_final) - len(resultado.params)) - #pontos_discrepantes = [] - #for i, cook_dist in enumerate(distancia_cook): - #if cook_dist > limite_cook: - #pontos_discrepantes.append(df_final.iloc[i, 0]) # Usando a primeira coluna como rótulo - # Listagem de pontos influentes - limite_cook = 1 - pontos_influentes = [] - for i, cook_dist in enumerate(distancia_cook): - if cook_dist > limite_cook: - pontos_influentes.append(df_final.iloc[i, 0]) # Usando a primeira coluna como rótulo - - # Transformando a lista em uma string separada por vírgula - string_pontos_influentes = ", ".join(map(str, pontos_influentes)) - - #---------------------------------------Outputs----------------------------------# + + # OUTPUTS + # -----------------------------------------------------------------------------------------------------------------# + # Comentário 23: + # 1) Ao lado de cada output consta a linha do código + # -----------------------------------------------------------------------------------------------------------------# return ( df_original, string_colunas, resultados_gerais, equacao_modelo, - resultado_html, - df_final, + resultados_vars, + df_final_2, Listagem_df_maiores_que_2, string_pontos_influentes, df_maiores_que_2, df_outliers, - df_correl, + df_limites_var_final, + 'residuos_padronizados.png', + 'histograma_residuos_padronizados.png', + 'distancia_cook.png', + 'valores_ajustados_vs_observados.png', + 'matriz_correlacao.png', + df_aval_original, + 'planilha_aval.xlsx', + output_file, fig_v1, fig_v2, fig_v3, @@ -811,350 +1422,204 @@ def gera_model(planilha, name_model, v_d, scv_d, fig_v14, fig_v15, fig_v16, - plt, - df_aval_original, - 'planilha_aval.xlsx', - output_file - - #X_aval, - #X, - #y, - #'X.xlsx', - #'y.xlsx', + trabalho, + dados_resp, + introd, + regiao, + diag, + metodologia, + 'relatorio_avaliacao.doc' ) -#-----------------------------------------FUNÇÃO PRINCIPAL DE CARREGAMENTO DE MODELOS-----------------------------------------# - -# função para a regressão linear -def carrega_model(planilha): - - #----------------------------Carregando modelo--------------------------------# - - df_model = pd.read_excel(planilha.name, 'Model') - - df_original = df_model.copy() - - y = df_model.iloc[:, 1:2] - - # Para converter os valores calculados posteriormente - cabecalho_lista = list(y.columns) - cabecalho_lista_transformado = ['lny' if 'ln(' in col else '1/y' if '1/(' in col else 'y²' if '(' in col and ')' in col and '²' in col else 'y' for col in cabecalho_lista] - scv_d = cabecalho_lista_transformado[0] - - X_model = df_model.drop(df_model.columns[[0, 1]], axis=1) - - # Inicializando o modelo de regressão linear - modelo = sm.OLS(y, X_model) - - # Ajustando o modelo aos dados - resultado = modelo.fit() - - # Calculando os resíduos do modelo - residuos = resultado.resid - # Calculando Desvio Padrão dos Resíduos - #desvio_padrao_residuos = round(np.std(resultado.resid), 8) - desvio_padrao_residuos = round(np.std(residuos), 8) - # Calculando Estatística F - estatistica_F = round(resultado.fvalue, 8) - # Obtendo Nível de Significância do Modelo - nivel_significancia = round(resultado.f_pvalue, 8) - # Calculando R² - r_squared = round(resultado.rsquared, 8) - # Calculando R² ajustado - r_squared_adjusted = round(resultado.rsquared_adj, 8) - # Obtendo Número de Observações - num_observacoes = int(round(resultado.nobs, 0)) - # Calculando Coeficiente de Correlação - coef_correlacao = round(np.sqrt(r_squared), 8) - # Calculando o teste de Jarque-Bera para os resíduos - jarque_bera_test, p_value, skewness, kurtosis = jarque_bera(residuos) - # Formatando os resultados com 4 casas decimais - jarque_bera_test = round(jarque_bera_test, 8) - p_value = round(p_value, 8) - skewness = round(skewness, 8) - kurtosis = round(kurtosis, 8) - # Extrair os coeficientes da regressão - coeficientes = resultado.params - # Calcular a distância de Cook - distancia_cook = resultado.get_influence().cooks_distance[0] - - # String com os resultados - resultados_gerais = f""" - Desvio Padrão: {desvio_padrao_residuos} - Estatística F: {estatistica_F} - Nível de Significância do Modelo: {nivel_significancia} - - R²: {r_squared} - R² ajustado: {r_squared_adjusted} - Correlação: {coef_correlacao} - Número de observações: {num_observacoes} - - Teste de Jarque-Bera: - - Estatística do teste: {jarque_bera_test} - - Valor-p: {p_value} - - Assimetria (Skewness): {skewness} - - Curtose (Kurtosis): {kurtosis} - """ - - #------------------Criando uma lista com as escalas das variáveis-----------------------# - - cabecalho_lista = list(X_model.columns) - cabecalho_lista_transformado = ['lnx' if 'ln(' in col else '1/x' if '1/(' in col else 'x²' if '(' in col and ')' in col and '²' in col else 'x' for col in cabecalho_lista] - const = cabecalho_lista_transformado[0] - v = cabecalho_lista_transformado[1:] # Exclui o primeiro elemento da lista - # Atribuindo os valores restantes a variáveis v_1, v_2, v_3, ... - for i, valor in enumerate(v, start=1): - globals()[f"scv_{i}"] = valor - # Imprimindo os valores armazenados - print("const:", const) - for i in range(1, len(v) + 1): - print(f"scv_{i}:", globals()[f"scv_{i}"]) - - #-------------------------------Carregando avaliando(s)----------------------------------# - - try: - # Carregando o(s) avaliando(s) - df_avalia = pd.read_excel(planilha.name, 'Avalia') - df_aval_original = df_avalia.copy() - - X_avalia = df_avalia.drop(df_avalia.columns[[0]], axis=1) - X_avalia.insert(0, 'const', 1) - - # Lista de scv's - scvs = [globals().get(f"scv_{i}") for i in range(1, 17)] - - # Aplicando a operação para cada scv - for i, scv in enumerate(scvs, start=1): - if scv is not None: - aplicar_operacao(X_avalia, scv, i) - - # Avaliando(s) - valores_previstos_aval = resultado.predict(X_avalia) - df_aval_original['VALOR'] = round(valores_previstos_aval, 8) - - if scv_d == 'lny': - df_aval_original['VALOR'] = round(np.exp(df_aval_original['VALOR']), 8) - elif scv_d == '1/y': - df_aval_original['VALOR'] = round(1 / df_aval_original['VALOR'], 8) - elif scv_d == 'y²': - df_aval_original['VALOR'] = round(np.sqrt(df_aval_original['VALOR']), 8) - else: - pass # Nenhuma transformação é necessária - - # Campo de arbítrio - df_aval_original['LI_CA'] = round((df_aval_original['VALOR']*0.85), 2) - df_aval_original['LS_CA'] = round((df_aval_original['VALOR']*1.15), 2) - - # Intervalo de Confiança de 80% - # Calcular os intervalos de confiança para a média prevista - intervalo_confianca = resultado.get_prediction(X_avalia).summary_frame(alpha=0.2) - # Extrair os limites inferior e superior do intervalo de confiança - limite_inferior = intervalo_confianca['mean_ci_lower'] - limite_superior = intervalo_confianca['mean_ci_upper'] - # Adicionar as colunas ao DataFrame df_aval_original - df_aval_original['LI_IC'] = limite_inferior.values - df_aval_original['LS_IC'] = limite_superior.values - - if scv_d == 'lny': - df_aval_original['LI_IC'] = round(np.exp(df_aval_original['LI_IC']), 2) - df_aval_original['LS_IC'] = round(np.exp(df_aval_original['LS_IC']), 2) - elif scv_d == '1/y': - f_aval_original['LI_IC'] = round(1 / df_aval_original['LI_IC'], 2) - df_aval_original['LS_IC'] = round(1 / df_aval_original['LS_IC'], 2) - elif scv_d == 'y²': - df_aval_original['LI_IC'] = round(np.sqrt(df_aval_original['LI_IC']), 2) - df_aval_original['LS_IC'] = round(np.sqrt(df_aval_original['LS_IC']), 2) - else: - pass # Nenhuma transformação é necessária - - df_aval_original['LI_IC_%'] = round(((df_aval_original['VALOR']-df_aval_original['LI_IC'])/df_aval_original['VALOR'])*100, 2) - df_aval_original['LS_IC_%'] = round(((df_aval_original['LS_IC']-df_aval_original['VALOR'])/df_aval_original['VALOR'])*100, 2) - df_aval_original['TOTAL_IC_%'] = round(df_aval_original['LI_IC_%'] + df_aval_original['LS_IC_%'], 2) - - # Aplicação das condições para determinar 'PRECISÃO' - df_aval_original['PRECISÃO'] = "" # Inicializa a coluna 'PRECISÃO' - df_aval_original.loc[df_aval_original['TOTAL_IC_%'] <= 30, 'PRECISÃO'] = "Grau III" - df_aval_original.loc[(df_aval_original['TOTAL_IC_%'] > 30) & (df_aval_original['TOTAL_IC_%'] <= 40), 'PRECISÃO'] = "Grau II" - df_aval_original.loc[(df_aval_original['TOTAL_IC_%'] > 40) & (df_aval_original['TOTAL_IC_%'] <= 50), 'PRECISÃO'] = "Grau I" - df_aval_original.loc[df_aval_original['TOTAL_IC_%'] > 50, 'PRECISÃO'] = "Fora dos critérios" - - # Retirando as colunas valor total e valor unitário - df_aval_original = df_aval_original.drop(df_aval_original.columns[[1, 2]], axis=1) - # Salve o DataFrame 'result' em uma planilha - df_aval_original.to_excel("planilha_aval.xlsx", index=False) - - except: - # Se a aba não existir, crie um DataFrame vazio - df_aval_original = pd.DataFrame() - - # Salve o DataFrame em uma planilha - df_aval_original.to_excel("planilha_aval.xlsx", index=False) - - #----------------------------------------Outpus------------------------------------------# - - return ( - df_original, - #y, - #X_model, - resultados_gerais, - #X_avalia, - df_aval_original, - 'planilha_aval.xlsx' - ) + # -------------------------------------- # + +lista_finalidades = ["-", + "ADJUDICAÇÃO COMPULSÓRIA", "ALUGUEL", "AQUISIÇÃO", "CAUÇÃO", "CEDÊNCIA", "DAÇÃO EM PAGAMENTO", + "DEC_PROJ DE LEI", "DECLARATÓRIA", "DESAPROPRIAÇÃO PARCIAL", "DESAPROPRIAÇÃO TOTAL", "DOAÇÃO", + "EMBARGOS À ARREMATAÇÃO", "EMBARGOS A EXECUÇÃO FISCAL", "EQUIVALÊNCIA", "EXECUÇÃO FISCAL", + "FUTURA LICITAÇÃO", "GARANTIA", "INDENIZAÇÃO", "IPTU", "MULTA IMÓVEL INVENTARIADO", "PERMUTA", + "PROJETO ESPECIAL", "PRÓPRIO MUNICIPAL", "PRÓPRIO MUNICIPAL - ALIENAÇÃO", + "PRÓPRIO MUNICIPAL - CONCESSÃO DE USO", "PRÓPRIO MUNICIPAL - PERMISSÃO DE USO", "RECOMPRA", + "RECURSO ITBI", "REGULARIZAÇÃO", "REINTEGRAÇÃO DE POSSE", "SOLO CRIADO", "TAXA DE OCUPAÇÃO", + "USUCAPIÃO" +] + +lista_imo = ["-", + "Apartamento", "Apartamento de cobertura", "Apartamento garden", "Armazém", "Bangalô", + "Barracão", "Box/Garagem", "Casa", "Casa comercial", "Casa em condomínio", + "Centro de distribuição", "Chácara", "Cobertura duplex", "Cobertura triplex", + "Condomínio de apartamentos", "Condomínio de casas", "Condomínio fechado", "Conjunto comercial", + "Duplex", "Edifício residencial", "Estúdio", "Fazenda", "Flat", "Galpão", "Gleba", "Hotel", + "Imóvel rural", "Imóvel urbano", "Kitnet", "Loft", "Loft duplex", "Loja", "Lote", "Motel", + "Ponto comercial", "Pousada/Chalé", "Prédio comercial", "Quarto", "Sala comercial", "Sobrado", + "Studio", "Sítio", "Terreno", "Terreno em condomínio", "Triplex", "Vila residencial", + "Outro" +] #----------------------------------------------------------INTERFACES----------------------------------------------------------# with gr.Blocks(theme=gr.themes.Monochrome(primary_hue="yellow", secondary_hue="yellow",)) as interface: gr.Markdown(f""" -
- aval - ia - .se -
Aplicativo MCDDM com tratamento científico / Você pode fazer um download de uma planilha de exemplo aqui+ aval + ia + .se +
+Faça o download de uma planilha de exemplo aqui