Pengantar

Latar Belakang

Penyakit kardiovaskular merupakan penyakit yang tidak boleh dianggap remeh. Menurut data World Health Organization penyakit kardiovaskular dapat menyebabkan kematian 17,6 juta orang tiap tahunnya. Banyak faktor yang dapat menyebabkan seseorang terkena penyakit kardiovaskular, seperti pola makan tidak sehat, kebiasaan merokok, kebiasaan kurang gerak dan jarang berolahraga, konsumsi alkohol berlebihan, dsb.

Kita akan mencari tau faktor apa yang mempengaruhi seseorang dapat divonis penyakit kardiovaskular menggunakan dataset Cardiovascular Disease dengan membandingkan data pasien berdasarkan variabel cardio 1 dan 0.

Tentang Dataset

Dataset Cardiovascular Disease merupakan data pasien yang diambil pada saat melakukan pemeriksaan kesehatan. Dataset memiliki 70.000 baris dan 13 kolom yang terdiri dari.

id : Nomor ID
age : Umur dalam hari
gender : Jenis kelamin, 1 = Perempuan 2 = Laki-laki
height : Tinggi badan dalam cm
weight : Berat badan dalam kg
ap_hi : Tekanan darah sistolik
ap_lo : Tekanan darah diastolik
cholesterol : Kadar kolesterol, 1 = Normal 2 = Di Atas Normal 3 = Jauh di Atas Normal
gluc : Kadar gula darah, 1 = Normal 2 = Di Atas Normal 3 = Jauh di Atas Normal
smoke : Apakah pasien perokok?, 1 = Ya 2 = Tidak
alco : Apakah pasien peminum?, 1 = Ya 2 = Tidak
active : Apakah pasien aktif bergerak?, 1 = Ya 2 = Tidak
cardio : Penyakit kardiovaskular, 1 = Ya 2 = Tidak

Data Wrangling

Yang pertama kita lakukan adalah memanggil library yang dibutuhkan.

library(tidyverse)

Selanjutnya kita input dataset Cardiovascular Disease menggunakan fungsi read.csv() dan menyimpannya ke dalam variabel cardio_raw.

cardio_raw <- read.csv("cardio_train.csv")

head(cardio_raw)

Variabel dan nilai pada dataset yang kita punya masih dalam bentuk satu kesatuan. Kita perlu untuk memisahkan mereka menjadi 13 kolom menggunakan separate() seperti pada chunk di bawah. Kita juga membuang kolom yang tidak diperlukan yaitu decimal dan id.

cardio <-
  cardio_raw %>% 
  separate(id.age.gender.height.weight.ap_hi.ap_lo.cholesterol.gluc.smoke.alco.active.cardio, 
           c("id", "age", "gender", "height", "weight", "decimal", "ap_hi", "ap_lo", "cholesterol", "gluc", "smoke", "alco", "active", "cardio")) %>% 
  select(-c(decimal, id))

head(cardio)

Setelah itu kita melakukan glimpse() untuk melihat apakah tipe data sudah sesuai.

glimpse(cardio)
## Rows: 70,000
## Columns: 12
## $ age         <chr> "18393", "20228", "18857", "17623", "17474", "21914", "221…
## $ gender      <chr> "2", "1", "1", "2", "1", "1", "1", "2", "1", "1", "1", "2"…
## $ height      <chr> "168", "156", "165", "169", "156", "151", "157", "178", "1…
## $ weight      <chr> "62", "85", "64", "82", "56", "67", "93", "95", "71", "68"…
## $ ap_hi       <chr> "110", "140", "130", "150", "100", "120", "130", "130", "1…
## $ ap_lo       <chr> "80", "90", "70", "100", "60", "80", "80", "90", "70", "60…
## $ cholesterol <chr> "1", "3", "3", "1", "1", "2", "3", "3", "1", "1", "1", "1"…
## $ gluc        <chr> "1", "1", "1", "1", "1", "2", "1", "3", "1", "1", "1", "1"…
## $ smoke       <chr> "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"…
## $ alco        <chr> "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0"…
## $ active      <chr> "1", "1", "0", "1", "0", "0", "1", "1", "1", "0", "1", "1"…
## $ cardio      <chr> "0", "1", "1", "1", "0", "0", "0", "1", "0", "0", "0", "0"…

