Eksplorasi Data dan Prediksi Pemodelan dari Kasus Serangan Jantung

Galih Bahtera
8 min readJun 23, 2021
Photo by Robina Weermeijer on Unsplash

Penyakit jantung saat ini merupakan salah satu penyakit yang banyak diderita oleh banyak orang. Penyakit jantung sendiri umumnya mengacu pada pada kondisi yang melibatkan penyempitan atau pemblokiran pembuluh darah yang bisa menyebabkan serangan jantung, nyeri dada (angina) atau stroke. Penyakit jantung sendiri memiliki banyak factor pemicu yang dapat menyebabkan terjadinya serangan jantung.

Pada kasus kali ini, saya akan mencoba melakukan eksplorasi dan analisis data serta mencoba untuk melakukan prediksi pemodelan pada kasus serangan jantung atau heart attack. Untuk data saya menggunakan data dari situs kaggle yang datanya dapat diakses pada link berikut.

Import library dan membaca dataset

Sebelum melakukan eksplorasi dan analisis data, terlebih dahulu melakukan import library dasar dan dilanjutkan dengan membaca dataset, menggunakan fungsi read yang ada di Pandas.

#import basic library
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
heart = pd.read_csv('/content/heart.csv')

Setelah melakukan pembacaan data melihat data yang telah dibaca

heart.head()
heart.tail()

Selanjutnya melihat jumlah data yang dibaca

heart.shape

(303, 14)

Lalu melanjutkan dengan melihat statiska deskriptif

heart.describe().T

Info dari dataset yang ada

heart.info()

