UTS PSD A

1. Menggunakan Data Heart Desease: Heart Desease.
data_heart <- read.csv("C:/Users/USER/Downloads/heart.csv")
head (data_heart)
##   age sex cp trestbps chol fbs restecg thalach exang oldpeak slope ca thal
## 1  63   1  3      145  233   1       0     150     0     2.3     0  0    1
## 2  37   1  2      130  250   0       1     187     0     3.5     0  0    2
## 3  41   0  1      130  204   0       0     172     0     1.4     2  0    2
## 4  56   1  1      120  236   0       1     178     0     0.8     2  0    2
## 5  57   0  0      120  354   0       1     163     1     0.6     2  0    2
## 6  57   1  0      140  192   0       1     148     0     0.4     1  0    1
##   target
## 1      1
## 2      1
## 3      1
## 4      1
## 5      1
## 6      1
str(data_heart)
## 'data.frame':    303 obs. of  14 variables:
##  $ age     : int  63 37 41 56 57 57 56 44 52 57 ...
##  $ sex     : int  1 1 0 1 0 1 0 1 1 1 ...
##  $ cp      : int  3 2 1 1 0 0 1 1 2 2 ...
##  $ trestbps: int  145 130 130 120 120 140 140 120 172 150 ...
##  $ chol    : int  233 250 204 236 354 192 294 263 199 168 ...
##  $ fbs     : int  1 0 0 0 0 0 0 0 1 0 ...
##  $ restecg : int  0 1 0 1 1 1 0 1 1 1 ...
##  $ thalach : int  150 187 172 178 163 148 153 173 162 174 ...
##  $ exang   : int  0 0 0 0 1 0 0 0 0 0 ...
##  $ oldpeak : num  2.3 3.5 1.4 0.8 0.6 0.4 1.3 0 0.5 1.6 ...
##  $ slope   : int  0 0 2 2 2 1 1 2 2 2 ...
##  $ ca      : int  0 0 0 0 0 0 0 0 0 0 ...
##  $ thal    : int  1 2 2 2 2 1 2 3 3 2 ...
##  $ target  : int  1 1 1 1 1 1 1 1 1 1 ...
A. Lakukan pengecekan apakah terdapat:
  • Nilai yang hilang (Missing Values).
colSums(is.na(data_heart))
##      age      sex       cp trestbps     chol      fbs  restecg  thalach 
##        0        0        0        0        0        0        0        0 
##    exang  oldpeak    slope       ca     thal   target 
##        0        0        0        0        0        0

Tidak terdapat Missing Values pada data Heart Disease.

  • Data yang tercatat ganda (duplicate records).
#Data Ganda
sum(duplicated(data_heart))
## [1] 1

Terdapat 1 data yang tercatat ganda.

  • Nilai ekstrim (outlier) pada variabel numerik.
check_outliers <- function(x) {
  Q1 <- quantile(x, 0.25)
  Q3 <- quantile(x, 0.75)
  IQR <- Q3 - Q1
  lower <- Q1 - 1.5 * IQR
  upper <- Q3 + 1.5 * IQR
  sum(x < lower | x > upper)
}

# Terapkan fungsi ke kolom numerik
sapply(data_heart[, sapply(data_heart, is.numeric)], check_outliers)
##      age      sex       cp trestbps     chol      fbs  restecg  thalach 
##        0        0        0        9        5       45        0        1 
##    exang  oldpeak    slope       ca     thal   target 
##        0        5        0       25        2        0

Hasilnya menunjukkan bahwa variabel fbs memiliki jumlah outlier terbanyak, yaitu sebanyak 45 nilai. Disusul oleh variabel ca dengan 25 outlier, trestbps dengan 9 outlier, serta chol dan oldpeak masing-masing dengan 5 outlier. Sementara itu, variabel thalach dan thal memiliki 1 dan 2 outlier secara berturut-turut. Adapun variabel age, cp, restecg, exang, dan slope tidak memiliki outlier sama sekali. Ini menunjukkan bahwa beberapa variabel dalam dataset memiliki distribusi data yang lebih stabil.

Karena terdapat data yang duplikat, maka penanganan yang tepat pada data ini adalah melakukan penghapusan data duplikat.

#Menghapus data ganda
data_heart <- data_heart[!duplicated(data_heart), ]

Sehingga didapatkan statistika deskriptif setelah penghapusan data duplikat.
- Statistik Deskriptif.