Semua kolom masih bertipe data character sehingga kita perlu mengubahnya. Kolom age, height, weight, ap_hi, ap_lo menjadi tipe data numerik dan kolom gender, cholesterol, gluc, smoke, alco, active, cardio menjadi factor.

cardio <- 
  cardio %>% 
  mutate(age = as.numeric(age),
         height = as.numeric(height),
         weight = as.numeric(weight),
         ap_hi = as.numeric(ap_hi),
         ap_lo = as.numeric(ap_lo),
         gender = as.factor(gender),
         cholesterol = as.factor(cholesterol),
         gluc = as.factor(gluc),
         smoke = as.factor(smoke),
         alco = as.factor(alco),
         active = as.factor(active),
         cardio = as.factor(cardio))

Untuk memudahkan kita dalam mengambil insight kita perlu membuat kolom baru yaitu range_age. Kolom range_age merupakan rentang umur pasien yang ditentukan berdasarkan nilai pada kolom age. Tapi sebelumnya kita perlu mengubah kolom age terlebih dahulu dari hari menjadi tahun. Kita bagi nilai pada kolom age dengan 365.

cardio <-
  cardio %>% 
  mutate(age = age/365) 

Hasil pembagian di atas menghasilkan bilangan decimal. Sehingga kita perlu menghapus angka di belakang koma dengan fungsi sub() dan mengubah kembali tipe data variabel age menjadi numerik.

cardio$age = sub("\\..*", "", cardio$age)

cardio$age = as.numeric(cardio$age)

Kita akan mengklasifikasikan kolom range_age menjadi empat kelas yaitu 25-34, 35-44, 45-54, dan 55-64 dan membuat tipe datanya menjadi factor.

cardio <-
  cardio %>% 
  mutate(range_age = case_when(age >= 25 & age <= 34 ~ "25-34",
                               age >= 35 & age <= 44 ~ "35-44",
                               age >= 45 & age <= 54 ~ "45-54",
                               age >= 55 & age <= 64 ~ "55-64")) %>% 
  mutate(range_age = as.factor(range_age))

Selain range_age kita perlu membuat kolom baru lagi yaitu imt. imt merupakan kepanjangan dari indeks massa tubuh. Dengan mengetahui indeks massa tubuh kita dapat menentukan apakah pasien mengalami obesitas atau tidak. Hal ini menjadi perlu karena obesitas salah satu faktor yang berkontribusi langsung dengan penyakit kardiovaskular. Kita dapat menentukan nilai imt dengan membagi berat badan (dalam kg) dengan tinggi badan (dalam m²). Hasil dari perhitungan tersebut akan diklasifikasikan ke dalam empat kelas yaitu obecity, above normal, normal, dan below normal.

cardio <-
  cardio %>% 
  mutate(height = height/100) %>% 
  mutate(imt = case_when(weight/height^2 >= 24.9 ~ "Obecity",
                         weight/height^2 >= 22.9 & weight/height^2 < 24.9 ~ "Above Normal",
                         weight/height^2 >= 18.5 & weight/height^2 < 22.9 ~ "Normal",
                         weight/height^2 < 18.5 ~ "Below Normal")) %>% 
  mutate(imt = as.factor(imt))

Faktor lainnya yang berkontribusi langsung dengan penyakit kardiovaskular adalah hipertensi. Kita perlu untuk mengetahui apakah pasien mengalami hipertensi atau tidak dengan melihat tekanan darah sistolik dan diastolik. Kita mengklasifikasikan menurut ilmu kesehatan yang berlaku menjadi tiga kelas yaitu hypertension, normal, dan hypotension.

