Neste tutorial, vamos construir um sistema completo de análise e predição de doenças cardíacas usando Python, Streamlit e Machine Learning. Este projeto é perfeito para portfólios e aprendizado de ciência de dados aplicada à saúde.
📋 Pré-requisitos
- Python 3.8+
- Conhecimento básico de Python
- Noções de pandas e machine learning
🚀 Passo 1: Configuração do Ambiente
Primeiro, vamos instalar as dependências necessárias:
bash
pip install streamlit pandas numpy matplotlib seaborn scikit-learn🗂️ Passo 2: Estrutura do Projeto
Crie um arquivo heart_attack.py com a seguinte estrutura:
python
import streamlit as st
import pandas as pdimport numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# Configuração da página
st.set_page_config(page_title="Predição Cardíaca", page_icon="", layout="wide")📊 Passo 3: Carregamento e Cache de Dados
Vamos implementar uma função eficiente para carregar os dados:
python
@st.cache_data
def load_data():
"""
Carrega o dataset de doenças cardíacas com cache para performance
"""
try:
data = pd.read_csv('./data/heart.csv')
st.success("✅ Dados carregados com sucesso!")
return data
except FileNotFoundError:
st.error("❌ Arquivo não encontrado. Verifique o caminho do dataset.")
return None
def mostrar_info_dataset(df):
"""
Mostra informações básicas sobre o dataset
"""
st.subheader("📁 Informações do Dataset")
col1, col2, col3 = st.columns(3)
with col1:
st.metric("Total de Pacientes", len(df))
with col2:
st.metric("Variáveis", len(df.columns))
with col3:
taxa_doenca = (df['output'].mean() * 100)
st.metric("Taxa de Doença Cardíaca", f"{taxa_doenca:.1f}%")
# Expander com detalhes técnicos
with st.expander("🔍 Detalhes Técnicos do Dataset"):
st.write("**Variáveis incluídas:**")
st.write("- `age`: Idade do paciente")
st.write("- `sex`: Sexo (1 = masculino, 0 = feminino)")
st.write("- `cp`: Tipo de dor no peito")
st.write("- `trtbps`: Pressão arterial em repouso")
st.write("- `chol`: Colesterol sérico")
st.write("- `fbs`: Açúcar no sangue em jejum")
st.write("- `restecg`: Resultados eletrocardiográficos em repouso")
st.write("- `thalachh`: Frequência cardíaca máxima alcançada")
st.write("- `exng`: Angina induzida por exercício")
st.write("- `oldpeak`: Depressão ST induzida por exercício")
st.write("- `slp`: Inclinação do segmento ST")
st.write("- `caa`: Número de vasos principais coloridos")
st.write("- `thall`: Talassemia")
st.write("- `output`: Diagnóstico (0 = sem doença, 1 = com doença)")🎨 Passo 4: Estilização com CSS
Vamos criar um design atrativo para nossa aplicação:
python
def aplicar_estilos():
"""
Aplica estilos CSS customizados à aplicação
"""
custom_css = """
<style>
.main-header {
font-size: 3rem;
color: #FF4B4B;
text-align: center;
margin-bottom: 2rem;
font-weight: bold;
}
.section-header {
font-size: 1.8rem;
color: #FF4B4B;
border-bottom: 2px solid #FF4B4B;
padding-bottom: 0.5rem;
margin-top: 2rem;
}
.metric-card {
background-color: #262730;
padding: 1rem;
border-radius: 10px;
border-left: 4px solid #FF4B4B;
}
.insight-box {
background-color: #0E1117;
padding: 1rem;
border-radius: 10px;
border: 1px solid #FF4B4B;
margin: 1rem 0;
}
</style>
"""
st.markdown(custom_css, unsafe_allow_html=True)📈 Passo 5: Análise Exploratória Interativa
Vamos criar visualizações interativas para entender os dados:
python
def criar_analise_exploratoria(df):
"""
Cria seção de análise exploratória com visualizações
"""
st.markdown("<div class='section-header'>📊 Análise Exploratória</div>",
unsafe_allow_html=True)
# Abas para organizar as análises
tab1, tab2, tab3, tab4 = st.tabs([
"📋 Estatísticas",
"📈 Distribuições",
"🔗 Correlações",
"🎯 Insights"
])
with tab1:
criar_estatisticas_descritivas(df)
with tab2:
criar_visualizacoes_distribuicao(df)
with tab3:
criar_analise_correlacao(df)
with tab4:
criar_insights_avancados(df)
def criar_estatisticas_descritivas(df):
"""
Cria visualizações de estatísticas descritivas
"""
st.subheader("Estatísticas Descritivas")
# Métricas principais em cards
col1, col2, col3, col4 = st.columns(4)
with col1:
with st.container():
st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
st.metric("Média Idade", f"{df['age'].mean():.1f} anos")
st.markdown("</div>", unsafe_allow_html=True)
with col2:
with st.container():
st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
st.metric("Pressão Arterial Média", f"{df['trtbps'].mean():.1f} mmHg")
st.markdown("</div>", unsafe_allow_html=True)
with col3:
with st.container():
st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
st.metric("Colesterol Médio", f"{df['chol'].mean():.1f} mg/dl")
st.markdown("</div>", unsafe_allow_html=True)
with col4:
with st.container():
st.markdown("<div class='metric-card'>", unsafe_allow_html=True)
st.metric("Freq. Cardíaca Máx.", f"{df['thalachh'].mean():.1f} bpm")
st.markdown("</div>", unsafe_allow_html=True)
# Tabela de estatísticas
st.dataframe(df.describe(), use_container_width=True)
def criar_visualizacoes_distribuicao(df):
"""
Cria visualizações de distribuição dos dados
"""
st.subheader("Distribuições das Variáveis")
# Seleção interativa de variável
variavel = st.selectbox(
"Selecione a variável para visualizar:",
['age', 'trtbps', 'chol', 'thalachh', 'oldpeak']
)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
# Histograma
sns.histplot(data=df, x=variavel, hue='output', ax=ax1, kde=True)
ax1.set_title(f'Distribuição de {variavel} por Diagnóstico')
# Boxplot
sns.boxplot(data=df, x='output', y=variavel, ax=ax2)
ax2.set_title(f'Boxplot de {variavel} por Diagnóstico')
ax2.set_xticklabels(['Sem Doença', 'Com Doença'])
st.pyplot(fig)
# Insight automático
with st.container():
st.markdown("<div class='insight-box'>", unsafe_allow_html=True)
st.write("💡 **Insight:** Esta visualização mostra como a variável selecionada se distribui entre pacientes com e sem doença cardíaca.")
st.markdown("</div>", unsafe_allow_html=True)🤖 Passo 6: Modelo de Machine Learning Robusto
Vamos implementar um modelo com validação e métricas:
python
class ModeloCardiaco:
def __init__(self):
self.modelo = None
self.X_train = None
self.X_test = None
self.y_train = None
self.y_test = None
def preparar_dados(self, df):
"""
Prepara os dados para treinamento
"""
X = df.drop('output', axis=1)
y = df['output']
self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
return X, y
def treinar_modelo(self, n_estimators=100):
"""
Treina o modelo Random Forest
"""
self.modelo = RandomForestClassifier(
n_estimators=n_estimators,
random_state=42,
max_depth=10,
min_samples_split=5
)
self.modelo.fit(self.X_train, self.y_train)
return self.modelo
def avaliar_modelo(self):
"""
Avalia o modelo e retorna métricas
"""
if self.modelo is None:
raise ValueError("Modelo não foi treinado ainda")
y_pred = self.modelo.predict(self.X_test)
y_pred_proba = self.modelo.predict_proba(self.X_test)[:, 1]
# Cálculo de métricas
acuracia = accuracy_score(self.y_test, y_pred)
# Validação cruzada
cv_scores = cross_val_score(self.modelo, self.X_train, self.y_train, cv=5)
return {
'acuracia': acuracia,
'cv_mean': cv_scores.mean(),
'cv_std': cv_scores.std(),
'matriz_confusao': confusion_matrix(self.y_test, y_pred),
'relatorio_classificacao': classification_report(self.y_test, y_pred)
}
def prever(self, dados):
"""
Faz predição para novos dados
"""
if self.modelo is None:
raise ValueError("Modelo não foi treinado ainda")
probabilidade = self.modelo.predict_proba(dados)[0][1]
return probabilidade
def criar_secao_modelo(df):
"""
Cria a seção completa do modelo de machine learning
"""
st.markdown("<div class='section-header'>🤖 Modelo de Predição</div>",
unsafe_allow_html=True)
# Treinar modelo
if st.button("🚀 Treinar Modelo", type="primary"):
with st.spinner("Treinando modelo..."):
modelo_cardiaco = ModeloCardiaco()
X, y = modelo_cardiaco.preparar_dados(df)
modelo_cardiaco.treinar_modelo()
metricas = modelo_cardiaco.avaliar_modelo()
# Mostrar resultados
col1, col2 = st.columns(2)
with col1:
st.metric("Acurácia", f"{metricas['acuracia']:.2%}")
st.metric("Validação Cruzada", f"{metricas['cv_mean']:.2%} (±{metricas['cv_std']:.2%})")
with col2:
st.write("**Matriz de Confusão:**")
st.dataframe(metricas['matriz_confusao'])
# Salvar modelo na session state
st.session_state.modelo = modelo_cardiaco
st.session_state.metricas = metricas
# Mostrar métricas se modelo já foi treinado
if 'metricas' in st.session_state:
st.success("✅ Modelo treinado e avaliado com sucesso!")
with st.expander("📊 Ver Relatório Detalhado"):
st.text(st.session_state.metricas['relatorio_classificacao'])
return st.session_state.get('modelo', None)🎯 Passo 7: Interface de Predição
Vamos criar um formulário interativo para predições:
python
def criar_formulario_predicao(modelo):
"""
Cria formulário para entrada de dados e predição
"""
st.markdown("<div class='section-header'>🎯 Fazer Predição</div>",
unsafe_allow_html=True)
with st.form("formulario_predicao"):
st.write("**Informações do Paciente:**")
col1, col2 = st.columns(2)
with col1:
idade = st.slider("Idade", 20, 80, 50)
sexo = st.selectbox("Sexo", ["Masculino", "Feminino"])
tipo_dor = st.selectbox(
"Tipo de Dor no Peito",
["0 - Típica", "1 - Atípica", "2 - Não anginosa", "3 - Assintomática"]
)
pressao_arterial = st.slider("Pressão Arterial (mmHg)", 90, 200, 120)
colesterol = st.slider("Colesterol (mg/dl)", 100, 400, 200)
with col2:
glicemia = st.selectbox("Glicemia > 120 mg/dl", ["Não", "Sim"])
freq_card_max = st.slider("Freq. Cardíaca Máxima", 60, 220, 150)
depressao_st = st.slider("Depressão ST", 0.0, 6.0, 1.0, 0.1)
vasos_principais = st.selectbox("Vasos Principais", ["0", "1", "2", "3"])
talassemia = st.selectbox("Talassemia", ["0", "1", "2", "3"])
# Botão de predição
submitted = st.form_submit_button("🔍 Calcular Risco", type="primary")
if submitted and modelo is not None:
# Processar entradas
dados_processados = processar_entradas(
idade, sexo, tipo_dor, pressao_arterial, colesterol,
glicemia, freq_card_max, depressao_st, vasos_principais, talassemia
)
# Fazer predição
probabilidade = modelo.prever(dados_processados)
# Mostrar resultado
mostrar_resultado(probabilidade)
def processar_entradas(idade, sexo, tipo_dor, pressao, colesterol,
glicemia, freq_card, depressao_st, vasos, talassemia):
"""
Processa as entradas do usuário para o formato do modelo
"""
sexo_num = 1 if sexo == "Masculino" else 0
tipo_dor_num = int(tipo_dor.split(" - ")[0])
glicemia_num = 1 if glicemia == "Sim" else 0
dados = pd.DataFrame({
'age': [idade],
'sex': [sexo_num],
'cp': [tipo_dor_num],
'trtbps': [pressao],
'chol': [colesterol],
'fbs': [glicemia_num],
'restecg': [0], # Valor padrão
'thalachh': [freq_card],
'exng': [0], # Valor padrão
'oldpeak': [depressao_st],
'slp': [1], # Valor padrão
'caa': [int(vasos)],
'thall': [int(talassemia)]
})
return dados
def mostrar_resultado(probabilidade):
"""
Mostra o resultado da predição de forma visual
"""
st.markdown("---")
st.subheader("📊 Resultado da Predição")
# Barra de progresso visual
st.write(f"**Probabilidade de Doença Cardíaca:** {probabilidade:.1%}")
st.progress(float(probabilidade))
# Interpretação do resultado
if probabilidade < 0.3:
st.success("🎉 **Baixo Risco** - Probabilidade baixa de doença cardíaca")
elif probabilidade < 0.7:
st.warning("⚠️ **Risco Moderado** - Recomendada avaliação médica")
else:
st.error("🚨 **Alto Risco** - Procure avaliação médica urgente")
# Disclaimer médico
with st.expander("⚠️ Aviso Importante"):
st.warning("""
Este sistema é uma ferramenta educacional e **NÃO substitui** o diagnóstico médico profissional.
Consulte sempre um médico para avaliações de saúde.
**Limitações:**
- Baseado em dados históricos limitados
- Não considera histórico familiar
- Não substitui exames clínicos
- Precisão do modelo: ~80-85%
""")🔧 Passo 8: Função Principal
Finalmente, vamos integrar tudo na função principal:
python
def main():
"""
Função principal da aplicação
"""
# Aplicar estilos
aplicar_estilos()
# Cabeçalho
st.markdown("<h1 class='main-header'>❤️ Predição de Doenças Cardíacas</h1>",
unsafe_allow_html=True)
st.write("Sistema inteligente para análise e predição de riscos cardíacos usando Machine Learning")
# Carregar dados
df = load_data()
if df is not None:
# Mostrar informações do dataset
mostrar_info_dataset(df)
# Análise exploratória
criar_analise_exploratoria(df)
# Seção do modelo
modelo = criar_secao_modelo(df)
# Formulário de predição (após modelo treinado)
if modelo is not None:
criar_formulario_predicao(modelo)
else:
st.info("💡 Treine o modelo primeiro para habilitar as predições")
# Rodapé
st.markdown("---")
st.markdown(
"Desenvolvido com ❤️ usando Streamlit | "
"[](https://github.com)"
)
if __name__ == "__main__":
main()Como Rodar o Algoritimo em um Ambiente Virtual Usando Python
1 Vamos criar a seguinte estrutura de arquivos:
heart_prediction_app/
├── heart_attack_improved.py
├── requirements.txt
└── data/
└── heart.csv2 requirements.txt
streamlit==1.28.0
pandas==2.0.3
numpy==1.24.3
matplotlib==3.7.2
seaborn==0.12.2
scikit-learn==1.3.03 Criar o ambiente virtual com python
# 1. Entre no Diretório heart_prediction_app e rode:
python -m venv heart_env
# 2. Ativar ambiente (Linux/Mac)
source heart_env/bin/activate
# 3. Ativar ambiente (Windows)
heart_env\Scripts\activate
# 4. Instalar dependências
pip install -r requirements.txt
# 4.1 Se houver erro no requirements.txt, instale uma dependência de cada vez.
pip install streamlit pandas numpy matplotlib seaborn scikit-learn
# 5. Executar aplicação
streamlit run heart_attack_improved.py
🎉 Conclusão
Parabéns! Você construiu um sistema completo de predição de doenças cardíacas com:
- ✅ Análise exploratória interativa
- ✅ Modelo de ML com validação robusta
- ✅ Interface moderna e responsiva
- ✅ Formulário de predição intuitivo
- ✅ Visualizações profissionais
🚀 Próximos Passos
- Melhorias técnicas:
- Adicionar mais algoritmos de ML
- Implementar feature engineering
- Adicionar persistência do modelo
- Funcionalidades:
- Exportar relatórios
- Histórico de predições
- Múltiplos datasets
- Deploy:
- Docker
Este tutorial mostra como construir uma aplicação de data science completa. Ideal para aprender Streamlit, ML aplicado e desenvolvimento de dashboards interativos!
projeto completo no github