summary(data_heart[, sapply(data_heart, is.numeric)])
##       age             sex               cp            trestbps    
##  Min.   :29.00   Min.   :0.0000   Min.   :0.0000   Min.   : 94.0  
##  1st Qu.:48.00   1st Qu.:0.0000   1st Qu.:0.0000   1st Qu.:120.0  
##  Median :55.50   Median :1.0000   Median :1.0000   Median :130.0  
##  Mean   :54.42   Mean   :0.6821   Mean   :0.9636   Mean   :131.6  
##  3rd Qu.:61.00   3rd Qu.:1.0000   3rd Qu.:2.0000   3rd Qu.:140.0  
##  Max.   :77.00   Max.   :1.0000   Max.   :3.0000   Max.   :200.0  
##       chol            fbs           restecg          thalach     
##  Min.   :126.0   Min.   :0.000   Min.   :0.0000   Min.   : 71.0  
##  1st Qu.:211.0   1st Qu.:0.000   1st Qu.:0.0000   1st Qu.:133.2  
##  Median :240.5   Median :0.000   Median :1.0000   Median :152.5  
##  Mean   :246.5   Mean   :0.149   Mean   :0.5265   Mean   :149.6  
##  3rd Qu.:274.8   3rd Qu.:0.000   3rd Qu.:1.0000   3rd Qu.:166.0  
##  Max.   :564.0   Max.   :1.000   Max.   :2.0000   Max.   :202.0  
##      exang           oldpeak          slope             ca        
##  Min.   :0.0000   Min.   :0.000   Min.   :0.000   Min.   :0.0000  
##  1st Qu.:0.0000   1st Qu.:0.000   1st Qu.:1.000   1st Qu.:0.0000  
##  Median :0.0000   Median :0.800   Median :1.000   Median :0.0000  
##  Mean   :0.3278   Mean   :1.043   Mean   :1.397   Mean   :0.7185  
##  3rd Qu.:1.0000   3rd Qu.:1.600   3rd Qu.:2.000   3rd Qu.:1.0000  
##  Max.   :1.0000   Max.   :6.200   Max.   :2.000   Max.   :4.0000  
##       thal           target     
##  Min.   :0.000   Min.   :0.000  
##  1st Qu.:2.000   1st Qu.:0.000  
##  Median :2.000   Median :1.000  
##  Mean   :2.315   Mean   :0.543  
##  3rd Qu.:3.000   3rd Qu.:1.000  
##  Max.   :3.000   Max.   :1.000
B. Visualisasi jenis kelamin yang paling banyak mengalami Heart desease, dan usia yang paling banyak mengalami heart desease, dan usia yang memiliki gula darah lebih besar dari 120 mg/dl.
  • Jenis kelamin yang paling banyak mengalami Heart Disease
library(ggplot2)

#Konversi kolom sex & target menjadi faktor
data_heart$sex <- factor(data_heart$sex, labels = c("Female", "Male"))
data_heart$target <- factor(data_heart$target, labels = c("No Disease", "Disease"))

#Visualisasi jenis kelamin yang paling banyak mengalami heart disease.
ggplot(data_heart[data_heart$target == "Disease", ], aes(x = sex)) +
  geom_bar(fill = "#e4cab5") +
  labs(title = "Jenis Kelamin yang Mengalami Heart Disease", x = "Jenis Kelamin", y = "Jumlah") +
  theme_minimal()

Dapat dilihat dari visualisasi diatas yang menunjukkan bahwa jenis kelamin pria yang mengalami Heart Disease

  • Usia yang paling banyak mengalami Heart Disease
#Visualisasi usia yang paling banyak mengalami heart disease.
ggplot(data_heart[data_heart$target == "Disease", ], aes(x = age)) +
  geom_histogram(binwidth = 1, fill = "#D2E0D3", color = "black") +
  labs(title = "Distribusi Usia Pasien dengan Heart Disease", x = "Usia", y = "Jumlah") +
  theme_minimal()

Dari histogram tersebut dapat dilihat bahwa usia 54 tahun merupakan usia yang paling banyak mengalami Heart Disease.
- Usia yang memiliki gula darah lebih besar dari >120 mg/dl.

#Visualisasi usia yang memiliki gula darah yang lebih besar daripada 120 mg/dl.
ggplot(data_heart[data_heart$fbs == 1, ], aes(x = age)) +
  geom_histogram(binwidth = 1, fill = "#f2dfd3", color = "black") +
  labs(title = "Distribusi Usia dengan Gula Darah > 120 mg/dl", x = "Usia", y = "Jumlah") +
  theme_minimal()