cardio <-
  cardio %>% 
  mutate(hyper = case_when(ap_hi >= 140 & ap_lo >= 90 ~ "Hypertension",
                           ap_hi >= 90 & ap_lo >= 60 ~ "Normal",
                           ap_hi < 90 & ap_lo < 60 ~ "Hypotension")) %>% 
  mutate(hyper = as.factor(hyper)) %>% 
  filter(!hyper %in% NA)

Selanjutnya kita perlu melihat apakah terdapat missing value pada data kita.

anyNA(cardio)
## [1] FALSE

Tidak terdapat missing value pada dataset Cardiovascular Disease.

Semua

Kita menggunakan fungsi summary() untuk dapat melihat data secara keseluruhan.

summary(cardio)
##       age        gender        height          weight           ap_hi        
##  Min.   :29.00   1:45221   Min.   :0.550   Min.   : 10.00   Min.   :   12.0  
##  1st Qu.:48.00   2:24331   1st Qu.:1.590   1st Qu.: 65.00   1st Qu.:  120.0  
##  Median :53.00             Median :1.650   Median : 72.00   Median :  120.0  
##  Mean   :52.85             Mean   :1.644   Mean   : 74.23   Mean   :  129.2  
##  3rd Qu.:58.00             3rd Qu.:1.700   3rd Qu.: 82.00   3rd Qu.:  140.0  
##  Max.   :64.00             Max.   :2.500   Max.   :200.00   Max.   :16020.0  
##      ap_lo          cholesterol gluc      smoke     alco      active   
##  Min.   :    0.00   1:52034     1:59090   0:63420   0:65814   0:13641  
##  1st Qu.:   80.00   2: 9485     2: 5159   1: 6132   1: 3738   1:55911  
##  Median :   80.00   3: 8033     3: 5303                                
##  Mean   :   96.75                                                      
##  3rd Qu.:   90.00                                                      
##  Max.   :11000.00                                                      
##  cardio    range_age               imt                 hyper      
##  0:34761   25-34:    4   Above Normal:14489   Hypertension:15131  
##  1:34791   35-44:10177   Below Normal:  639   Hypotension :   20  
##            45-54:28309   Normal      :10067   Normal      :54401  
##            55-64:31062   Obecity     :44357                       
##                                                                   
## 

Berdasarkan hasil di atas kita dapat menemukan bahwa.

‑ Umur pasien yang paling muda adalah 29 tahun sedangkan yang paling tua adalah 64 tahun.
‑ Pasien yang paling banyak melakukan pemeriksaan adalah pasien dengan jenis kelamin perempuan.
‑ Tinggi dan berat badan rata-rata pasien berada di angka 1,64 m dan 74,23 kg.
‑ Jumlah pasien dengan kadar kolesterol normal jauh lebih besar dibanding kelas yang lainnya.
‑ Begitu juga dengan jumlah pasien dengan kadar gula darah normal jauh lebih besar dibanding kelas yang lainnya.
‑ Jumlah pasien yang perokok dan peminum jauh lebih kecil dibanding dengan yang tidak.
‑ Jumlah pasien yang aktif bergerak sebanyak 55.911 dan yang tidak 13.641.
‑ Pada data kita pasien yang divonis penyakit kardiovaskular dan yang tidak memiliki jumlah yang seimbang.

Cardio 1

Selanjutnya kita akan mencari tau variabel apa yang paling berpengaruh terhadap penyakit kardiovaskular. Kita akan melakukan subsetting pada data pasien yang divonis penyakit kardiovaskular dengan menggunakan fungsi filter() dan menyimpannya ke dalam variabel cardio_y.

cardio_y <-
  cardio %>% 
  filter(cardio %in% 1)

Kita ingin melihat jumlah pasien yang divonis penyakit kardiovaskular berdasarkan kolom range umur yang telah kita buat dan kita ubah ke dalam bentuk persen.

prop.table(table(cardio_y$range_age))*100
## 
##     25-34     35-44     45-54     55-64 
##  0.000000  8.737892 36.854359 54.407749

Untuk memudahkan kita dalam melihat kita lakukan plotting.

plot1 <- as.data.frame(prop.table(table(cardio_y$range_age))*100)