Deskripsi Fitur

  • Age : Umur pasien
  • Sex : Jenis Kelamin pasien (0 = Perempuan, 1 = Laki-Laki
  • exang: olahraga untuk induksi angina (1 = yes; 0 = no)
  • ca: jumlah pembuluh darah utama
  • cp : Tipe dari nyeri dada
    — Value 1: nyeri dada normal
    — Value 2: nyeri dada anormal
    — Value 3: tidak ada nyeri dada
    — Value 4: asymptomatic
  • trtbps : tekanan darah (mm Hg)
  • chol : kolestrol dalam mg/dl
  • slp : perubahan kemampuan bicara
  • fbs : (gula darah ketika puasa > 120 mg/dl) (1 = true; 0 = false)
  • rest_ecg : hasil resting EKG
    — Value 0: normal
    — Value 1: memiliki gelombang ST-T abnormal
    — Value 2: menunjukkan kemungkinan atau hipertrofi ventrikel kiri dengan kriteria Estestes
  • thalach : maximum detak jantung
  • output : 0= kemungkinan kecil terkena serangan jantung, 1= kemungkinan besar terkena serangan jantung

Missing Value

Selanjutnya adalah pengecekan missing value, missing value sendiri adalah data yang kosong atau tidak ber nilai. Missing value ini dapat mengganggu dalam analisis mau pun pemodelan data sehingga harus diisi atau bahkan dibuang.

heart.isnull().sum()

Setelah dilakukan pengecekan, tidak terdapat missing value pada dataset yang telah terimpor.

Duplikasi Data

Duplikasi data sendiri seperti namanya, duplikasi data adalah data yang sama seperti data yang lain. Duplikasi data sendiri juga dapat mengganggu ketika dilakukan analisis dan prediksi model. Oleh karena itu seringnya data yang terduplikasi akan dibuang.

def cek_duplikat(dataframe):
if dataframe.duplicated().sum() > 0 :
print ('Ada duplikasi data sebanyak {} data' .format(dataframe.duplicated().sum())) else: print('Tidak ada duplikasi data')cek_duplikat(heart)

Ada duplikasi data sebanyak 1 data

Setelah dilakukan pengecekan ternyata terdapat 1 data yang terduplikasi. Selanjutnya akan melihat data yang terduplikasi tersebut.

#Melihat data yang terduplikasi
heart[heart.duplicated()]

Setelah melihat data yang terduplikasi tersebut, yang akan dilakukan adalah men-drop atau menghilangkan data duplikasi tersebut. Lalu menjalankan def cek_duplikasi(dataframe) untuk melihat apakah data duplikasi tersebut sudah hilang atau belum.

#Menghapus duplikasi
heart.drop_duplicates(inplace=True)
cek_duplikat(heart)

Tidak ada duplikasi data

Melihat jumlah data setelah data duplikasi tersebut di-drop.

print('Jumlah data setelah menghilangkan duplikasi:', heart.shape)

Jumlah data setelah menghilangkan duplikasi: (302, 14)

Analisa Dan Visualisasi

Selanjutnya adalah melakukan Analisa dan Visualisasi Data yang ada. Yang pertama adalah menggunakan korelasi, untuk melihat korelasi antar data yang ada.

plt.figure(figsize=(14, 8))
sns.heatmap(heart.corr(), annot=True, cmap='YlGnBu')
plt.tight_layout()
plt.show()

Setelah dilihat dapat dikatakan ada beberapa kolom data yang saling berkorelasi dengan kuat.

  • cp dan output berkorelasi cukup kuat sehingga penderita serangan jantung sebagian besar dipengaruhi oleh cp atau rasa nyeri.
  • thalachh dan output berkorelasi cukup kuat, artinya penderita serangan jantung juga sebagian besar dipengaruhi oleh nilai maximum detak jantung.
  • Selain itu thalachh juga berkorelasi dengan slp.
  • Karena thalachh berkorelasi dengan output, juga selain itu berkorelasi dengan slp. Maka slp akan berpengaruh dengan output yang ada.

Analisis Kategorikal Variabel

Setelah melihat data yang ada dapat dilihat yang termasuk data kategorikal adalah sex, cp, fbs, restecg, exng, slp, caa, thall, dan output.

Pertama akan melihat rasio nilai/jumlah dari tiap-tiap kategori yang ada.

print('Ratio Jenis Kelamin\n')
print(pd.DataFrame({'sex': heart['sex'].value_counts(),
"Ratio": 100 * heart['sex'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('')
print('Ratio Nilai CP\n')
print(pd.DataFrame({'cp': heart['cp'].value_counts(),
"Ratio": 100 * heart['cp'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('')
print('Ratio Nilai FBS\n')
print(pd.DataFrame({'fbs': heart['fbs'].value_counts(),
"Ratio": 100 * heart['fbs'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('Ratio Nilai RESTECG\n')
print(pd.DataFrame({'restecg': heart['restecg'].value_counts(),
"Ratio": 100 * heart['restecg'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('')
print('Ratio Nilai EXNG\n')
print(pd.DataFrame({'exng': heart['exng'].value_counts(),
"Ratio": 100 * heart['exng'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('')
print('Ratio Nilai SLP\n')
print(pd.DataFrame({'slp': heart['slp'].value_counts(),
"Ratio": 100 * heart['slp'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('Ratio Nilai CAA\n')
print(pd.DataFrame({'caa': heart['caa'].value_counts(),
"Ratio": 100 * heart['caa'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('')
print('Ratio Nilai THALL\n')
print(pd.DataFrame({'thall': heart['thall'].value_counts(),
"Ratio": 100 * heart['thall'].value_counts() / len(heart)}))
print('')
print("#"*50)
print('')
print('Ratio Nilai OUTPUT\n')
print(pd.DataFrame({'output': heart['output'].value_counts(),
"Ratio": 100 * heart['output'].value_counts() / len(heart)}))
print('')
print("#"*50)

Setelah melihat rasio yang ada, bagaimana jika dilihat berdasarkan hasil outputnya?

print('1)', heart.groupby(['sex', 'output'])['output'].count())
print('')
print('')
print('2)', heart.groupby(['exng', 'output'])['output'].count())
print('')
print('')
print('3)', heart.groupby(['caa', 'output'])['output'].count())
print('4)', heart.groupby(['cp', 'output'])['output'].count())
print('')
print('')
print('5)', heart.groupby(['fbs', 'output'])['output'].count())
print('')
print('')
print('6)', heart.groupby(['restecg', 'output'])['output'].count())
print('7)', heart.groupby(['slp', 'output'])['output'].count())
print('')
print('')
print('8)', heart.groupby(['thall', 'output'])['output'].count())
print('')
print('')
print('9)', heart.groupby(['output'])['output'].count())
fig = plt.figure(figsize=(18,15))
gs = fig.add_gridspec(3,3)
ax_sex = fig.add_subplot(gs[0,0])
sns.countplot(x='sex', hue='output', data=heart, ax=ax_sex, palette='viridis')
sns.despine()
ax_exng = fig.add_subplot(gs[0,1])
sns.countplot(x='exng', hue='output', data=heart, ax=ax_exng, palette='viridis')
sns.despine()
ax_caa = fig.add_subplot(gs[0,2])
sns.countplot(x='caa', hue='output', data=heart, ax=ax_caa, palette='viridis')
sns.despine()
ax_cp = fig.add_subplot(gs[1,0])
sns.countplot(x='cp', hue='output', data=heart, ax=ax_cp, palette='viridis')
sns.despine()
ax_fbs = fig.add_subplot(gs[1,1])
sns.countplot(x='fbs', hue='output', data=heart, ax=ax_fbs, palette='viridis')
sns.despine()
ax_restecg = fig.add_subplot(gs[1,2])
sns.countplot(x='restecg', hue='output', data=heart, ax=ax_restecg, palette='viridis')
sns.despine()
ax_slp = fig.add_subplot(gs[2,0])
sns.countplot(x='slp', hue='output', data=heart, ax=ax_slp, palette='viridis')
sns.despine()
ax_thall = fig.add_subplot(gs[2,1])
sns.countplot(x='thall', hue='output', data=heart, ax=ax_thall, palette='viridis')
sns.despine()
ax_output = fig.add_subplot(gs[2,2])
sns.countplot(x='output', data=heart, ax=ax_output, palette='viridis')
sns.despine()
plt.show()

Hasil analisa kategorikal variabel

  • Pada gambar pertama dapat dilihat bahwa sebagian besar penderita diderita oleh Laki-Laki
  • Sebagian besar yang melakukan terapi angina menderita serangan jantung.
  • Penyumbatan pembuluh darah sebagai penanda adanya penyakit jantung.
  • Sebagian besar orang yang merasakan nyeri dada yang normal tidak menderita penyakit jantung, berbeda ketika dilihat adanya nyeri dada yang tidak normal angka penderita penyakit jantung semakin meningkat.
  • Gula darah tidak terlalu berpengaruh dengan penyakit jantung, dikarenakan pada grafik terlihat bahwa orang yang memiliki gula darah cukup tinggi menunjukkan angka kasus penderita jantung yang rendah.
  • Pada penderita penyakit jantung sebagian besar memiliki hasil EKG dengan hasil gelombang ST-T abnormal.
  • Semakin besar nilai slp maka semakin besar kemungkinan menderita penyakit jantung.
  • Ketika orang memiliki thall tipe 2 maka akan semakin besar juga kemungkinan orang tersebut menderita penyakit jantung.
  • Pada grafik terakhir data penderita penyait jantung lebih banyak dibanding orang yang tidak menderita penyakit jantung.

Analisis Numerikal Variabel

Setelah melakukan analisa secara kategorikal selanjutnya akan melakukan analisa secara numerikal. Kolom yang bersifat numerikal antara lain: age, trtbps, chol, thalachh, oldpeak.

fig = plt.figure(figsize=(18,15))
gs = fig.add_gridspec(2,3)
ax_age = fig.add_subplot(gs[0,0])
sns.kdeplot(x='age', hue='output', data=heart, fill=True, alpha=.5, linewidth=0, ax=ax_age, palette='viridis', shade=True)
sns.despine()
ax_trtbps = fig.add_subplot(gs[0,1])
sns.kdeplot(x='trtbps', hue='output', data=heart, fill=True, alpha=.5, linewidth=0, ax=ax_trtbps, palette='viridis', shade=True)
sns.despine()
ax_chol = fig.add_subplot(gs[0,2])
sns.kdeplot(x='chol', hue='output', data=heart, fill=True, alpha=.5, linewidth=0, ax=ax_chol, palette='viridis', shade=True)
sns.despine()
ax_thalachh = fig.add_subplot(gs[1,0])
sns.kdeplot(x='thalachh', hue='output', data=heart, fill=True, alpha=.5, linewidth=0, ax=ax_thalachh, palette='viridis', shade=True)
sns.despine()
ax_oldpeak = fig.add_subplot(gs[1,1])
sns.kdeplot(x='oldpeak', hue='output', data=heart, fill=True, alpha=.5, linewidth=0, ax=ax_oldpeak, palette='viridis', shade=True)
sns.despine()

Dari grafik yang ada dapat dianalisa:

  • Sebagian besar penderita penyakit jantung berumur antara 40–60 tahun.
  • Sebagian besar penderita penyakit jantung memiliki tekanan darah tinggai dengan nilai kisaran 120-150 mm/Hg.
  • Hampir sebagian orang yang memiliki kolestrol memiliki penyakit jantung, walaupun ada sebagian yang tidak memiliki.
  • Orang yang memiliki nilai tinggi (antara 125–175) berkemungkinan besar memiliki penyakit jantung.
  • Pada oldpeak (depresi ST yang diakibatkan oleh latihan relative terhadap saat istirahat) penderita penyakit jantung akan memiliki nilai yang kecil dibandingkan dengan orang yang tidak penderita penyakit jantung.

Prediksi Pemodelan

Selanjut adalah melakukan pemrediksian model. Pada kali ini akan menggunakan logistic regression. Mengapa menggunakan logistic regression , dikarenakan pemodelan logistic regression digunakan untuk melakukan prediksi apakah sesuatu bernilai 0 atau 1, sehingga dinilai cocok untuk pemodelan ini.

Sebelum melakukan pemodelan adalah melakukan import library yang akan digunakan ketika pemodelan/

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score

Selanjutnya adalah membagi model untuk dilatih dan untuk pengetesan model, menggunakan train_test_split(). Namun sebelumnya untuk variabel x berisi semua kolom kecuali kolom output, dan untuk variable y hanya menggunakan kolom output sebagai targetnya.

x = heart.drop(labels=['output'], axis =1)
y = heart['output']
print(x.shape)
print(y.shape)

(302, 13)

(302,)

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=42)

Setelah dilakukan pembagian train dan test selanjutnya adalah pengimplementasian Logistic Regression.

lr = LogisticRegression()
lr_heart = lr.fit(x_train, y_train)
y_pred_lr = lr_heart.predict(x_test)

Setelah dilakukan pengimplementasian Logistic Regression, munculkan evaluasi model menggunakan confusion matrix.

#evaluasi model dengan confusion matrix
cnf_matrix_lr=confusion_matrix(y_test,y_pred_lr)
print('Confusion Matrix\n',cnf_matrix_lr)

Untuk lebih jelasnya lakukan plotting confusion matrix tersebut.

# Plot confusion matrix
plt.figure()
heatmap = sns.heatmap(pd.DataFrame(cnf_matrix_lr), annot=True, annot_kws={'size': 14}, fmt='d', cmap='YlGnBu')
heatmap.yaxis.set_ticklabels(heatmap.yaxis.get_ticklabels(), rotation=0, ha='right', fontsize=14)
heatmap.xaxis.set_ticklabels(heatmap.xaxis.get_ticklabels(), rotation=0, ha='right', fontsize=14)
plt.title('Confusion Matrix (Logistic Regression)', fontsize=18, color='darkblue')
plt.ylabel('True label', fontsize=14)
plt.xlabel('Predicted label', fontsize=14)
plt.show()

Selanjutnya melihat akurasi dalam pemodelan

acc=accuracy_score(y_test,y_pred_lr)
print('Accuracy: {} %'.format(round((acc*100),3)))

Accuracy: 83.516 %

Hasil akurasi model Logistic Regression diatas adalah 83,516% sehingga hasil pemodelan cukup akurat.

Itulah hasil dari Eksplorasi, Analisis serta prediksi pemodelan data yang telah dibuat menggunakan pemodelan Logistic Regression dengan menggunakan dataset mengenai serangan jantung dan menggunakan bahasa pemrograman Python. Cukup sekian yang dapat saya sampaikan. Terima Kasih.

Sumber: Dataset : https://www.kaggle.com/rashikrahmanpritom/heart-attack-analysis-prediction-dataset

--

--