Dari histogram diatas dapat dilihat bahwa usia paling banyak dengan gula darah yang lebih besar daripada 120 mg/dl berada di usia 52 tahun.

C. Analisis untuk mengetahui, apakah kadar gula darah seseorang yang lebih besar dari 120 paling banyak mengalami Heart desease?
data_heart$fbs <- factor(data_heart$fbs, labels = c("≤120 mg/dl", ">120 mg/dl"))
data_heart$target <- factor(data_heart$target, labels = c("Tidak", "Ya"))

table_fbs_hd <- table(data_heart$fbs, data_heart$target)
table_fbs_hd
##             
##              Tidak  Ya
##   ≤120 mg/dl   116 141
##   >120 mg/dl    22  23
ggplot(data_heart, aes(x = fbs, fill = target)) +
  geom_bar(position = "fill", color = "black") +
  labs(title = "Proporsi Heart Disease berdasarkan Gula Darah",
       x = "Fasting Blood Sugar",
       y = "Proporsi",
       fill = "Heart Disease") +
  scale_fill_manual(values = c("Tidak" = "#97B3AE", "Ya" = "#D2E0D3")) +
  theme_minimal()

Bar Chart menunjukkan bahwa proporsi penderita dan non-penderita penyakit jantung hampir sama pada kedua kategori gula darah puasa (≤120 mg/dl dan >120 mg/dl). Ini menunjukkan bahwa kadar gula darah puasa tidak menunjukkan hubungan yang jelas dengan keberadaan penyakit jantung dalam data ini.

D. Mengetahui jenis nyeri dada yang paling banyak terjadi pada seseorang mengalami Heart disease.
data_heart$cp <- factor(data_heart$cp, 
                        levels = 0:3,
                        labels = c("Typical Angina", "Atypical Angina", "Non-anginal Pain", "Asymptomatic"))

#Filter data penderita heart disease
penderita_hd <- subset(data_heart, target == "Ya")

#Buat tabel frekuensi jenis nyeri dada
table_cp <- table(penderita_hd$cp)

#Visualisasi
ggplot(penderita_hd, aes(x = cp)) +
  geom_bar(fill = "#97B3AE", color = "black") +
  labs(title = "Jenis Nyeri Dada pada Penderita Heart Disease", 
       x = "Jenis Nyeri Dada", 
       y = "Jumlah") +
  theme_minimal()

Berdasarkan visualisasi diatas, jenis nyeri dada paling umum yang dialami oleh penderita penyakit jantung adalah Non-anginal Pain (nyeri dada non-angina), dengan jumlah kasus tertinggi dibandingkan jenis lainnya. Selanjutnya oleh Atypical Angina dan Typical Angina yang jumlahnya relatif seimbang. Sementara itu, jenis Asymptomatic (tidak menunjukkan gejala nyeri dada) merupakan yang paling jarang terjadi. Hal ini menunjukkan bahwa sebagian besar penderita penyakit jantung dalam dataset mengalami nyeri dada yang tidak khas, bukan nyeri khas angina atau tidak menunjukkan gejala sama sekali.

E. Visualisasi Bar plot proporsi heart desease terhadap variabel kategorikal cp, ca, dan thal.
# cp (jenis nyeri dada)
ggplot(data_heart, aes(x = factor(cp), fill = factor(target))) +
  geom_bar(position = "fill") + 
  scale_fill_manual(
    values = c("#97B3AE", "#D2E0D3")) +
  labs(x = "Jenis Nyeri Dada", y = "Proporsi", fill = "Penyakit Jantung")

Dapat diketahui bahwa pasien dengan cp = 2 (Non-anginal pain) dan cp = 1 (Atypical angina) memiliki proporsi tertinggi menderita penyakit jantung dan cp = 0 (Typical angina) memiliki proporsi lebih rendah terhadap penyakit jantung.

# ca (jumlah pembuluh darah besar)
ggplot(data_heart, aes(x = factor(ca), fill = factor(target))) +
  geom_bar(position = "fill") + 
  scale_fill_manual(
    values = c("#97B3AE", "#D2E0D3")) +
  labs(x = "Jumlah Pembuluh Besar", y = "Proporsi", fill = "Penyakit Jantung")

