Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -8,6 +8,9 @@ import numpy as np
|
|
| 8 |
import plotly.express as px
|
| 9 |
import io
|
| 10 |
from sklearn.metrics import confusion_matrix, roc_curve, auc
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
# --- CONFIGURAÇÃO ---
|
| 13 |
st.set_page_config(page_title="CrediFast Risk System", layout="wide")
|
|
@@ -422,20 +425,105 @@ with tab2:
|
|
| 422 |
st.info("👈 Preencha os dados ao lado e clique em 'Calcular Risco' para ver o resultado.")
|
| 423 |
|
| 424 |
# =========================================================
|
| 425 |
-
# ABA
|
| 426 |
# =========================================================
|
| 427 |
with tab3:
|
| 428 |
-
st.header("IV. Segmentação de Clientes")
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
st.warning("Clusterização não disponível.")
|
| 438 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 439 |
# =========================================================
|
| 440 |
# ABA V: RECOMENDAÇÕES (Mantida)
|
| 441 |
# =========================================================
|
|
|
|
| 8 |
import plotly.express as px
|
| 9 |
import io
|
| 10 |
from sklearn.metrics import confusion_matrix, roc_curve, auc
|
| 11 |
+
from sklearn.decomposition import PCA
|
| 12 |
+
from sklearn.preprocessing import StandardScaler
|
| 13 |
+
from sklearn.cluster import KMeans
|
| 14 |
|
| 15 |
# --- CONFIGURAÇÃO ---
|
| 16 |
st.set_page_config(page_title="CrediFast Risk System", layout="wide")
|
|
|
|
| 425 |
st.info("👈 Preencha os dados ao lado e clique em 'Calcular Risco' para ver o resultado.")
|
| 426 |
|
| 427 |
# =========================================================
|
| 428 |
+
# ABA III: CLUSTERIZAÇÃO COM PCA (Visualização Avançada)
|
| 429 |
# =========================================================
|
| 430 |
with tab3:
|
| 431 |
+
st.header("IV. Segmentação de Clientes (Clusterização)")
|
| 432 |
+
|
| 433 |
+
st.markdown("""
|
| 434 |
+
Abaixo, utilizamos **K-Means** para agrupar clientes semelhantes e **PCA (Análise de Componentes Principais)** para reduzir todas as dimensões (Renda, Idade, Juros, etc.) em um mapa 2D.
|
| 435 |
+
""")
|
| 436 |
+
|
| 437 |
+
# 1. Definição das Colunas Numéricas para Clusterização
|
| 438 |
+
# (Removendo colunas categóricas e alvo)
|
| 439 |
+
cols_cluster = ['person_age', 'person_income', 'person_emp_length',
|
| 440 |
+
'loan_amnt', 'loan_int_rate', 'loan_percent_income',
|
| 441 |
+
'cb_person_cred_hist_length']
|
| 442 |
+
|
| 443 |
+
# 2. Verifica/Gera Clusters (Caso o CSV não tenha a coluna 'Cluster')
|
| 444 |
+
if 'Cluster' not in df.columns:
|
| 445 |
+
with st.spinner("Identificando grupos de clientes (Clusterização)..."):
|
| 446 |
+
# Prepara dados (Inputa médidas se houver nulos para não quebrar)
|
| 447 |
+
X_clus = df[cols_cluster].fillna(df[cols_cluster].mean())
|
| 448 |
+
|
| 449 |
+
# Escala específica para o Cluster (importante ser fresco)
|
| 450 |
+
scaler_clus = StandardScaler()
|
| 451 |
+
X_clus_scaled = scaler_clus.fit_transform(X_clus)
|
| 452 |
+
|
| 453 |
+
# Aplica K-Means (Ex: 4 grupos)
|
| 454 |
+
kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
|
| 455 |
+
df['Cluster'] = kmeans.fit_predict(X_clus_scaled)
|
| 456 |
+
|
| 457 |
+
# Garante que Cluster seja tratado como texto (Categoria) para cores discretas
|
| 458 |
+
df['Cluster'] = df['Cluster'].astype(str)
|
| 459 |
+
|
| 460 |
+
# 3. Aplicação do PCA para Visualização
|
| 461 |
+
try:
|
| 462 |
+
# Prepara dados para PCA
|
| 463 |
+
X_pca_input = df[cols_cluster].fillna(df[cols_cluster].mean())
|
| 464 |
+
scaler_pca = StandardScaler()
|
| 465 |
+
X_scaled = scaler_pca.fit_transform(X_pca_input)
|
| 466 |
+
|
| 467 |
+
# Calcula PCA (Reduz para 2 componentes)
|
| 468 |
+
pca = PCA(n_components=2)
|
| 469 |
+
components = pca.fit_transform(X_scaled)
|
| 470 |
+
|
| 471 |
+
# Cria DataFrame temporário para o gráfico
|
| 472 |
+
df_pca = pd.DataFrame(data=components, columns=['PC1', 'PC2'])
|
| 473 |
+
df_pca['Cluster'] = df['Cluster'].values
|
| 474 |
|
| 475 |
+
# Adiciona dados originais para o Tooltip (Hover)
|
| 476 |
+
df_pca['Renda'] = df['person_income'].values
|
| 477 |
+
df_pca['Empréstimo'] = df['loan_amnt'].values
|
| 478 |
+
df_pca['Risco'] = df['loan_status'].apply(lambda x: 'Calote' if x==1 else 'Bom Pagador').values
|
|
|
|
| 479 |
|
| 480 |
+
# 4. Gráfico Interativo
|
| 481 |
+
col_graph, col_stats = st.columns([2, 1])
|
| 482 |
+
|
| 483 |
+
with col_graph:
|
| 484 |
+
var_explicada = pca.explained_variance_ratio_.sum()
|
| 485 |
+
st.caption(f"Visualização PCA (Explica {var_explicada:.1%} da variação dos dados)")
|
| 486 |
+
|
| 487 |
+
fig_pca = px.scatter(
|
| 488 |
+
df_pca,
|
| 489 |
+
x='PC1',
|
| 490 |
+
y='PC2',
|
| 491 |
+
color='Cluster',
|
| 492 |
+
symbol='Risco', # Diferencia caloteiros por formato (opcional)
|
| 493 |
+
hover_data=['Renda', 'Empréstimo', 'Risco'],
|
| 494 |
+
title="Mapa de Clusters (PCA)",
|
| 495 |
+
color_discrete_sequence=px.colors.qualitative.Bold,
|
| 496 |
+
height=500
|
| 497 |
+
)
|
| 498 |
+
fig_pca.update_traces(marker=dict(size=8, opacity=0.7), selector=dict(mode='markers'))
|
| 499 |
+
st.plotly_chart(fig_pca, use_container_width=True)
|
| 500 |
+
|
| 501 |
+
# 5. Estatísticas dos Perfis
|
| 502 |
+
with col_stats:
|
| 503 |
+
st.subheader("Perfil dos Grupos")
|
| 504 |
+
# Agrupa e calcula médias
|
| 505 |
+
resumo = df.groupby('Cluster')[['person_income', 'loan_amnt', 'person_age', 'loan_status']].mean()
|
| 506 |
+
|
| 507 |
+
# Formatação bonita
|
| 508 |
+
st.dataframe(
|
| 509 |
+
resumo.style.format({
|
| 510 |
+
'person_income': 'R$ {:,.0f}',
|
| 511 |
+
'loan_amnt': 'R$ {:,.0f}',
|
| 512 |
+
'person_age': '{:.0f} anos',
|
| 513 |
+
'loan_status': '{:.1%}'
|
| 514 |
+
}).background_gradient(cmap='Blues', subset=['loan_status']),
|
| 515 |
+
use_container_width=True
|
| 516 |
+
)
|
| 517 |
+
|
| 518 |
+
# Interpretação Rápida (Exemplo genérico, ajuste conforme seus dados reais)
|
| 519 |
+
st.info("""
|
| 520 |
+
**Dica de Análise:**
|
| 521 |
+
* Observe se existe um cluster com **alta inadimplência** (Vermelho escuro na tabela).
|
| 522 |
+
* Veja se o PCA conseguiu separar bem os grupos (espaço entre as cores).
|
| 523 |
+
""")
|
| 524 |
+
|
| 525 |
+
except Exception as e:
|
| 526 |
+
st.error(f"Erro ao gerar PCA: {e}")
|
| 527 |
# =========================================================
|
| 528 |
# ABA V: RECOMENDAÇÕES (Mantida)
|
| 529 |
# =========================================================
|