ggplot(plot1, aes(x = Var1, y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#cecece", "#cecece", "#cecece", "#5dade2")) +
  xlab("Age Range") + ylab("Percentage") +
  theme_minimal()

Berdasarkan plot di atas kita dapat melihat bahwa semakin besar range umur pasien maka semakin besar pula jumlah pasien yang divonis penyakit kardiovaskular. Pasien dengan range umur 25-34 tidak ada yang divonis penyakit kardiovaskular sedangkan pasien dengan range umur 55-64 merupakan pasien yang paling banyak divonis penyakit kardiovaskular. Umur 35 tahun merupakan umur paling muda yang divonis penyakit kardiovaskular.

Selanjutnya kita akan melihat jumlah pasien yang divonis penyakit kardiovaskular berdasarkan jenis kelamin.

prop.table(table(cardio_y$gender))*100
## 
##        1        2 
## 64.65178 35.34822

Sebanyak 64,7% pasien yang divonis penyakit kardiovaskular adalah perempuan dan sisanya 35,3% adalah laki-laki.

Kita juga akan melihat pasien yang divonis penyakit kardiovaskular berdasarkan kolom baru yang telah kita buat yaitu imt.

prop.table(table(cardio_y$imt))*100
## 
## Above Normal Below Normal       Normal      Obecity 
##   17.8724383    0.5202495   10.3130120   71.2943003

Kita perlu melakukan plotting kembali.

plot2 <- as.data.frame(prop.table(table(cardio_y$imt))*100)

ggplot(plot2, aes(x = reorder(Var1, Freq), y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#cecece", "#cecece", "#cecece", "#5dade2")) +
  xlab("Body Mass Index") + ylab("Percentage") +
  theme_minimal()

Kita dapat melihat semakin tinggi nilai imt maka semakin banyak jumlah pasien yang divonis penyakit kardiovaskular. Jumlah pasien yang memiliki nilai imt obesitas sebanyak 71,3%, jauh lebih besar dibanding dengan kelas yang lainnya. Sedangkan jumlah pasien yang memiliki nilai imt di bawah normal sebanyak 0,5%.

Kita akan mencari tau kadar kolesterol pasien yang divonis penyakit kardiovaskular.

prop.table(table(cardio_y$cholesterol))*100
## 
##        1        2        3 
## 65.89923 16.42954 17.67124
plot3 <- as.data.frame(prop.table(table(cardio_y$cholesterol))*100)

ggplot(plot3, aes(x = Var1, y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#5dade2", "#cecece", "#cecece")) +
  xlab("Cholesterol") + ylab("Percentage") +
  theme_minimal()

Jumlah pasien dengan kadar kolesterol normal paling banyak di antara kelas yang lainnya yaitu 65,9%. Selisih dengan kelas yang lainnya juga cukup jauh. Jumlah pasien dengan kadar kolesterol di atas normal 16,4% sedangkan jauh di atas normal 17,7%.

Kita juga akan mencari tau kadar gula darah pasien yang divonis penyakit kardiovaskular.

prop.table(table(cardio_y$gluc))*100
## 
##         1         2         3 
## 81.710787  8.809750  9.479463
plot4 <- as.data.frame(prop.table(table(cardio_y$gluc))*100)

ggplot(plot4, aes(x = Var1, y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#5dade2", "#cecece", "#cecece")) +
  xlab("Blood Glucose") + ylab("Percentage") +
  theme_minimal()

Sama seperti kolesterol, pasien yang memiliki kadar gula darah normal jauh lebih banyak dibanding kelas lainnya. Pasien dengan kadar gula darah di atas normal sebanyak 8,8% dan jauh di atas normal sebanyak 9,5%.

Selanjutnya kita ingin melihat jumlah pasien yang divonis penyakit kardiovaskular berdasarkan kolom hyper yang telah kita buat.

prop.table(table(cardio_y$hyper))*100
## 
## Hypertension  Hypotension       Normal 
##  36.72214078   0.01149723  63.26636199
plot5 <- as.data.frame(prop.table(table(cardio_y$hyper))*100)

ggplot(plot5, aes(x = reorder(Var1, -Freq), y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#cecece", "#cecece", "#5dade2")) +
  xlab("Hypertension") + ylab("Percentage") +
  theme_minimal()

Pasien dengan nilai hyper normal lebih banyak dibanding dengan hipertensi dan hipotensi. Jumlah pasien dengan nilai hyper hipotensi sangat sedikit yaitu 0,01%. Selisih pasien dengan nilai hyper hipertensi dan normal sekitar 26.6%.

Kita akan melihat jumlah pasien berdasarkan tiga pertanyaan yaitu “apakah pasien perokok?”, “apakah pasien peminum?”, dan “apakah pasien aktif bergerak?”.

prop.table(table(cardio_y$smoke))*100
## 
##         0         1 
## 91.609899  8.390101
prop.table(table(cardio_y$alco))*100
## 
##         0         1 
## 94.780259  5.219741
prop.table(table(cardio_y$active))*100
## 
##        0        1 
## 21.04567 78.95433

Jumlah pasien yang perokok yang divonis penyakit kardiovaskular jauh lebih sedikit dibanding dengan yang tidak. Begitu juga dengan pasien peminum. Sebaliknya pasien yang aktif bergerak memiliki jumlah yang cukup besar dibanding dengan yang tidak.

Cardio 0

Sebagai pembanding kita perlu juga menganalisa pasien yang tidak divonis penyakit kardiovaskular. Kita kembali melakukan subsetting pada kolom cardio dan menyimpannya ke dalam variabel cardio_n.

cardio_n <-
  cardio %>% 
  filter(cardio %in% 0)

Pertama kita akan melihat jumlah pasien yang tidak divonis penyakit kardiovaskular berdasarkan range_age.

prop.table(table(cardio_n$range_age))*100
## 
##       25-34       35-44       45-54       55-64 
##  0.01150715 20.53163028 44.55280343 34.90405915
plot6 <- as.data.frame(prop.table(table(cardio_n$range_age))*100)

ggplot(plot6, aes(x = Var1, y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#cecece", "#cecece", "#5dade2", "#cecece")) +
  xlab("Age Range") + ylab("Percentage") +
  theme_minimal()

Kita dapat melihat jumlah pasien yang tidak divonis penyakit kardiovaskular cenderung naik mulai dari range 25-34 sampai range 45-54. Mulai dari 0,01% sampai 44,6%. Setelah itu turun pada range 55-64 tapi tidak terlalu jauh menjadi 34,9%.

Selanjutnya kita akan melihat jumlah pasien berdasarkan jenis kelamin.

prop.table(table(cardio_n$gender))*100
## 
##        1        2 
## 65.38362 34.61638

Terdapat 65,4% pasien perempuan yang tidak divonis penyakit kardiovaskular dan sisanya laki-laki sebanyak 34,6%.

Kita juga akan melihat jumlah pasien yang tidak divonis penyakit kardiovaskular berdasarkan nilai imt mereka.

prop.table(table(cardio_n$imt))*100
## 
## Above Normal Below Normal       Normal      Obecity 
##    23.793907     1.317569    18.638704    56.249820
plot7 <- as.data.frame(prop.table(table(cardio_n$imt))*100)

ggplot(plot7, aes(x = reorder(Var1, Freq), y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#cecece", "#cecece", "#cecece", "#5dade2")) +
  xlab("Body Mass Index") + ylab("Percentage") +
  theme_minimal()

Sama seperti cardio_y, semakin tinggi nilai imt semakin banyak jumlah pasien. Jumlah pasien yang memiliki nilai imt obesitas sebanyak 56,2%. Dan jumlah pasien yang memiliki nilai imt below normal sebanyak 1,3%.

Kita akan melihat jumlah pasien berdasarkan kadar kolesterol dan kadar gula darah mereka.

prop.table(table(cardio_n$cholesterol))*100
## 
##         1         2         3 
## 83.734645 10.842611  5.422744
plot8 <- as.data.frame(prop.table(table(cardio_n$cholesterol))*100)

ggplot(plot8, aes(x = Var1, y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#5dade2", "#cecece", "#cecece")) +
  xlab("Cholesterol") + ylab("Percentage") +
  theme_minimal()

prop.table(table(cardio_n$gluc))*100
## 
##         1         2         3 
## 88.208049  6.023992  5.767958
plot9 <- as.data.frame(prop.table(table(cardio_n$gluc))*100)

ggplot(plot9, aes(x = Var1, y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#5dade2", "#cecece", "#cecece")) +
  xlab("Blood Glucose") + ylab("Percentage") +
  theme_minimal()

Pada cardio_n jumlah pasien yang memiliki kadar kolesterol dan gula darah normal paling banyak di antara kelas yang lainnya. Keduanya memiliki rentang yang sangat jauh dengan kelas di atas normal maupun jauh di atas normal.

Selanjutnya kita akan melihat jumlah pasien berdasarkan tekanan darah mereka.

prop.table(table(cardio_n$hyper))*100
## 
## Hypertension  Hypotension       Normal 
##    6.7748339    0.0460286   93.1791375
plot10 <- as.data.frame(prop.table(table(cardio_n$hyper))*100)

ggplot(plot10, aes(x = reorder(Var1, -Freq), y = Freq)) + 
  geom_bar(stat = "identity", fill = c("#cecece", "#cecece", "#5dade2")) +
  xlab("Hypertension") + ylab("Percentage") +
  theme_minimal()

Jumlah pasien yang memiliki tekanan darah normal sangat berbeda jauh dengan jumlah pasien hipertensi maupun hipotensi. Dimana pasien tekanan darah normal memiliki jumlah sebanyak 93,2%.

Yang terakhir sama seperti cardio_y kita akan melihat jumlah pasien berdasarkan tiga pertanyaan yaitu “apakah pasien perokok?”, “apakah pasien peminum?”, dan “apakah pasien aktif bergerak?”.

prop.table(table(cardio_n$smoke))*100
## 
##         0         1 
## 90.756883  9.243117
prop.table(table(cardio_n$alco))*100
## 
##         0         1 
## 94.470815  5.529185
prop.table(table(cardio_n$active))*100
## 
##        0        1 
## 18.17842 81.82158

Hasilnya sama seperti cardio_y pasien yang perokok dan peminum memiliki jumlah yang sangat sedikit dibanding dengan yang tidak. Tetapi pasien yang aktif bergerak memiliki jumlah yang sangat besar dibanding dengan yang tidak.

Kesimpulan

Setelah melakukan berbagai proses analisa dapat kita temukan bahwa.

  1. Pada cardio_y semakin tua rentang umur pasien maka semakin banyak jumlah pasien yang divonis penyakit kardiovaskular. Tetapi pada cardio_n dua rentang umur pasien yang paling banyak tidak divonis penyakit kardiovaskular adalah 45-54 dan 55-64.
  2. Pada cardio_y jenis kelamin pasien yang paling banyak divonis penyakit kardiovaskular adalah perempuan. Begitu juga pada cardio_n. Jika kita lihat data secara keseluruhan jumlah perempuan 45.221 dan laki-laki 24.331.
  3. Pada cardio_y jumlah pasien dengan nilai imt obesitas jauh lebih banyak dibanding dengan kelas yang lainnya. Begitu juga pada cardio_n.
  4. Pada cardio_y jumlah pasien dengan kadar kolester dan gula darah normal jauh lebih banyak dibanding dengan kelas yang lainnya. Begitu juga pada cardio_n.
  5. Pada cardio_y dan cardio_n jumlah pasien yang memiliki tekanan darah normal lebih banyak dibanding dengan kelas yang lainnya. Meskipun selisih jumlah pasien yang memiliki tekanan darah normal dan hipertensi jauh lebih besar pada cardio_n.
  6. Pada cardio_y dan cardio_n jumlah pasien yang perokok dan peminum jauh lebih sedikit dibanding dengan yang tidak.
  7. Pada cardio_y dan cardio_n jumlah pasien yang aktif bergerak jauh lebih banyak dibanding dengan yang tidak.