Dapat diketahui bahwa semakin banyak pembuluh darah yang terlihat (ca > 0), proporsi penderita jantung justru lebih rendah dan ca = 0 memiliki proporsi tertinggi menderita penyakit jantung.

# thal
ggplot(data_heart, aes(x = factor(thal), fill = factor(target))) +
  geom_bar(position = "fill") +  
  scale_fill_manual(
    values = c("#97B3AE", "#D2E0D3")) +
  labs(x = "Jenis Thal", y = "Proporsi", fill = "Penyakit Jantung")

Dapat diketahui bahwa kategori thal = 2 (fixed defect) dan thal = 3 (reversible defect) menunjukkan proporsi tinggi penderita penyakit jantung dan thal = 1 (normal) memiliki proporsi rendah.

F. Lakukan eksplorasi untuk mengetahui arah hubungan antara variabel age dan thalach yang dibedakan untuk seseorang yang memiliki penyakit jantung dan tidak. Apakah hubungan itu linear atau non-linear? Bagaimana cara mengetahuinya?
library(ggplot2)

ggplot(data_heart, aes(x = age, y = thalach, color = as.factor(target))) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(
    title = "Hubungan antara Age dan Thalach berdasarkan Status Penyakit Jantung",
    x = "Usia",
    y = "Detak Jantung Maksimum (thalach)",
    color = "Status"
  ) +
  scale_color_manual(labels = c("Tidak Sakit", "Sakit"), values = c("#97B3AE", "#D2E0D3")) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

Dari visualisasi tersebut dapat dilihat bahwa terdapat arah negatif antara usia dan thalach yang dimana semakin tua usia, cenderung semakin rendah detak jantung maksimum, terutama pada kelompok yang memiliki penyakit jantung. Garis non-linear terlihat lebih mengikuti pola data dibandingkan dengan garis linear, terutama pada kelompok penderita penyakit jantung. Hal ini menunjukkan bahwa hubungan antara age dan thalach cenderung non-linear, terdapat pola yang tidak bisa dijelaskan dengan regresi linear.

G. Heatmap korelasi antar variabel yang berskala interval atau rasio.
# Korelasi
numeric_data <- data_heart[, sapply(data_heart, is.numeric)]
cor_matrix <- cor(numeric_data)

# Heatmap
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.3.3
## corrplot 0.95 loaded
corrplot(cor_matrix, method = "color", type = "upper", tl.cex = 0.8)

Berdasarkan heatmap di atas, terlihat bahwa sebagian besar variabel memiliki korelasi yang rendah satu sama lain yang ditunjukkan oleh warna yang mendekati putih. Namun, ada beberapa hubungan yang cukup mencolok, seperti korelasi negatif antara thalach (detak jantung maksimal) dan age, serta antara exang (angina akibat olahraga) dengan thalach, yang ditunjukkan dengan warna biru muda ke merah muda. Sementara itu, variabel oldpeak memiliki korelasi negatif yang cukup kuat dengan slope, dan korelasi positif sedang dengan exang. Korelasi paling kuat (positif maupun negatif) tampaknya tidak mendekati ±1, yang menandakan tidak ada multikolinearitas yang ekstrem di antara variabel-variabel tersebut.

H. Summary hasil analisis yang telah dilakukan. Hal-hal yang dapat mencegah penyakit jantung dan aspek apa saja yang merupakan indikasi penyakit jantung.
  • Berdasarkan visualisasi sebelumnya diketahui bahwa laki-laki lebih berisiko mengalami penyakit jantung.
  • Detak jantung maksimum menurun seiring bertambahnya usia.
  • Gula darah tinggi dan jenis nyeri dada tertentu berkaitan erat dengan penyakit jantung.
  • Usia 50–60 tahun merupakan rentang usia paling rentan dengan penyakit jantung.

Berikut Pencegahannya :
- Mulai rutin cek tekanan darah, kolesterol, dan gula darah baik melalui puskesmas ataupun rumah sakit.
- Menerapkan pola hidup sehat dan aktif secara fisik seperti berolahraga.
- Melakukan pemeriksaan kesehatan jantung secara berkala.

2. Buat diagram yang sama dengan contoh. Serta jelaskan maksud setiap dari bagian sintax tersebut. Kemudian interpretasikan.

