Skip to content

K-Means - Doenças Cardiovasculares


O Pré-Processamento já foi feito e pode ser encontrado em: Árvore de Decisão


Objetivo

Aplicar o algoritmo de K-Means ao dataset de doenças cardíacas para verificar se é possível identificar grupos de pacientes com perfis semelhantes, sem utilizar a variável alvo (HeartDisease). O objetivo aqui não é prever, mas descobrir padrões ocultos (aprendizado não supervisionado).

Metodologia

K-Means configurado com: - n_clusters=3 (três grupo) - init="k-means++" (boa inicialização dos centróides) - max_iter=300 (número máximo de iterações)

Como os dados têm múltiplas dimensões, aplicou-se PCA (Análise de Componentes Principais) para reduzir para 2 dimensões (PC1 e PC2), permitindo representar os clusters graficamente.

Resultados Obtidos

Centroides finais (em espaço normalizado): - Foram obtidos 3 centróides representando os "perfis médios" de cada grupo de pacientes. (valores mostrados no código, em escala normalizada entre 0 e 1).

Inércia (WCSS - Within-Cluster Sum of Squares): - Valor: 712.73 - Esse número representa a soma das distâncias quadráticas dos pontos em relação ao seu centróide. Quanto menor, mais compactos e coesos são os clusters.

Visualização dos Clusters (via PCA): - O gráfico mostra os pacientes distribuídos em três grupos. - Cada cor representa um cluster. - Os pontos vermelhos em formato de estrela representam os centróides (pontos médios dos clusters). - Observa-se que os grupos são relativamente bem definidos, mas ainda com algumas sobreposições.

2025-12-02T19:35:35.757553 image/svg+xml Matplotlib v3.10.7, https://matplotlib.org/
import numpy as np
import matplotlib.pyplot as plt
from io import StringIO
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import pandas as pd

# pre processamento
def preprocess(df):
    df.fillna(df.median(numeric_only=True), inplace=True)

    df["Sex"] = df["Sex"].map({"M": 1, "F": 0})
    df["ChestPainType"] = df["ChestPainType"].map({"TA": 0, "ATA": 1, "NAP": 2, "ASY": 3})
    df["RestingECG"] = df["RestingECG"].map({"Normal": 0, "ST": 1, "LVH": 2})
    df["ExerciseAngina"] = df["ExerciseAngina"].map({"Y": 1, "N": 0})
    df["ST_Slope"] = df["ST_Slope"].map({"Up": 0, "Flat": 1, "Down": 2})
    return df

# carregar dataset
df = pd.read_csv("https://raw.githubusercontent.com/bligui/Machine-Learning-Ana/refs/heads/main/dados/heart.csv")
df = preprocess(df)

numeric_cols = df.select_dtypes(include=[np.number]).columns

# Normalização Min-Max
df_minmax = df.copy()
df_minmax[numeric_cols] = (df_minmax[numeric_cols] - df_minmax[numeric_cols].min()) / (
    df_minmax[numeric_cols].max() - df_minmax[numeric_cols].min()
)

X = df_minmax[numeric_cols].values

# k-means
kmeans = KMeans(n_clusters=3, init='k-means++', max_iter=300, random_state=42)
labels = kmeans.fit_predict(X)

# visualizacao
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
centers_pca = pca.transform(kmeans.cluster_centers_)

plt.figure(figsize=(12, 10))
plt.scatter(X_pca[:, 0], X_pca[:, 1], c=labels, cmap="viridis", s=60, alpha=0.7, edgecolor="k")
plt.scatter(centers_pca[:, 0], centers_pca[:, 1], c="red", marker="*", s=250, label="Centroids")
plt.title("K-Means Clustering (Heart Dataset) - PCA 2D Projection")
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.legend()


# Print centroids and inertia 
# print("Final centroids:", kmeans.cluster_centers_) 
# print("Inertia (WCSS):", kmeans.inertia_)

buffer = StringIO()
plt.savefig(buffer, format="svg", transparent=True)
print(buffer.getvalue())

Interpretação

  • O algoritmo conseguiu separar a população em três grupos principais, possivelmente relacionados a perfis de risco cardiovascular diferentes.

  • Como a variável HeartDisease não foi usada, o modelo não sabe quem tem ou não a doença, mas pode ser interessante comparar depois os clusters com a variável alvo para verificar se existe relação entre eles e a presença da doença.

  • O PCA reduziu a dimensionalidade para 2 componentes, o que ajuda na visualização, mas simplifica a informação original. Mesmo assim, os clusters mostraram certa estrutura.

Conclusão

O algoritmo K-Means (k=3) conseguiu identificar três grupos distintos de pacientes, mesmo sem utilizar a variável alvo. A inércia encontrada (712,73) indica um nível razoável de coesão interna. Esse tipo de análise pode ser útil para segmentar pacientes em grupos de risco e auxiliar em análises médicas exploratórias.