|
|
import gradio as gr |
|
|
import pandas as pd |
|
|
import numpy as np |
|
|
import statsmodels.api as sm |
|
|
import matplotlib.pyplot as plt |
|
|
import seaborn as sns |
|
|
import plotly.graph_objects as go |
|
|
import plotly.express as px |
|
|
import scipy.stats as stats |
|
|
from joblib import dump |
|
|
import joblib |
|
|
import os |
|
|
import locale |
|
|
from io import BytesIO |
|
|
|
|
|
try: |
|
|
locale.setlocale(locale.LC_ALL, 'pt_BR.UTF-8') |
|
|
except locale.Error: |
|
|
|
|
|
locale.setlocale(locale.LC_ALL, 'C') |
|
|
|
|
|
|
|
|
def carregar_planilha(file): |
|
|
try: |
|
|
|
|
|
df = pd.read_excel(file.name) |
|
|
|
|
|
|
|
|
for col in df.columns: |
|
|
df[col] = pd.to_numeric(df[col], errors='coerce') |
|
|
|
|
|
|
|
|
df.fillna(0, inplace=True) |
|
|
|
|
|
|
|
|
df.columns = [str(col) for col in df.columns] |
|
|
|
|
|
|
|
|
df.insert(0, "Dado", range(1, len(df) + 1)) |
|
|
|
|
|
|
|
|
for col in df.select_dtypes(include=[float]).columns: |
|
|
df[col] = df[col].round(4) |
|
|
|
|
|
cabecalhos = list(df.columns) |
|
|
return cabecalhos, df |
|
|
except Exception as e: |
|
|
print(f"Erro ao carregar a planilha: {e}") |
|
|
return [], pd.DataFrame() |
|
|
|
|
|
|
|
|
def aplicar_transformacao(df, coluna, transformacao): |
|
|
try: |
|
|
if transformacao == "1/x": |
|
|
return 1 / df[coluna].replace(0, np.nan).fillna(0) |
|
|
elif transformacao == "ln(x)": |
|
|
return np.log(df[coluna].replace(0, np.nan).fillna(0)) |
|
|
elif transformacao == "x²": |
|
|
return df[coluna] ** 2 |
|
|
elif transformacao == "exp(x)": |
|
|
return np.exp(df[coluna]) |
|
|
else: |
|
|
return df[coluna] |
|
|
except Exception as e: |
|
|
return df[coluna] |
|
|
|
|
|
|
|
|
def grafico_dispersao(df, y_coluna, transformacao_y, x_coluna, transformacao_x, dados_out): |
|
|
if df.empty or x_coluna not in df.columns or y_coluna not in df.columns: |
|
|
return None |
|
|
|
|
|
|
|
|
df_grafico = df.copy() |
|
|
|
|
|
|
|
|
if dados_out is None: |
|
|
dados_out = "" |
|
|
|
|
|
dados_out = [int(num.strip()) for num in dados_out.split(",") if num.strip()] |
|
|
|
|
|
df_grafico = df_grafico[~df_grafico["Dado"].isin(dados_out)] |
|
|
|
|
|
x = aplicar_transformacao(df_grafico, x_coluna, transformacao_x) |
|
|
y = aplicar_transformacao(df_grafico, y_coluna, transformacao_y) |
|
|
|
|
|
coef = np.polyfit(x, y, 1) |
|
|
linha_tendencia = np.poly1d(coef) |
|
|
y_tendencia = linha_tendencia(x) |
|
|
|
|
|
residuos = np.abs(y - y_tendencia) |
|
|
|
|
|
residuos_norm = (residuos - residuos.min()) / (residuos.max() - residuos.min()) |
|
|
|
|
|
correlacao = np.corrcoef(x, y)[0, 1] |
|
|
|
|
|
fig = go.Figure() |
|
|
|
|
|
fig.add_trace(go.Scatter( |
|
|
x=x, |
|
|
y=y, |
|
|
mode='markers', |
|
|
marker=dict( |
|
|
size=8, |
|
|
color=residuos_norm, |
|
|
colorscale='Spectral', |
|
|
showscale=False, |
|
|
), |
|
|
text=[f"Índice: {idx}<br>{x_coluna}: {x_val:.2f}<br>{y_coluna}: {y_val:.2f}<br>Resíduo: {resid:.2f}" |
|
|
for idx, x_val, y_val, resid in zip(df_grafico["Dado"], x, y, residuos)], |
|
|
hoverinfo="text" |
|
|
)) |
|
|
|
|
|
|
|
|
fig.add_trace(go.Scatter( |
|
|
x=x, |
|
|
y=y_tendencia, |
|
|
mode='lines', |
|
|
line=dict(color='darkred', width=2), |
|
|
)) |
|
|
|
|
|
|
|
|
fig.update_layout( |
|
|
title=f"Gráfico de Dispersão: {x_coluna} vs {y_coluna}<br>Correlação: {correlacao:.2f}", |
|
|
xaxis_title=f"{x_coluna} ({transformacao_x})", |
|
|
yaxis_title=f"{y_coluna} ({transformacao_y})", |
|
|
template="plotly_white", |
|
|
showlegend=False |
|
|
) |
|
|
|
|
|
return fig |
|
|
|
|
|
|
|
|
def grafico_boxplot(df, y_coluna, transformacao_y, x_coluna, transformacao_x, dados_out): |
|
|
if df.empty or y_coluna not in df.columns: |
|
|
return None |
|
|
|
|
|
|
|
|
df_boxplot = df.copy() |
|
|
|
|
|
|
|
|
|
|
|
if dados_out is None: |
|
|
dados_out = "" |
|
|
dados_out = [int(num.strip()) for num in dados_out.split(",") if num.strip()] |
|
|
|
|
|
df_boxplot = df_boxplot[~df_boxplot["Dado"].isin(dados_out)] |
|
|
|
|
|
|
|
|
y = aplicar_transformacao(df_boxplot, y_coluna, transformacao_y) |
|
|
|
|
|
|
|
|
hover_text = [ |
|
|
f"Índice: {idx}<br>{y_coluna}: {y_val:.2f}" |
|
|
for idx, y_val in zip(df_boxplot["Dado"], y) |
|
|
] |
|
|
|
|
|
|
|
|
fig = go.Figure() |
|
|
|
|
|
|
|
|
fig.add_trace(go.Box( |
|
|
y=y, |
|
|
name=y_coluna, |
|
|
boxpoints='all', |
|
|
jitter=0.8, |
|
|
pointpos=-1.8, |
|
|
marker=dict( |
|
|
color='orange', |
|
|
size=8 |
|
|
), |
|
|
line=dict(color='gray'), |
|
|
hovertemplate="%{text}", |
|
|
text=hover_text |
|
|
)) |
|
|
|
|
|
|
|
|
fig.update_layout( |
|
|
title=f"Boxplot da Coluna: {y_coluna} ({transformacao_y})", |
|
|
yaxis_title=f"{y_coluna} ({transformacao_y})", |
|
|
template="plotly_white", |
|
|
showlegend=False |
|
|
) |
|
|
|
|
|
return fig |
|
|
|
|
|
|
|
|
def atualizar_dropdowns(cabeçalhos): |
|
|
if cabeçalhos: |
|
|
|
|
|
cabecalhos_sem_indice = [col for col in cabeçalhos if col != "Dado"] |
|
|
dropdown_update_x = gr.update(choices=cabecalhos_sem_indice, value=cabecalhos_sem_indice) |
|
|
dropdown_update = gr.update(choices=cabecalhos_sem_indice, value=[]) |
|
|
return [dropdown_update_x] + [dropdown_update] * 4 + [dropdown_update] |
|
|
else: |
|
|
dropdown_reset = gr.update(choices=[], value=[]) |
|
|
return [dropdown_reset] * 5 + [dropdown_reset] |
|
|
|
|
|
|
|
|
def criar_dataframe_cabecalhos(cabecalhos, x, ln_x, exp_x, inv_x, quad_x, dados, dados_out, var_dep): |
|
|
if dados.empty: |
|
|
return pd.DataFrame(), {} |
|
|
|
|
|
|
|
|
if dados_out: |
|
|
dados_out = [int(num.strip()) for num in dados_out.split(",") if num.strip()] |
|
|
dados = dados[~dados["Dado"].isin(dados_out)] |
|
|
|
|
|
|
|
|
escalas = { |
|
|
col: [escala] for col, escala in zip( |
|
|
x + ln_x + exp_x + inv_x + quad_x, |
|
|
["(x)"] * len(x) + ["ln(x)"] * len(ln_x) + ["exp(x)"] * len(exp_x) |
|
|
+ ["1/(x)"] * len(inv_x) + ["(x)²"] * len(quad_x) |
|
|
) |
|
|
} |
|
|
|
|
|
|
|
|
df = pd.DataFrame.from_dict(escalas, orient='index', columns=['Escala']).transpose() |
|
|
|
|
|
|
|
|
if var_dep in df.columns: |
|
|
cols = [var_dep] + [col for col in df.columns if col != var_dep] |
|
|
df = df[cols] |
|
|
|
|
|
|
|
|
limites = { |
|
|
"Máximo": dados.max().round(2), |
|
|
"Mínimo": dados.min().round(2), |
|
|
"Média": dados.mean().round(2) |
|
|
} |
|
|
|
|
|
|
|
|
for label, valores in limites.items(): |
|
|
linha = {col: valores[col] if col in valores else '' for col in df.columns} |
|
|
df = pd.concat([df, pd.DataFrame([linha], index=[label])]) |
|
|
|
|
|
return df, escalas |
|
|
|
|
|
|
|
|
def criar_dataframes(dados, x, ln_x, exp_x, inv_x, quad_x, dados_out, var_dep): |
|
|
if dados.empty: |
|
|
return pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), None |
|
|
|
|
|
|
|
|
if dados_out is None: |
|
|
dados_out = "" |
|
|
|
|
|
colunas_escolhidas = x + ln_x + exp_x + inv_x + quad_x |
|
|
df_original = dados[["Dado"] + colunas_escolhidas] |
|
|
|
|
|
|
|
|
df_escalado = pd.DataFrame() |
|
|
df_escalado["Dado"] = dados["Dado"] |
|
|
|
|
|
for col in x: |
|
|
df_escalado[col] = dados[col] |
|
|
for col in ln_x: |
|
|
df_escalado[col] = np.log(dados[col].replace(0, np.nan)).fillna(0) |
|
|
for col in exp_x: |
|
|
df_escalado[col] = np.exp(dados[col]) |
|
|
for col in inv_x: |
|
|
df_escalado[col] = 1 / dados[col].replace(0, np.nan).fillna(0) |
|
|
for col in quad_x: |
|
|
df_escalado[col] = dados[col] ** 2 |
|
|
|
|
|
|
|
|
if var_dep in df_original.columns: |
|
|
colunas_reorganizadas_original = ( |
|
|
["Dado", var_dep] + [col for col in df_original.columns if col not in ["Dado", var_dep]] |
|
|
) |
|
|
df_original = df_original[colunas_reorganizadas_original] |
|
|
|
|
|
if var_dep in df_escalado.columns: |
|
|
colunas_reorganizadas_escalado = ( |
|
|
["Dado", var_dep] + [col for col in df_escalado.columns if col not in ["Dado", var_dep]] |
|
|
) |
|
|
df_escalado = df_escalado[colunas_reorganizadas_escalado] |
|
|
|
|
|
|
|
|
df_variaveis = pd.DataFrame({'variáveis': df_original.columns}) |
|
|
df_variaveis.reset_index(drop=True, inplace=True) |
|
|
|
|
|
|
|
|
if not dados_out.strip(): |
|
|
df_outliers = pd.DataFrame() |
|
|
else: |
|
|
|
|
|
dados_out = [int(num.strip()) for num in dados_out.split(",") if num.strip()] |
|
|
|
|
|
df_outliers = df_original[df_original["Dado"].isin(dados_out)] |
|
|
|
|
|
df_original = df_original[~df_original["Dado"].isin(dados_out)] |
|
|
df_escalado = df_escalado[~df_escalado["Dado"].isin(dados_out)] |
|
|
|
|
|
|
|
|
correlation_matrix = df_escalado.drop(columns=["Dado"]).corr().round(2) |
|
|
|
|
|
return df_original, df_escalado, df_outliers |
|
|
|
|
|
|
|
|
def realizar_regressao(var_dep, dados_transformados, df_original, escalas): |
|
|
if isinstance(dados_transformados, pd.DataFrame) and not dados_transformados.empty: |
|
|
try: |
|
|
import statsmodels.api as sm |
|
|
import numpy as np |
|
|
|
|
|
if var_dep in dados_transformados.columns: |
|
|
|
|
|
y = dados_transformados[var_dep] |
|
|
X = dados_transformados.drop(columns=[var_dep, "Dado"]) |
|
|
|
|
|
|
|
|
num_variaveis = X.shape[1] |
|
|
|
|
|
|
|
|
X = sm.add_constant(X) |
|
|
|
|
|
|
|
|
modelo = sm.OLS(y, X).fit() |
|
|
|
|
|
|
|
|
resultados_gerais = "" |
|
|
|
|
|
|
|
|
residuos = modelo.resid |
|
|
desvio_padrao_residuos = round(np.std(residuos), 8) |
|
|
erro_padronizado = np.round(residuos / desvio_padrao_residuos, 8) |
|
|
estatistica_F = round(modelo.fvalue, 8) |
|
|
nivel_significancia = round(modelo.f_pvalue, 8) |
|
|
r_squared = round(modelo.rsquared, 8) |
|
|
r_squared_adjusted = round(modelo.rsquared_adj, 8) |
|
|
num_observacoes = int(round(modelo.nobs, 0)) |
|
|
coef_correlacao = round(np.sqrt(r_squared), 8) |
|
|
|
|
|
|
|
|
intervalos = [(-1.00, 1.00), (-1.64, 1.64), (-1.96, 1.96)] |
|
|
percentuais = [] |
|
|
for intervalo in intervalos: |
|
|
min_intervalo, max_intervalo = intervalo |
|
|
count = np.sum((erro_padronizado >= min_intervalo) & (erro_padronizado <= max_intervalo)) |
|
|
percentual = round(count / len(erro_padronizado) * 100, 0) |
|
|
percentuais.append(f"{percentual:.0f}%") |
|
|
perc_resid = ", ".join(percentuais) |
|
|
|
|
|
|
|
|
ks_test = sm.stats.diagnostic.kstest_normal(residuos) |
|
|
ks_test_formatted = tuple(f"{val:.4f}" for val in ks_test) |
|
|
|
|
|
import statsmodels.api as sm |
|
|
|
|
|
|
|
|
ks_test = sm.stats.diagnostic.kstest_normal(residuos) |
|
|
ks_test_formatted = tuple(f"{val:.4f}" for val in ks_test) |
|
|
|
|
|
|
|
|
estatistica_ks, p_valor_ks = ks_test |
|
|
|
|
|
if p_valor_ks > 0.05: |
|
|
ks_interpretacao = "Não há evidências estatísticas suficientes para rejeitar a hipótese nula. Os resíduos podem seguir uma distribuição normal." |
|
|
else: |
|
|
ks_interpretacao = "Rejeitamos a hipótese nula. Há evidências estatísticas de que os resíduos não seguem uma distribuição normal." |
|
|
|
|
|
|
|
|
|
|
|
influencia = modelo.get_influence() |
|
|
distancia_cook = influencia.cooks_distance[0] |
|
|
|
|
|
|
|
|
coeficientes = modelo.params |
|
|
erros_padrao = modelo.bse |
|
|
t_values = modelo.tvalues |
|
|
p_values = modelo.pvalues |
|
|
|
|
|
|
|
|
escalas_coluna = [escalas[var][0] if var in escalas else "Nenhuma" for var in coeficientes.index] |
|
|
|
|
|
resultados_vars = pd.DataFrame({ |
|
|
"Variável": coeficientes.index, |
|
|
"Escala": escalas_coluna, |
|
|
"Coeficiente": coeficientes.values.round(4), |
|
|
"Erro Padrão": erros_padrao.values.round(4), |
|
|
"t-valor": t_values.values.round(4), |
|
|
"P>|t|": p_values.values.round(4) |
|
|
}) |
|
|
|
|
|
|
|
|
if var_dep in escalas: |
|
|
escala_y = escalas[var_dep][0] |
|
|
if escala_y == "ln(x)": |
|
|
y_label_transformada = f"ln({var_dep})" |
|
|
ajustar_termo = lambda termo: f"exp({termo})" |
|
|
elif escala_y == "1/(x)": |
|
|
y_label_transformada = f"1/({var_dep})" |
|
|
ajustar_termo = lambda termo: f"1/({termo})" |
|
|
elif escala_y == "(x)²": |
|
|
y_label_transformada = f"({var_dep})²" |
|
|
ajustar_termo = lambda termo: f"sqrt({termo})" |
|
|
elif escala_y == "exp(x)": |
|
|
y_label_transformada = f"exp({var_dep})" |
|
|
ajustar_termo = lambda termo: f"ln({termo})" |
|
|
else: |
|
|
y_label_transformada = var_dep |
|
|
ajustar_termo = lambda termo: termo |
|
|
else: |
|
|
y_label_transformada = var_dep |
|
|
ajustar_termo = lambda termo: termo |
|
|
|
|
|
|
|
|
termos = [] |
|
|
for var, coef in zip(coeficientes.index, coeficientes.values): |
|
|
if var == 'const': |
|
|
interseção = f"{coef:.4f}" |
|
|
else: |
|
|
if var in escalas: |
|
|
escala_var = escalas[var][0] |
|
|
if escala_var == "ln(x)": |
|
|
var_label = f"ln({var})" |
|
|
elif escala_var == "1/(x)": |
|
|
var_label = f"1/({var})" |
|
|
elif escala_var == "(x)²": |
|
|
var_label = f"({var})²" |
|
|
elif escala_var == "exp(x)": |
|
|
var_label = f"exp({var})" |
|
|
else: |
|
|
var_label = var |
|
|
else: |
|
|
var_label = var |
|
|
termos.append(f"{coef:.4f} * {var_label}") |
|
|
|
|
|
|
|
|
lado_direito = interseção + " + " + " + ".join(termos) |
|
|
equacao_transformada = f"{y_label_transformada} = {lado_direito}" |
|
|
|
|
|
equacao_revertida = f"{var_dep} = {ajustar_termo(lado_direito)}" |
|
|
|
|
|
equacao_transformada = equacao_transformada.replace('.', ',') |
|
|
equacao_revertida = equacao_revertida.replace('.', ',') |
|
|
|
|
|
|
|
|
resultados_gerais += f"\nEquação do modelo (variável dependente na escala direta): {equacao_revertida}" |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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']) |
|
|
|
|
|
|
|
|
|
|
|
if num_observacoes >= 6 * (num_variaveis + 1): |
|
|
tab2 = "Grau III" |
|
|
elif num_observacoes >= 4 * (num_variaveis + 1): |
|
|
tab2 = "Grau II" |
|
|
elif num_observacoes >= 3 * (num_variaveis + 1): |
|
|
tab2 = "Grau I" |
|
|
else: |
|
|
tab2 = "Fora dos critérios" |
|
|
|
|
|
|
|
|
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" |
|
|
|
|
|
|
|
|
resultados_gerais = f""" |
|
|
Desvio Padrão dos Resíduos: {desvio_padrao_residuos} |
|
|
Estatística F: {estatistica_F} | Nível de Significância: {nivel_significancia} |
|
|
R²: {r_squared} | R² Ajustado: {r_squared_adjusted} |
|
|
Correlação: {coef_correlacao} |
|
|
Número de Observações: {num_observacoes} |
|
|
Número de Variáveis Independentes: {num_variaveis} |
|
|
|
|
|
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} |
|
|
|
|
|
Testes de normalidade: |
|
|
1) Comparação (curva normal) - Percentuais atingidos: {perc_resid} |
|
|
Ideal 68% - aceitável de 64% a 75% |
|
|
Ideal 90% - aceitável de 88% a 95% |
|
|
Ideal 95% - aceitável de 95% a 100% |
|
|
|
|
|
Teste Kolmogorov-Smirnov: Estatística = {ks_test_formatted[0]}, Valor-p = {ks_test_formatted[1]} - ({ks_interpretacao}) |
|
|
|
|
|
Distância de Cook (Máxima): {np.max(distancia_cook):.8f} |
|
|
|
|
|
Equação do modelo: {equacao_revertida} |
|
|
""" |
|
|
|
|
|
|
|
|
df_original_res = df_original.copy() |
|
|
df_original_res['Erro Padronizado'] = erro_padronizado |
|
|
|
|
|
|
|
|
df_grandes_residuos = df_original_res[abs(df_original_res['Erro Padronizado']) > 2].copy() |
|
|
df_grandes_residuos['Erro Abs'] = abs(df_grandes_residuos['Erro Padronizado']) |
|
|
|
|
|
|
|
|
listagem_grandes_residuos = ", ".join(map(str, df_grandes_residuos.iloc[:, 0].tolist())) |
|
|
|
|
|
|
|
|
limite_cook = 1 |
|
|
pontos_influentes = [] |
|
|
for i, cook_dist in enumerate(distancia_cook): |
|
|
if cook_dist > limite_cook: |
|
|
pontos_influentes.append(dados_transformados.iloc[i]["Dado"]) |
|
|
|
|
|
|
|
|
listagem_pontos_influentes = ", ".join(map(str, pontos_influentes)) |
|
|
|
|
|
|
|
|
valores_previstos = modelo.predict(X) |
|
|
valores_previstos_trans = valores_previstos.copy() |
|
|
|
|
|
if var_dep in escalas: |
|
|
escala_var_dep = escalas[var_dep][0] |
|
|
|
|
|
if escala_var_dep == "ln(x)": |
|
|
valores_previstos = np.exp(valores_previstos) |
|
|
elif escala_var_dep == "1/(x)": |
|
|
valores_previstos = 1 / valores_previstos |
|
|
elif escala_var_dep == "(x)²": |
|
|
valores_previstos = np.sqrt(valores_previstos) |
|
|
elif escala_var_dep == "exp(x)": |
|
|
valores_previstos = np.log(valores_previstos) |
|
|
|
|
|
|
|
|
|
|
|
df_calc_obs = df_original.copy() |
|
|
df_calc_obs['Valores Ajustados'] = round(valores_previstos, 8) |
|
|
|
|
|
df_calc_obs['Resíduo'] = (df_calc_obs[var_dep].replace(0, np.nan) - df_calc_obs['Valores Ajustados']).round(4) |
|
|
|
|
|
df_calc_obs['Erro Padronizado'] = erro_padronizado.round(4) |
|
|
|
|
|
|
|
|
df_calc_obs['Erro'] = df_calc_obs['Valores Ajustados'] / df_calc_obs[var_dep].replace(0, np.nan) |
|
|
|
|
|
df_calc_obs['Erro'] = df_calc_obs['Erro'].round(4) |
|
|
|
|
|
df_calc_obs['Erro Percentual (%)'] = (abs(df_calc_obs['Erro'] - 1) * 100).round(4) |
|
|
|
|
|
|
|
|
df_calc_obs_trans = dados_transformados.copy() |
|
|
df_calc_obs_trans['Valores Ajustados'] = round(valores_previstos_trans, 8) |
|
|
|
|
|
return resultados_gerais, resultados_vars, df_grandes_residuos, listagem_grandes_residuos, listagem_pontos_influentes, df_calc_obs, df_calc_obs_trans, erro_padronizado, modelo |
|
|
else: |
|
|
return "Erro: A variável dependente não está nos dados transformados.", pd.DataFrame(), pd.DataFrame(), "Erro", "Erro", pd.DataFrame(), pd.DataFrame(), [], None |
|
|
except Exception as e: |
|
|
return f"Erro na regressão: {str(e)}", pd.DataFrame(), pd.DataFrame(), "Erro", "Erro", pd.DataFrame(), pd.DataFrame(), [], None |
|
|
else: |
|
|
return "Erro: Dados transformados inválidos ou vazios.", pd.DataFrame(), pd.DataFrame(), "Erro", "Erro", pd.DataFrame(), pd.DataFrame(), [], None |
|
|
|
|
|
|
|
|
def graficos(escala_dependente, df_calc_obs, df_calc_obs_trans, erro_padronizado, var_dep, num_bins=20): |
|
|
|
|
|
|
|
|
|
|
|
residuos_norm = (np.abs(erro_padronizado) - np.abs(erro_padronizado).min()) / \ |
|
|
(np.abs(erro_padronizado).max() - np.abs(erro_padronizado).min()) |
|
|
|
|
|
fig1 = go.Figure() |
|
|
fig1.add_trace(go.Scatter( |
|
|
x=df_calc_obs_trans['Valores Ajustados'], |
|
|
y=erro_padronizado, |
|
|
mode='markers', |
|
|
marker=dict( |
|
|
size=8, |
|
|
color=residuos_norm, |
|
|
colorscale='Spectral', |
|
|
), |
|
|
text=df_calc_obs_trans.iloc[:, 0], |
|
|
hovertemplate="<b>Índice: %{text}</b><br>Valores Ajustados: %{x:.2f}<br>Resíduos: %{y:.2f}<extra></extra>" |
|
|
)) |
|
|
fig1.add_hline(y=0, line_dash="dash", line_color="black") |
|
|
fig1.add_hline(y=2, line_dash="dot", line_color="red") |
|
|
fig1.add_hline(y=-2, line_dash="dot", line_color="red") |
|
|
fig1.update_layout( |
|
|
title="Gráfico de Resíduos Padronizados", |
|
|
xaxis_title="Valores Ajustados", |
|
|
yaxis_title="Resíduos Padronizados", |
|
|
template="plotly_white" |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
mean_residuos = np.mean(erro_padronizado) |
|
|
std_residuos = np.std(erro_padronizado) |
|
|
|
|
|
|
|
|
x_vals = np.linspace(mean_residuos - 4 * std_residuos, mean_residuos + 4 * std_residuos, 500) |
|
|
y_vals = stats.norm.pdf(x_vals, mean_residuos, std_residuos) |
|
|
|
|
|
|
|
|
hist_values, bin_edges = np.histogram(erro_padronizado, bins=num_bins, density=True) |
|
|
scale_factor = max(hist_values) / max(y_vals) |
|
|
y_vals_scaled = y_vals * scale_factor |
|
|
|
|
|
|
|
|
bin_centers = bin_edges[:-1] + np.diff(bin_edges) / 2 |
|
|
bin_colors = 1 - (np.abs(bin_centers) - np.abs(bin_centers).min()) / (np.abs(bin_centers).max() - np.abs(bin_centers).min()) |
|
|
|
|
|
fig2 = go.Figure() |
|
|
fig2.add_trace(go.Bar( |
|
|
x=bin_centers, |
|
|
y=hist_values, |
|
|
width=np.diff(bin_edges), |
|
|
marker=dict( |
|
|
color=bin_colors, |
|
|
colorscale='Reds', |
|
|
), |
|
|
opacity=0.7, |
|
|
name='Histograma' |
|
|
)) |
|
|
|
|
|
|
|
|
fig2.add_trace(go.Scatter( |
|
|
x=x_vals, |
|
|
y=y_vals_scaled, |
|
|
mode='lines', |
|
|
line=dict(color='red', width=2), |
|
|
name='Curva Normal' |
|
|
)) |
|
|
|
|
|
fig2.update_layout( |
|
|
title="Histograma dos Resíduos Padronizados com Curva Normal", |
|
|
xaxis_title="Resíduos Padronizados", |
|
|
yaxis_title="Frequência Normalizada", |
|
|
template="plotly_white", |
|
|
) |
|
|
|
|
|
|
|
|
if escala_dependente == "Direta": |
|
|
df_graf_ao = df_calc_obs |
|
|
else: |
|
|
df_graf_ao = df_calc_obs_trans |
|
|
|
|
|
|
|
|
valores_observados = df_graf_ao.iloc[:, 1] |
|
|
valores_calculados = df_graf_ao['Valores Ajustados'] |
|
|
|
|
|
|
|
|
residuos = np.abs(valores_observados - valores_calculados) |
|
|
residuos_norm = (residuos - residuos.min()) / (residuos.max() - residuos.min()) |
|
|
|
|
|
|
|
|
X = sm.add_constant(valores_observados) |
|
|
modelo = sm.OLS(valores_calculados, X).fit() |
|
|
x_reta = np.linspace(valores_observados.min(), valores_observados.max(), 100) |
|
|
y_reta = modelo.predict(sm.add_constant(x_reta)) |
|
|
|
|
|
|
|
|
fig3 = go.Figure() |
|
|
fig3.add_trace(go.Scatter( |
|
|
x=valores_observados, |
|
|
y=valores_calculados, |
|
|
mode='markers', |
|
|
marker=dict( |
|
|
size=8, |
|
|
color=residuos_norm, |
|
|
colorscale='Spectral', |
|
|
showscale=False |
|
|
), |
|
|
text=df_graf_ao.iloc[:, 0], |
|
|
hovertemplate="<b>Índice: %{text}</b><br>Observado: %{x:.2f}<br>Ajustado: %{y:.2f}<extra></extra>", |
|
|
showlegend=False |
|
|
)) |
|
|
|
|
|
|
|
|
fig3.add_trace(go.Scatter( |
|
|
x=x_reta, |
|
|
y=y_reta, |
|
|
mode="lines", |
|
|
line=dict(color="green", dash="solid"), |
|
|
name="Reta Ajustada" |
|
|
)) |
|
|
|
|
|
|
|
|
fig3.update_layout( |
|
|
title="Valores Ajustados vs Preços Observados", |
|
|
xaxis_title="Preços Observados", |
|
|
yaxis_title="Valores Ajustados", |
|
|
template="plotly_white", |
|
|
showlegend=False |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
corr_matrix = df_calc_obs_trans.drop(columns=["Dado", "Valores Ajustados"], errors='ignore').corr() |
|
|
|
|
|
|
|
|
fig4 = go.Figure() |
|
|
|
|
|
|
|
|
for i, row in enumerate(corr_matrix.index): |
|
|
for j, col in enumerate(corr_matrix.columns): |
|
|
|
|
|
if row == col: |
|
|
color = "black" |
|
|
elif corr_matrix.loc[row, col] > 0.8: |
|
|
if row == var_dep or col == var_dep: |
|
|
color = "blue" |
|
|
else: |
|
|
color = "red" |
|
|
else: |
|
|
color = "black" |
|
|
|
|
|
|
|
|
fig4.add_trace(go.Scatter( |
|
|
x=[col], |
|
|
y=[row], |
|
|
text=[f"{corr_matrix.loc[row, col]:.2f}"], |
|
|
mode="text", |
|
|
textfont=dict(size=12, color=color), |
|
|
)) |
|
|
|
|
|
|
|
|
fig4.update_layout( |
|
|
title="Matriz de Correlações", |
|
|
xaxis=dict(title="Variáveis", tickmode='array', tickvals=corr_matrix.columns), |
|
|
yaxis=dict(title="Variáveis", tickmode='array', tickvals=corr_matrix.index), |
|
|
template="plotly_white", |
|
|
showlegend=False |
|
|
) |
|
|
|
|
|
return fig1, fig2, fig3, fig4 |
|
|
|
|
|
|
|
|
def exportar_para_excel(df_planilha, df_infos, df_original, df_escalado, df_outliers, resultados_gerais, resultados_vars, df_calc_obs, df_calc_obs_trans): |
|
|
try: |
|
|
|
|
|
buffer = BytesIO() |
|
|
|
|
|
|
|
|
with pd.ExcelWriter(buffer, engine='xlsxwriter') as writer: |
|
|
df_planilha.to_excel(writer, sheet_name='Dados Originais', index=False) |
|
|
df_infos.to_excel(writer, sheet_name='Infos', index=False) |
|
|
df_original.to_excel(writer, sheet_name='Dados Modelo', index=False) |
|
|
df_outliers.to_excel(writer, sheet_name='Outliers', index=False) |
|
|
|
|
|
|
|
|
resultados_lista = [linha.strip() for linha in resultados_gerais.split("\n") if linha.strip()] |
|
|
resultados_df = pd.DataFrame({"Descrição": resultados_lista}) |
|
|
resultados_df.to_excel(writer, sheet_name='Resultados Gerais', index=False) |
|
|
|
|
|
resultados_vars.to_excel(writer, sheet_name='Resultados Variáveis', index=False) |
|
|
df_calc_obs.to_excel(writer, sheet_name='Calc x Obs', index=False) |
|
|
|
|
|
|
|
|
buffer.seek(0) |
|
|
|
|
|
|
|
|
return buffer.getvalue() |
|
|
|
|
|
except Exception as e: |
|
|
return f"Erro ao criar o arquivo Excel: {str(e)}" |
|
|
|
|
|
|
|
|
|
|
|
def exportar_modelo_completo_avse(nome_pacote, modelo, resultados_gerais, df_planilha, df_infos, df_original, df_outliers, resultados_vars, df_calc_obs): |
|
|
try: |
|
|
|
|
|
if not nome_pacote: |
|
|
return "Erro: O nome do arquivo não pode estar vazio." |
|
|
|
|
|
|
|
|
if not nome_pacote.endswith(".avse"): |
|
|
nome_pacote += ".avse" |
|
|
|
|
|
|
|
|
pacote = { |
|
|
"modelo": modelo, |
|
|
"Resultados Gerais": resultados_gerais, |
|
|
"df_planilha": df_planilha, |
|
|
"df_infos": df_infos, |
|
|
"df_original": df_original, |
|
|
"df_outliers": df_outliers, |
|
|
"resultados_vars": resultados_vars, |
|
|
"df_calc_obs": df_calc_obs |
|
|
} |
|
|
|
|
|
|
|
|
dump(pacote, nome_pacote) |
|
|
|
|
|
return f"Pacote '{nome_pacote}' criado com sucesso." |
|
|
|
|
|
except Exception as e: |
|
|
return f"Erro ao criar o pacote: {str(e)}" |
|
|
|
|
|
|
|
|
|
|
|
def carregar_modelo(nome_pacote): |
|
|
try: |
|
|
|
|
|
pacote = joblib.load(nome_pacote) |
|
|
|
|
|
|
|
|
modelo = pacote.get("modelo", None) |
|
|
resultados_gerais = pacote.get("Resultados Gerais", "") |
|
|
df_planilha = pacote.get("df_planilha", pd.DataFrame()) |
|
|
df_infos = pacote.get("df_infos", pd.DataFrame()) |
|
|
df_original = pacote.get("df_original", pd.DataFrame()) |
|
|
df_outliers = pacote.get("df_outliers", pd.DataFrame()) |
|
|
resultados_vars = pacote.get("resultados_vars", pd.DataFrame()) |
|
|
df_calc_obs = pacote.get("df_calc_obs", pd.DataFrame()) |
|
|
|
|
|
|
|
|
if not df_infos.empty: |
|
|
df_infos.loc[len(df_infos)] = [None] * len(df_infos.columns) |
|
|
|
|
|
|
|
|
df_infos_transposed = df_infos.T |
|
|
|
|
|
|
|
|
df_infos_transposed.columns = ['Escalas', 'Máximo', 'Mínimo', 'Médio', 'Avaliando'] |
|
|
|
|
|
|
|
|
df_infos_transposed.insert(0, 'Variáveis', df_infos.columns) |
|
|
|
|
|
|
|
|
df_infos_transposed.iloc[0, -1] = "Variável dependente" |
|
|
|
|
|
|
|
|
nome_arquivo = os.path.basename(nome_pacote) |
|
|
|
|
|
|
|
|
mensagem_sucesso = f"Modelo '{nome_arquivo}' carregado com sucesso." |
|
|
|
|
|
|
|
|
return ( |
|
|
mensagem_sucesso, |
|
|
modelo, |
|
|
resultados_gerais, |
|
|
df_planilha, |
|
|
df_original, |
|
|
df_outliers, |
|
|
resultados_vars, |
|
|
df_calc_obs, |
|
|
df_infos_transposed, |
|
|
) |
|
|
except Exception as e: |
|
|
|
|
|
return ( |
|
|
"Carregue o modelo antes de clicar no botão VISUALIZAR MODELO", |
|
|
None, |
|
|
"", |
|
|
pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
def realizar_previsoes(modelo, tab_infos_carregada): |
|
|
try: |
|
|
if modelo is None or tab_infos_carregada.empty: |
|
|
return "Erro: Modelo não carregado ou tabela de informações vazia.", pd.DataFrame(), pd.DataFrame(), "" |
|
|
|
|
|
|
|
|
escalas_independentes = tab_infos_carregada.iloc[1:, 1].to_list() |
|
|
escala_dependente = tab_infos_carregada.iloc[0, 1] |
|
|
|
|
|
|
|
|
valores_entrada = tab_infos_carregada.iloc[1:, 5].values |
|
|
|
|
|
|
|
|
valores_entrada = pd.to_numeric(valores_entrada, errors='coerce') |
|
|
|
|
|
|
|
|
valores_transformados = [] |
|
|
for valor, escala in zip(valores_entrada, escalas_independentes): |
|
|
if np.isnan(valor): |
|
|
valores_transformados.append(np.nan) |
|
|
elif escala == "ln(x)": |
|
|
valores_transformados.append(np.log(valor) if valor > 0 else np.nan) |
|
|
elif escala == "1/(x)": |
|
|
valores_transformados.append(1 / valor if valor != 0 else np.nan) |
|
|
elif escala == "(x)²": |
|
|
valores_transformados.append(valor ** 2) |
|
|
elif escala == "exp(x)": |
|
|
valores_transformados.append(np.exp(valor)) |
|
|
else: |
|
|
valores_transformados.append(valor) |
|
|
|
|
|
|
|
|
df_previsao = pd.DataFrame([valores_transformados], columns=tab_infos_carregada.iloc[1:, 0]) |
|
|
|
|
|
|
|
|
X = sm.add_constant(df_previsao, has_constant='add') |
|
|
|
|
|
|
|
|
colunas_modelo = modelo.model.exog_names |
|
|
X = X.reindex(columns=colunas_modelo, fill_value=0) |
|
|
|
|
|
|
|
|
if X.isnull().values.any(): |
|
|
return "Erro: Existem valores inválidos após a transformação. Verifique os dados de entrada.", df_previsao, pd.DataFrame(), "" |
|
|
|
|
|
|
|
|
previsao_transformada = modelo.predict(X).iloc[0] |
|
|
|
|
|
|
|
|
if escala_dependente == "ln(x)": |
|
|
previsao_final = np.exp(previsao_transformada) |
|
|
elif escala_dependente == "1/(x)": |
|
|
previsao_final = 1 / previsao_transformada |
|
|
elif escala_dependente == "(x)²": |
|
|
previsao_final = np.sqrt(previsao_transformada) |
|
|
elif escala_dependente == "exp(x)": |
|
|
previsao_final = np.log(previsao_transformada) |
|
|
else: |
|
|
previsao_final = previsao_transformada |
|
|
|
|
|
|
|
|
limite_inferior_arbitrio = previsao_final * 0.85 |
|
|
limite_superior_arbitrio = previsao_final * 1.15 |
|
|
|
|
|
|
|
|
intervalos = modelo.get_prediction(X).conf_int(alpha=0.2) |
|
|
limite_inferior_ic = intervalos[0, 0] |
|
|
limite_superior_ic = intervalos[0, 1] |
|
|
|
|
|
|
|
|
if escala_dependente == "ln(x)": |
|
|
limite_inferior_ic = np.exp(limite_inferior_ic) |
|
|
limite_superior_ic = np.exp(limite_superior_ic) |
|
|
elif escala_dependente == "1/(x)": |
|
|
limite_inferior_ic = 1 / limite_inferior_ic |
|
|
limite_superior_ic = 1 / limite_superior_ic |
|
|
elif escala_dependente == "(x)²": |
|
|
limite_inferior_ic = np.sqrt(limite_inferior_ic) |
|
|
limite_superior_ic = np.sqrt(limite_superior_ic) |
|
|
elif escala_dependente == "exp(x)": |
|
|
limite_inferior_ic = np.log(limite_inferior_ic) |
|
|
limite_superior_ic = np.log(limite_superior_ic) |
|
|
|
|
|
|
|
|
extrapolacao_info = "" |
|
|
valores_ajustados = valores_entrada.copy() |
|
|
contagem_extrapolacoes = 0 |
|
|
fora_dos_criterios = False |
|
|
for i, valor in enumerate(valores_entrada): |
|
|
maximo = pd.to_numeric(tab_infos_carregada.iloc[i+1, 2], errors='coerce') |
|
|
minimo = pd.to_numeric(tab_infos_carregada.iloc[i+1, 3], errors='coerce') |
|
|
|
|
|
if not np.isnan(valor): |
|
|
if valor < minimo: |
|
|
percentual_extrapolacao = ((minimo - valor) / minimo) * -100 |
|
|
extrapolacao_info += f"Variável '{tab_infos_carregada.iloc[i+1, 0]}' está {percentual_extrapolacao:.2f}% abaixo do mínimo da amostra.\n" |
|
|
valores_ajustados[i] = minimo |
|
|
contagem_extrapolacoes += 1 |
|
|
if percentual_extrapolacao < -50: |
|
|
fora_dos_criterios = True |
|
|
elif valor > maximo: |
|
|
percentual_extrapolacao = ((valor - maximo) / maximo) * 100 |
|
|
extrapolacao_info += f"Variável '{tab_infos_carregada.iloc[i+1, 0]}' está {percentual_extrapolacao:.2f}% acima do máximo da amostra.\n" |
|
|
valores_ajustados[i] = maximo |
|
|
contagem_extrapolacoes += 1 |
|
|
if percentual_extrapolacao > 100: |
|
|
fora_dos_criterios = True |
|
|
|
|
|
|
|
|
previsoes_extrapoladas = [] |
|
|
for i, (valor, ajustado) in enumerate(zip(valores_entrada, valores_ajustados)): |
|
|
if valor != ajustado: |
|
|
valores_transformados_ext = [] |
|
|
for valor_ext, escala in zip(valores_ajustados, escalas_independentes): |
|
|
if np.isnan(valor_ext): |
|
|
valores_transformados_ext.append(np.nan) |
|
|
elif escala == "ln(x)": |
|
|
valores_transformados_ext.append(np.log(valor_ext) if valor_ext > 0 else np.nan) |
|
|
elif escala == "1/(x)": |
|
|
valores_transformados_ext.append(1 / valor_ext if valor_ext != 0 else np.nan) |
|
|
elif escala == "(x)²": |
|
|
valores_transformados_ext.append(valor_ext ** 2) |
|
|
elif escala == "exp(x)": |
|
|
valores_transformados_ext.append(np.exp(valor_ext)) |
|
|
else: |
|
|
valores_transformados_ext.append(valor_ext) |
|
|
|
|
|
df_previsao_ext = pd.DataFrame([valores_transformados_ext], columns=tab_infos_carregada.iloc[1:, 0]) |
|
|
X_ext = sm.add_constant(df_previsao_ext, has_constant='add') |
|
|
X_ext = X_ext.reindex(columns=colunas_modelo, fill_value=0) |
|
|
|
|
|
if X_ext.isnull().values.any(): |
|
|
continue |
|
|
|
|
|
previsao_transformada_ext = modelo.predict(X_ext).iloc[0] |
|
|
|
|
|
if escala_dependente == "ln(x)": |
|
|
previsao_final_ext = np.exp(previsao_transformada_ext) |
|
|
elif escala_dependente == "1/(x)": |
|
|
previsao_final_ext = 1 / previsao_transformada_ext |
|
|
elif escala_dependente == "(x)²": |
|
|
previsao_final_ext = np.sqrt(previsao_transformada_ext) |
|
|
elif escala_dependente == "exp(x)": |
|
|
previsao_final_ext = np.log(previsao_transformada_ext) |
|
|
else: |
|
|
previsao_final_ext = previsao_transformada_ext |
|
|
|
|
|
previsoes_extrapoladas.append((df_previsao_ext, previsao_final_ext)) |
|
|
|
|
|
|
|
|
if fora_dos_criterios: |
|
|
fundamentacao = "Fundamentação - Extrapolação (Item 4 (a) tab 9.2.1 NBR 14.653-2): Fora dos critérios" |
|
|
elif contagem_extrapolacoes == 1: |
|
|
fundamentacao = "Fundamentação - Extrapolação (Item 4 (a) tab 9.2.1 NBR 14.653-2): Grau II" |
|
|
elif contagem_extrapolacoes > 1: |
|
|
fundamentacao = "Fundamentação - Extrapolação (Item 4 (a) tab 9.2.1 NBR 14.653-2): Grau I" |
|
|
else: |
|
|
fundamentacao = "" |
|
|
|
|
|
|
|
|
resultado_texto = ( |
|
|
f"Valor estimado central: {locale.currency(previsao_final, grouping=True)}\n" |
|
|
"------------------------------------\n" |
|
|
f"Limite inferior do campo de arbítrio (- 15% do Valor estimado central): {locale.currency(limite_inferior_arbitrio, grouping=True)}\n" |
|
|
f"Limite superior do campo de arbítrio (+ 15% do Valor estimado central): {locale.currency(limite_superior_arbitrio, grouping=True)}\n" |
|
|
"------------------------------------\n" |
|
|
f"Limite inferior do Intervalo de Confiança de 80%: {locale.currency(limite_inferior_ic, grouping=True)}\n" |
|
|
f"Limite superior do Intervalo de Confiança de 80%: {locale.currency(limite_superior_ic, grouping=True)}\n" |
|
|
"------------------------------------\n" |
|
|
f"{extrapolacao_info.strip()}\n" |
|
|
f"{fundamentacao}\n" |
|
|
) |
|
|
|
|
|
|
|
|
resultado_df = df_previsao |
|
|
resultado_df_ext = pd.DataFrame() |
|
|
resultado_texto_ext = "" |
|
|
|
|
|
if previsoes_extrapoladas: |
|
|
for df_ext, previsao_ext in previsoes_extrapoladas: |
|
|
resultado_df_ext = df_ext |
|
|
resultado_texto_ext = ( |
|
|
f"Valor estimado central (na fronteira amostral): {locale.currency(previsao_ext, grouping=True)}\n" |
|
|
"------------------------------------\n" |
|
|
) |
|
|
|
|
|
|
|
|
variacao_percentual = abs((previsao_final - previsao_ext) / previsao_final) * 100 |
|
|
|
|
|
|
|
|
if variacao_percentual > 20: |
|
|
fundamentacao_ext = "Fundamentação - Extrapolação (Item 4 (b) tab 9.2.1 NBR 14.653-2): Fora dos critérios" |
|
|
elif variacao_percentual > 15: |
|
|
fundamentacao_ext = "Fundamentação - Extrapolação (Item 4 (b) tab 9.2.1 NBR 14.653-2): Grau I" |
|
|
else: |
|
|
fundamentacao_ext = "Fundamentação - Extrapolação (Item 4 (b) tab 9.2.1 NBR 14.653-2): Grau II" |
|
|
|
|
|
resultado_texto_ext += f"{fundamentacao_ext}\n" |
|
|
|
|
|
return resultado_df, resultado_texto, resultado_df_ext, resultado_texto_ext |
|
|
|
|
|
except Exception as e: |
|
|
return pd.DataFrame(), "Erro ao realizar a previsão: {str(e)}", pd.DataFrame(), "" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rl_tab(): |
|
|
|
|
|
with gr.Tab("Regressão Linear"): |
|
|
planilha_input = gr.File(label="Carregar Planilha", file_types=[".xls", ".xlsx"], elem_classes=["small-file-upload"]) |
|
|
|
|
|
with gr.Group(): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cabeçalhos_state = gr.State([]) |
|
|
dados_state = gr.State(pd.DataFrame()) |
|
|
escalas_state = gr.State({}) |
|
|
erro_padronizado_state = gr.State([]) |
|
|
|
|
|
grafico_residuos_state = gr.State(None) |
|
|
grafico_histograma_state = gr.State(None) |
|
|
grafico_ajustados_state = gr.State(None) |
|
|
matriz_corr_state = gr.State(None) |
|
|
|
|
|
modelo_state = gr.State(None) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mostrar_planilha = gr.Checkbox(label="MOSTRAR PLANILHA CARREGADA e GRÁFICOS PARA ANÁLISE EXPLORATÓRIA (Os gráficos de dispersão e boxplot são atualizados com a retirada de dados)", value=False) |
|
|
tabela_planilha = gr.Dataframe(visible=False, max_height=250, elem_classes=["small span"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
coluna_y_dispersao = gr.Dropdown(label="Eixo Y (Dispersão)", choices=[], interactive=True, visible=False, scale=3) |
|
|
transformacao_y = gr.Dropdown( |
|
|
label="Transformação para Eixo Y", |
|
|
choices=["Nenhuma", "1/x", "ln(x)", "x²", "exp(x)"], |
|
|
value="Nenhuma", |
|
|
interactive=True, |
|
|
visible=False, |
|
|
scale=2 |
|
|
) |
|
|
coluna_x_dispersao = gr.Dropdown(label="Eixo X (Dispersão)", choices=[], interactive=True, visible=False, scale=3) |
|
|
transformacao_x = gr.Dropdown( |
|
|
label="Transformação para Eixo X", |
|
|
choices=["Nenhuma", "1/x", "ln(x)", "x²", "exp(x)"], |
|
|
value="Nenhuma", |
|
|
interactive=True, |
|
|
visible=False, |
|
|
scale=2 |
|
|
) |
|
|
|
|
|
botao_dispersao_boxplot = gr.Button("Gerar Gráficos de Dispersão e Boxplot", visible=False) |
|
|
with gr.Row(): |
|
|
grafico_dispersao_saida = gr.Plot(label="Gráfico de Dispersão", visible=False, scale=3) |
|
|
grafico_boxplot_saida = gr.Plot(label="Gráfico Boxplot", visible=False, scale=1) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mostrar_dropdowns = gr.Checkbox(label="VARIÁVEIS E ESCALAS (Variável dependente e variáveis independentes)", value=False, elem_classes="checkbox-yellow") |
|
|
|
|
|
|
|
|
with gr.Group(): |
|
|
var_ind = gr.Markdown("Selecione as variáveis desejadas no dropdown da escala para a transformação", visible=False) |
|
|
with gr.Row(): |
|
|
colunas_x = gr.Dropdown(label="(Direta: y ou x)", multiselect=True, choices=[], value=[], interactive=True, visible=False) |
|
|
colunas_ln_x = gr.Dropdown(label="Logarítmica: ln(y) ou ln(x)", multiselect=True, choices=[], interactive=True, visible=False) |
|
|
colunas_exp_x = gr.Dropdown(label="Exponencial: exp(y) ou exp(x)", multiselect=True, choices=[], interactive=True, visible=False) |
|
|
colunas_inv_x = gr.Dropdown(label="Inversa: 1/(y) ou 1/(x)", multiselect=True, choices=[], interactive=True, visible=False) |
|
|
colunas_quad_x = gr.Dropdown(label="Quadrática: (x)² ou (y²) ", multiselect=True, choices=[], interactive=True, visible=False) |
|
|
|
|
|
var_dep = gr.Dropdown(label="Variável Dependente", multiselect=False, choices=[], interactive=True, visible=False) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
|
|
|
botao_gerar_df = gr.Button("Gerar Planilhas", scale=1) |
|
|
|
|
|
mostrar_dataframes = gr.Checkbox(label="MOSTRAR PLANILHAS (Escalas e limites, Variáveis transformadas e Outliers)", value=False, scale=3) |
|
|
|
|
|
tabela_cabecalhos = gr.Dataframe(label="Planilha com Cabeçalhos, Escalas, Máximo, Mínimo e Média das variáveis utilizadas", max_height=200, visible=False, elem_classes=["small span"]) |
|
|
tabela_original = gr.Dataframe(label="Planilha original com Variáveis Escolhidas", max_height=250, visible=False, elem_classes=["small span"]) |
|
|
tabela_escalada = gr.Dataframe(label="Planilha com Variáveis Transformadas", max_height=250, visible=False, interactive=True, headers=None, elem_classes=["small span"]) |
|
|
|
|
|
df_out = gr.Dataframe(label="Outliers", max_height=150, visible=False, interactive=True, headers=None, elem_classes=["small span"]) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
|
|
|
botao_regressao = gr.Button("Gerar Modelo", scale=1) |
|
|
|
|
|
mostrar_resultados = gr.Checkbox(label="REGRESSÃO LINEAR (Resultados gerais e por variável, Resíduos > 2 e Pontos Influenciantes, Valores calculados x valores observados)", value=False, scale=3) |
|
|
|
|
|
with gr.Row(): |
|
|
resultado_geral = gr.Textbox(label="Resultados Gerais", lines=25, interactive=False, visible=False, scale=1) |
|
|
resultado_coef = gr.Dataframe(label="Resultados por Variável", interactive=False, visible=False, scale=1, elem_classes=["small span"]) |
|
|
|
|
|
residuos = gr.Dataframe(label="Resíduos padronizados > 2", interactive=False, max_height=250, visible=False, scale=1, elem_classes=["small span"]) |
|
|
with gr.Row(): |
|
|
|
|
|
residuos_list = gr.Textbox(label="Listagem resíduos padronizados > 2", lines=2, interactive=False, visible=False, scale=2) |
|
|
|
|
|
pontos_inf = gr.Textbox(label="Listagem dos Pontos Influenciantes", lines=2, interactive=False, visible=False, scale=1) |
|
|
|
|
|
entrada_dinamica = gr.Textbox(label="Retirar dados", lines=2, placeholder="Copie e cole os dados da caixa de texto ao lado ou escolha o dado a ser retirado", |
|
|
interactive=True, visible=False, scale=2) |
|
|
|
|
|
|
|
|
calc_obs = gr.Dataframe(label="Calculados x Observados", max_height=250, visible=False, interactive=True, headers=None, elem_classes=["small span"]) |
|
|
calc_obs_trans = gr.Dataframe(label="Calculados Transformados", max_height=250, visible=False, interactive=True, elem_classes=["small span"]) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
|
|
|
botao_graficos = gr.Button("Gerar Gráficos", scale=1) |
|
|
|
|
|
mostrar_graficos = gr.Checkbox(label="GRÁFICOS DO MODELO (Resíduos padronizados, histograma e valores ajustados vs observados, Matriz de Correlações)", value=False, scale=3) |
|
|
|
|
|
escala_graf_ao = gr.Dropdown(label="Escolha a escala da variável dependente para o gráfico Valores Ajustados x Observado", choices=["Transformada", "Direta"]) |
|
|
|
|
|
|
|
|
grafico_selecao = gr.Radio( |
|
|
choices=["Resíduos Padronizados", "Histograma", "Valores Ajustados vs Observados", "Matriz de Correlações"], |
|
|
label="Selecione o Gráfico", |
|
|
interactive=True, |
|
|
visible=False |
|
|
) |
|
|
|
|
|
|
|
|
grafico_saida = gr.Plot(label="Gráfico Selecionado", visible=False) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
botao_exportar_excel = gr.Button("Exportar Planilha") |
|
|
arquivo_excel = gr.File(label="Baixar Excel", interactive=False, visible=False) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
|
|
|
nome_arquivo_modelo = gr.Textbox( |
|
|
label="Nome do Arquivo do Modelo", |
|
|
placeholder="Digite o nome do modelo e clique no botão ao lado para salvar", |
|
|
interactive=True, |
|
|
scale=3 |
|
|
) |
|
|
|
|
|
botao_salvar_modelo = gr.Button("Salvar Modelo", scale=1) |
|
|
saida_salvar_modelo = gr.Textbox( |
|
|
label="Status do Salvamento do Modelo", |
|
|
interactive=False, |
|
|
visible=False, |
|
|
lines=2 |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(equal_height=True): |
|
|
|
|
|
modelo_input = gr.File(label="Carregar Modelo", file_types=[".avse"], elem_classes=["small-file-upload"]) |
|
|
|
|
|
botao_carregar_modelo = gr.Button("Visualizar Modelo") |
|
|
|
|
|
mostrar_modelo_checkbox = gr.Checkbox( |
|
|
label="MOSTRAR DETALHES DO MODELO", |
|
|
value=False, |
|
|
elem_classes=["checkbox-yellow"] |
|
|
) |
|
|
|
|
|
status_carregamento = gr.Textbox( |
|
|
label="Status do Carregamento do Modelo", |
|
|
interactive=False, |
|
|
visible=False, |
|
|
lines=1, |
|
|
elem_classes=["small span"] |
|
|
) |
|
|
|
|
|
|
|
|
resultado_geral_carregado = gr.Textbox( |
|
|
label="Resultados Gerais (Carregados)", |
|
|
interactive=False, |
|
|
visible=False, |
|
|
lines=25, |
|
|
elem_classes=["small span"] |
|
|
) |
|
|
|
|
|
|
|
|
tabela_planilha_carregada = gr.Dataframe(label="Dados Originais", visible=False, max_height=250, elem_classes=["small span"]) |
|
|
tabela_original_carregada = gr.Dataframe(label="Dados Modelo", visible=False, max_height=250, elem_classes=["small span"]) |
|
|
tabela_outliers_carregada = gr.Dataframe(label="Outliers", visible=False, max_height=250, elem_classes=["small span"]) |
|
|
tabela_resultados_vars_carregada = gr.Dataframe(label="Resultados Variáveis", visible=False, max_height=250, elem_classes=["small span"]) |
|
|
tabela_calc_obs_carregada = gr.Dataframe(label="Calculados x Observados", visible=False, max_height=250, elem_classes=["small span"]) |
|
|
tab_infos_carregada = gr.Dataframe(label="Variáveis, escalas, limites e avaliando", interactive=True, visible=False, elem_classes=["small span"]) |
|
|
|
|
|
|
|
|
|
|
|
botao_previsao = gr.Button("Realizar Previsão") |
|
|
tabela_previsao = gr.Dataframe(label="Valores Transformados para Previsão", visible=True, max_height=250) |
|
|
previsao_saida = gr.Textbox(label="Resultado da Previsão", lines=8, interactive=False, visible=True) |
|
|
|
|
|
|
|
|
tabela_previsao_ajustada = gr.Dataframe(label="Valores Transformados para Previsão Ajustada", visible=True, max_height=250) |
|
|
previsao_ajustada_saida = gr.Textbox(label="Resultado da Previsão Ajustada", lines=8, interactive=False, visible=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mostrar_planilha.change( |
|
|
lambda visible, dados: [gr.update(visible=visible, value=dados)] * 8, |
|
|
inputs=[mostrar_planilha, dados_state], |
|
|
outputs=[ |
|
|
tabela_planilha, coluna_y_dispersao, transformacao_y, coluna_x_dispersao, |
|
|
transformacao_x, botao_dispersao_boxplot, |
|
|
grafico_dispersao_saida, grafico_boxplot_saida |
|
|
] |
|
|
) |
|
|
|
|
|
|
|
|
mostrar_dropdowns.change( |
|
|
lambda visible: [gr.update(visible=visible)] * 7, |
|
|
inputs=[mostrar_dropdowns], |
|
|
outputs=[var_ind, colunas_x, colunas_ln_x, colunas_exp_x, colunas_inv_x, colunas_quad_x, var_dep] |
|
|
) |
|
|
|
|
|
|
|
|
mostrar_dataframes.change( |
|
|
lambda visible: [gr.update(visible=visible)] * 3, |
|
|
inputs=[mostrar_dataframes], |
|
|
outputs=[tabela_cabecalhos, tabela_escalada, df_out] |
|
|
) |
|
|
|
|
|
|
|
|
mostrar_resultados.change( |
|
|
lambda visible: [gr.update(visible=visible)] * 7, |
|
|
inputs=[mostrar_resultados], |
|
|
outputs=[resultado_geral, resultado_coef, residuos, residuos_list, pontos_inf, entrada_dinamica, calc_obs] |
|
|
) |
|
|
|
|
|
|
|
|
mostrar_graficos.change( |
|
|
lambda visible: [gr.update(visible=visible)] * 2, |
|
|
inputs=[mostrar_graficos], |
|
|
outputs=[grafico_selecao, grafico_saida] |
|
|
) |
|
|
|
|
|
|
|
|
mostrar_modelo_checkbox.change( |
|
|
lambda visible: [gr.update(visible=visible)] * 8, |
|
|
inputs=[mostrar_modelo_checkbox], |
|
|
outputs=[ |
|
|
resultado_geral_carregado, tabela_planilha_carregada, tabela_original_carregada, |
|
|
tabela_outliers_carregada, tabela_resultados_vars_carregada, tabela_calc_obs_carregada, |
|
|
tab_infos_carregada, status_carregamento |
|
|
] |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
planilha_input.change( |
|
|
lambda file: carregar_planilha(file), |
|
|
inputs=[planilha_input], |
|
|
outputs=[cabeçalhos_state, dados_state] |
|
|
) |
|
|
|
|
|
|
|
|
cabeçalhos_state.change( |
|
|
lambda cabecalhos: [gr.update(choices=cabecalhos, value=None)] * 2, |
|
|
inputs=[cabeçalhos_state], |
|
|
outputs=[coluna_y_dispersao, coluna_x_dispersao] |
|
|
) |
|
|
|
|
|
|
|
|
cabeçalhos_state.change( |
|
|
atualizar_dropdowns, |
|
|
inputs=[cabeçalhos_state], |
|
|
outputs=[colunas_x, colunas_ln_x, colunas_exp_x, colunas_inv_x, colunas_quad_x, var_dep] |
|
|
) |
|
|
|
|
|
|
|
|
grafico_selecao.change( |
|
|
lambda escala, selecao, fig1, fig2, fig3, fig4: ( |
|
|
fig1 if selecao == "Resíduos Padronizados" else |
|
|
(fig2 if selecao == "Histograma" else |
|
|
(fig3 if selecao == "Valores Ajustados vs Observados" else fig4)) |
|
|
), |
|
|
inputs=[escala_graf_ao, grafico_selecao, grafico_residuos_state, grafico_histograma_state, grafico_ajustados_state, matriz_corr_state], |
|
|
outputs=[grafico_saida] |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
botao_dispersao_boxplot.click( |
|
|
lambda df, y_coluna, transformacao_y, x_coluna, transformacao_x, dados_out: ( |
|
|
grafico_dispersao(df, y_coluna, transformacao_y, x_coluna, transformacao_x, dados_out), |
|
|
grafico_boxplot(df, y_coluna, transformacao_y, x_coluna, transformacao_x, dados_out) |
|
|
), |
|
|
inputs=[dados_state, coluna_y_dispersao, transformacao_y, coluna_x_dispersao, transformacao_x, entrada_dinamica], |
|
|
outputs=[grafico_dispersao_saida, grafico_boxplot_saida] |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
botao_gerar_df.click( |
|
|
criar_dataframe_cabecalhos, |
|
|
inputs=[cabeçalhos_state, colunas_x, colunas_ln_x, colunas_exp_x, colunas_inv_x, colunas_quad_x, dados_state, entrada_dinamica, var_dep], |
|
|
outputs=[tabela_cabecalhos, escalas_state] |
|
|
) |
|
|
|
|
|
botao_gerar_df.click( |
|
|
criar_dataframes, |
|
|
inputs=[dados_state, colunas_x, colunas_ln_x, colunas_exp_x, colunas_inv_x, colunas_quad_x, entrada_dinamica, var_dep], |
|
|
outputs=[tabela_original, tabela_escalada, df_out] |
|
|
) |
|
|
|
|
|
|
|
|
botao_regressao.click( |
|
|
realizar_regressao, |
|
|
inputs=[var_dep, tabela_escalada, tabela_original, escalas_state], |
|
|
outputs=[resultado_geral, resultado_coef, residuos, residuos_list, pontos_inf, calc_obs, calc_obs_trans, |
|
|
erro_padronizado_state, modelo_state] |
|
|
) |
|
|
|
|
|
|
|
|
botao_graficos.click( |
|
|
graficos, |
|
|
inputs=[escala_graf_ao, calc_obs, calc_obs_trans, erro_padronizado_state, var_dep], |
|
|
outputs=[grafico_residuos_state, grafico_histograma_state, grafico_ajustados_state, matriz_corr_state] |
|
|
) |
|
|
|
|
|
|
|
|
botao_exportar_excel.click( |
|
|
lambda df_planilha, df_infos, df_original, df_escalado, df_out, resultados_gerais, resultados_vars, df_calc_obs, df_calc_obs_trans: ( |
|
|
"resultado.xlsx", |
|
|
exportar_para_excel( |
|
|
df_planilha, df_infos, df_original, df_escalado, df_out, |
|
|
resultados_gerais, resultados_vars, df_calc_obs, df_calc_obs_trans |
|
|
) |
|
|
), |
|
|
inputs=[ |
|
|
dados_state, tabela_cabecalhos, tabela_original, tabela_escalada, df_out, |
|
|
resultado_geral, resultado_coef, calc_obs, calc_obs_trans |
|
|
], |
|
|
outputs=[arquivo_excel] |
|
|
) |
|
|
|
|
|
|
|
|
botao_salvar_modelo.click( |
|
|
lambda nome_arquivo, modelo, resultados_gerais, df_planilha, df_infos, df_original, df_outliers, resultados_vars, df_calc_obs: ( |
|
|
exportar_modelo_completo_avse( |
|
|
nome_arquivo, modelo, resultados_gerais, df_planilha, df_infos, df_original, |
|
|
df_outliers, resultados_vars, df_calc_obs |
|
|
) |
|
|
), |
|
|
inputs=[ |
|
|
nome_arquivo_modelo, modelo_state, resultado_geral, dados_state, tabela_cabecalhos, |
|
|
tabela_original, df_out, resultado_coef, calc_obs |
|
|
], |
|
|
outputs=[saida_salvar_modelo] |
|
|
) |
|
|
|
|
|
botao_salvar_modelo.click( |
|
|
lambda: gr.update(visible=True), |
|
|
inputs=[], |
|
|
outputs=[saida_salvar_modelo] |
|
|
) |
|
|
|
|
|
|
|
|
botao_carregar_modelo.click( |
|
|
carregar_modelo, |
|
|
inputs=[modelo_input], |
|
|
outputs=[ |
|
|
status_carregamento, |
|
|
modelo_state, |
|
|
resultado_geral_carregado, |
|
|
tabela_planilha_carregada, tabela_original_carregada, tabela_outliers_carregada, |
|
|
tabela_resultados_vars_carregada, tabela_calc_obs_carregada, tab_infos_carregada |
|
|
] |
|
|
) |
|
|
|
|
|
|
|
|
botao_previsao.click( |
|
|
realizar_previsoes, |
|
|
inputs=[modelo_state, tab_infos_carregada], |
|
|
outputs=[tabela_previsao, previsao_saida, tabela_previsao_ajustada, previsao_ajustada_saida] |
|
|
) |
|
|
|
|
|
return locals() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|