# Load library
library(ggplot2)
library(scales)
## Warning: package 'scales' was built under R version 4.3.3
# Membuat data
data <- data.frame(
  Konsumsi_GWh = c(
    10, 20, 30, 50, 70, 90,
    40, 80, 120, 200, 300, 400,
    15, 25, 35, 50, 70,
    5, 10, 15, 20, 25, 30, 40
  ),
  Biaya_per_kWh = c(
    1500, 1450, 1400, 1350, 1300, 1250,
    1300, 1250, 1200, 1150, 1100, 1050,
    1600, 1550, 1500, 1450, 1400,
    1700, 1600, 1550, 1500, 1450, 1400, 1350
  ),
  Konsumen = factor(c(
    rep("Rumah Tangga", 6),
    rep("Industri", 6),
    rep("Kantor Pemerintah", 5),
    rep("UMKM", 7)
  ))
)

# Membuat grafik
ggplot(data, aes(x = Konsumsi_GWh, y = Biaya_per_kWh, color = Konsumen)) +
  geom_point(size = 3) +
  geom_smooth(method = "lm", se = FALSE) +
  labs(
    title = "Biaya Listrik per kWh Menurun Seiring Kenaikan Konsumsi",
    x = "Total Konsumsi Listrik (GWh)",
    y = "Biaya per kWh (Rupiah)",
    caption = "Data simulasi untuk keperluan edukasi"
  ) +
  scale_y_continuous(labels = label_number(suffix = " Rp", big.mark = ".", decimal.mark = ",")) +
  scale_x_log10(
    breaks = c(10, 30, 100, 300),  # Atur titik X seperti contoh
    labels = label_number(big.mark = ".", decimal.mark = ",")
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
    axis.title.x = element_text(size = 12),
    axis.title.y = element_text(size = 12),
    plot.caption = element_text(hjust = 1, size = 8, face = "italic"),
    legend.title = element_blank()
  )
## `geom_smooth()` using formula = 'y ~ x'

Penjelasan Sintaks
  1. Library library(ggplot2) → Untuk membuat grafik. library(scales) → Untuk memformat angka (misal menambah “Rp” di Y-axis).

  2. Data data.frame(…) → Membuat tabel data berisi: Konsumsi_GWh: konsumsi listrik (sumbu X). Biaya_per_kWh: biaya listrik per kWh (sumbu Y). Konsumen: jenis konsumen (untuk membedakan warna titik).

  3. Grafik Dasar ggplot(data, aes(x = …, y = …, color = …)) → Menentukan data apa yang diplot: x: konsumsi listrik. y: biaya listrik. color: membedakan jenis konsumen.

  4. Elemen Grafik geom_point(size = 3) → Menambahkan titik-titik data, ukuran 3. geom_smooth(method = “lm”, se = FALSE) → Menambahkan garis trend (regresi linear), tanpa area bayangan.

  5. Judul dan Label labs(title = …, x = …, y = …, caption = …) → Menambahkan: Judul grafik. Nama sumbu X. Nama sumbu Y. Keterangan/caption di bawah grafik.

  6. Format Sumbu Y scale_y_continuous(labels = label_number(suffix = ” Rp”, big.mark = “.”, decimal.mark = “,”)) → Format angka Y-axis. Tambahkan satuan “Rp”. Gunakan titik (.) untuk pemisah ribuan.

  7. Format Sumbu X (Log Skala) scale_x_log10(breaks = c(10, 30, 100, 300)) → Gunakan skala logaritmik di X. Tentukan titik angka di X: 10, 30, 100, 300.

  8. Tema Grafik theme_minimal() → Menggunakan tema minimalis untuk grafik. theme(…) → Pengaturan tambahan: plot.title: posisi dan ukuran judul. axis.title.x/y: ukuran teks judul sumbu. plot.caption: posisi dan gaya caption. legend.title = element_blank(): menghilangkan judul legenda.

Interpretasi

Grafik menunjukkan bahwa biaya listrik per kWh menurun seiring meningkatnya total konsumsi listrik, berdasarkan data simulasi untuk empat kategori: Industri, Kantor Pemerintah, Rumah Tangga, dan UMKM.

Sektor Industri memiliki konsumsi tertinggi dengan tarif per kWh terendah, sementara UMKM menunjukkan konsumsi paling rendah dan tarif tertinggi. Kantor Pemerintah dan Rumah Tangga berada di antara keduanya, mengikuti tren serupa.

Pola ini mencerminkan prinsip skala ekonomi, di mana pengguna dengan konsumsi besar mendapat tarif lebih murah. Ini bisa menjadi strategi tarif yang mendorong efisiensi atau mendukung sektor prioritas.