1. Lakukan visualisasi yang efektif untuk menjawab
pertanyaan berikut tuliskan informasi tentang variabel (pengertian dari
variabel tersebut, skala data variabel), sintag, output yang dihasilkan
serta interpretasi.
A. Melakukan Pengecekan terhadap data
- Nilai yang hilang (missing values)
data <- read.csv("C:/Users/User/Downloads/heart_psd.csv")
colSums(is.na(data))
## 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
- Data yang tercatat ganda (duplicate records)
data <- read.csv("C:/Users/User/Downloads/heart_psd.csv")
sum(duplicated(data))
## [1] 1
#menghapus agar analisis tidak bias
data <- data[!duplicated(data), ]
- Nilai ekstrim (outlier) pada variabel numerik
data <- read.csv("C:/Users/User/Downloads/heart_psd.csv")
num_vars <- sapply(data, is.numeric)
numeric_data <- data[, num_vars]
# Buat layout boxplot
boxplot(numeric_data, main = "Boxplot Variabel Numerik", las = 2, col = "skyblue", outline = FALSE)
# Tambahkan outlier secara manual dengan warna merah
for (i in 1:ncol(numeric_data)) {
outliers <- boxplot.stats(numeric_data[[i]])$out
x_pos <- rep(i, length(outliers))
points(x_pos, outliers, col = "red", pch = 16)
}

- Menangani Kesalahan
# Contoh menangani outlier dengan winsorizing (memotong ujung distribusi)
data <- read.csv("C:/Users/User/Downloads/heart_psd.csv")
# Fungsi untuk menghapus outlier berdasarkan IQR
remove_outliers <- function(data, variable) {
Q1 <- quantile(data[[variable]], 0.25)
Q3 <- quantile(data[[variable]], 0.75)
IQR_value <- Q3 - Q1
lower_bound <- Q1 - 1.5 * IQR_value
upper_bound <- Q3 + 1.5 * IQR_value
cleaned_data <- data[data[[variable]] >= lower_bound & data[[variable]] <= upper_bound, ]
return(cleaned_data)
}
# Menghapus outlier pada kolom chol
data_clean <- remove_outliers(data, "chol")
# Menghapus outlier pada kolom trestbps dari data yang sudah dibersihkan chol-nya
data_clean <- remove_outliers(data_clean, "trestbps")
# Melihat dimensi data sebelum dan sesudah
cat("Sebelum: ", nrow(data), "baris\n")
## Sebelum: 303 baris
cat("Sesudah: ", nrow(data_clean), "baris\n")
## Sesudah: 289 baris
- Statistika Deskriptif
# Deskriptif statistik
summary(numeric_data)
## age sex cp trestbps
## Min. :29.00 Min. :0.0000 Min. :0.000 Min. : 94.0
## 1st Qu.:47.50 1st Qu.:0.0000 1st Qu.:0.000 1st Qu.:120.0
## Median :55.00 Median :1.0000 Median :1.000 Median :130.0
## Mean :54.37 Mean :0.6832 Mean :0.967 Mean :131.6
## 3rd Qu.:61.00 3rd Qu.:1.0000 3rd Qu.:2.000 3rd Qu.:140.0
## Max. :77.00 Max. :1.0000 Max. :3.000 Max. :200.0
## chol fbs restecg thalach
## Min. :126.0 Min. :0.0000 Min. :0.0000 Min. : 71.0
## 1st Qu.:211.0 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:133.5
## Median :240.0 Median :0.0000 Median :1.0000 Median :153.0
## Mean :246.3 Mean :0.1485 Mean :0.5281 Mean :149.6
## 3rd Qu.:274.5 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:166.0
## Max. :564.0 Max. :1.0000 Max. :2.0000 Max. :202.0
## exang oldpeak slope ca
## Min. :0.0000 Min. :0.00 Min. :0.000 Min. :0.0000
## 1st Qu.:0.0000 1st Qu.:0.00 1st Qu.:1.000 1st Qu.:0.0000
## Median :0.0000 Median :0.80 Median :1.000 Median :0.0000
## Mean :0.3267 Mean :1.04 Mean :1.399 Mean :0.7294
## 3rd Qu.:1.0000 3rd Qu.:1.60 3rd Qu.:2.000 3rd Qu.:1.0000
## Max. :1.0000 Max. :6.20 Max. :2.000 Max. :4.0000
## thal target
## Min. :0.000 Min. :0.0000
## 1st Qu.:2.000 1st Qu.:0.0000
## Median :2.000 Median :1.0000
## Mean :2.314 Mean :0.5446
## 3rd Qu.:3.000 3rd Qu.:1.0000
## Max. :3.000 Max. :1.0000
Penanganan data dilakukan untuk memastikan analisis berjalan akurat
dan tidak bias. Pemeriksaan awal menunjukkan tidak ada missing values,
sehingga tidak diperlukan imputasi data. Namun, ditemukan data duplikat
yang dihapus agar tidak mempengaruhi hasil analisis statistik. Untuk
outlier, penanganan dilakukan dengan metode IQR (Interquartile Range)
karena efektif menghapus nilai-nilai ekstrem tanpa mengubah distribusi
utama data. Outlier dihapus khususnya pada kolom chol dan trestbps
karena nilai ekstrem di kolom ini bisa mengganggu hasil rata-rata dan
standar deviasi.Berdasarkan hasil analisis deskriptif data numerik
setelah dilakukan pembersihan, dapat disimpulkan secara singkat sebagai
berikut: Rata-rata usia pasien adalah 54 tahun, dengan usia termuda 29
tahun dan tertua 77 tahun. Tekanan darah (trestbps) berkisar antara
94–200 mmHg, dengan rata-rata 131 mmHg. Kadar kolesterol (chol) memiliki
nilai maksimum cukup tinggi yaitu 564 mg/dL, meskipun rata-ratanya 246
mg/dL. Detak jantung maksimal (thalach) memiliki rata-rata 149 bpm,
dengan maksimum 202 bpm. Variabel fbs (indikator gula darah >120
mg/dL) didominasi oleh nilai 0 (normal), begitu juga dengan exang
(angina akibat latihan). Variabel oldpeak (depresi ST) menunjukkan
rata-rata 1.04, dengan nilai ekstrem tertinggi 6.2, menandakan adanya
beberapa kasus depresi ST berat. Untuk variabel kategorikal numerik
seperti cp (jenis nyeri dada), restecg (hasil EKG istirahat), slope, ca,
dan thal, nilai yang dominan umumnya adalah 0 atau 1, dengan cp memiliki
nilai maksimum 3 dan ca hingga 4, menandakan variasi dalam jumlah
pembuluh darah besar yang terlibat. Variabel target (target) menunjukkan
bahwa sekitar 54% pasien mengalami penyakit jantung.
C. Lakukan analisis untuk mengetahui, apakah kadar gula
darah seseorang yang lebih besar dari 120 paling banyak mengalami Heart
desease?
# Crosstab fbs dan target
table_fbs_target <- table(data$fbs, data$target)
prop.table(table_fbs_target, 1)
##
## 0 1
## 0 0.4496124 0.5503876
## 1 0.4888889 0.5111111
# Visualisasi
library(ggplot2)
ggplot(data, aes(x = factor(fbs), fill = factor(target))) +
geom_bar(position = "fill") +
labs(title = "Proporsi Heart Disease berdasarkan Kadar Gula Darah",
x = "Gula Darah (0 = Normal, 1 = >120 mg/dl)",
y = "Proporsi",
fill = "Heart Disease")

D. Lakukan identifikasi untuk mengetahui jenis nyeri dada
yang paling banyak terjadi pada seseorang mengalami Heart
desease.
# Filter hanya pasien yang terkena heart disease
heart_data <- subset(data, target == 1)
# Plot tipe nyeri dada
ggplot(heart_data, aes(x = factor(cp))) +
geom_bar(fill = "tomato") +
labs(title = "Tipe Nyeri Dada pada Penderita Heart Disease",
x = "Tipe Nyeri Dada (cp)", y = "Jumlah")

E. Buat visualisasi Bar plot proporsi heart desease terhadap
variabel kategorikal cp, ca, dan thal. Interpretasikan.
# Plot 1: cp
data$target <- factor(data$target)
ggplot(data, aes(x = factor(cp), fill = target)) +
geom_bar(position = "fill") +
scale_fill_manual(values = c("#FF6F61", "#6BAED6")) + # Warna custom
scale_y_continuous(labels = scales::percent) +
labs(title = "Proporsi Heart Disease berdasarkan Tipe Nyeri Dada (cp)",
x = "Tipe Nyeri Dada", y = "Proporsi", fill = "Heart Disease") +
theme_minimal()

Variabel cp menggambarkan jenis nyeri dada yang dirasakan pasien,
yang terbagi menjadi beberapa tipe (biasanya dikodekan dari 0 hingga 3).
Berdasarkan hasil visualisasi, terlihat bahwa jenis nyeri dada tipe 1
dan 2 memiliki proporsi lebih tinggi terhadap penderita penyakit jantung
(target = 1) dibandingkan tipe lainnya. Sebaliknya, tipe 0 menunjukkan
proporsi yang lebih tinggi untuk pasien tanpa penyakit jantung (target =
0). Hal ini menunjukkan bahwa jenis nyeri dada tertentu memiliki
keterkaitan kuat dengan kemungkinan adanya penyakit jantung, sehingga
dapat menjadi indikator penting dalam diagnosis.
#Plot 2 : Ca
ggplot(data, aes(x = factor(ca), fill = target)) +
geom_bar(position = "fill") +
scale_fill_manual(values = c("#FDCB6E", "#00B894")) +
scale_y_continuous(labels = scales::percent) +
labs(title = "Proporsi Heart Disease berdasarkan Jumlah Pembuluh (ca)",
x = "Jumlah Pembuluh", y = "Proporsi", fill = "Heart Disease") +
theme_minimal()

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)
# Pastikan 'target' adalah faktor agar jadi kategori
data$target <- factor(data$target, labels = c("Tidak Sakit", "Sakit"))
# Visualisasi scatter plot dengan garis regresi
ggplot(data, aes(x = age, y = thalach, color = target)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "loess", se = FALSE, size = 1.2) +
labs(title = "Hubungan antara Age dan Thalach berdasarkan Kondisi Jantung",
x = "Usia (age)", y = "Detak Jantung Maksimum (thalach)", color = "Penyakit Jantung") +
theme_minimal() +
scale_color_manual(values = c("#0984e3", "#d63031"))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
## `geom_smooth()` using formula = 'y ~ x'

Berdasarkan hasil visualisasi scatter plot dengan garis tren LOESS
(Local Regression), terlihat bahwa hubungan antara usia (age) dan detak
jantung maksimum (thalach) bersifat non-linear. Untuk kedua kelompok
(baik yang menderita penyakit jantung maupun yang tidak), tren
menunjukkan bahwa semakin bertambah usia, nilai thalach cenderung
menurun. Namun, pola penurunannya tidak membentuk garis lurus (linear),
melainkan melengkung, yang khas dari hubungan non-linear. Untuk pasien
yang memiliki penyakit jantung (target = 1), garis tren cenderung lebih
rendah dibandingkan pasien yang tidak sakit, menunjukkan bahwa detak
jantung maksimum mereka lebih rendah di hampir semua rentang usia. Arah
hubungan antara age dan thalach adalah negatif (semakin tua, thalach
semakin rendah). Hubungan tersebut bersifat non-linear, yang dapat
dilihat dari pola lengkung pada garis LOESS.Kita dapat mengetahuinya
dengan menggunakan visualisasi scatter plot dan melihat pola garis
regresi LOESS, yang dirancang untuk mengungkap pola non-linear antar
variabel numerik.
G. Buat heatmap korelasi antar variabel yang berskala
interval atau rasio kemudian interpretasukan hasil yang
didapat
library(corrplot)
## corrplot 0.95 loaded
# Pilih hanya variabel interval/rasio
num_vars <- c("age", "trestbps", "chol", "thalach", "oldpeak")
numeric_data <- data[, num_vars]
# Hitung matriks korelasi
cor_matrix <- cor(numeric_data, use = "complete.obs")
# Buat heatmap korelasi
corrplot(cor_matrix,
method = "color",
type = "upper",
order = "hclust",
tl.col = "black",
addCoef.col = "black",
number.cex = 0.8,
title = "Heatmap Korelasi Variabel Interval/Rasio",
mar = c(0,0,1,0))

Berdasarkan heatmap korelasi variabel interval/rasio, terlihat
sejumlah hubungan yang dapat diinterpretasikan secara klinis. Variabel
thalach (denyut jantung maksimum) memiliki korelasi negatif sedang
dengan oldpeak (r = -0.34), menunjukkan bahwa semakin tinggi kemampuan
jantung mencapai detak maksimum, semakin rendah depresi segmen-ST yang
dialami—menandakan kondisi jantung yang lebih baik. Thalach juga
berkorelasi negatif lemah dengan age (r = -0.40), mengindikasikan bahwa
usia yang lebih tua cenderung memiliki kemampuan detak jantung maksimum
yang lebih rendah. Korelasi thalach dengan chol (kolesterol) sangat
lemah dan negatif (r = -0.01), serta dengan trestbps (tekanan darah
istirahat) juga sangat lemah (r = -0.05), yang berarti hampir tidak ada
hubungan antara thalach dan kedua variabel tersebut. Selanjutnya,
variabel chol memiliki korelasi positif sangat lemah dengan oldpeak (r =
0.05), age (r = 0.21), dan trestbps (r = 0.12), yang menunjukkan bahwa
kadar kolesterol cenderung sedikit meningkat seiring bertambahnya usia
dan tekanan darah, meskipun hubungannya lemah. Sementara itu, oldpeak
berkorelasi positif lemah dengan age (r = 0.21) dan trestbps (r = 0.19),
yang menunjukkan bahwa orang yang lebih tua atau memiliki tekanan darah
lebih tinggi cenderung mengalami depresi ST yang lebih besar saat uji
beban. Variabel age memiliki korelasi positif lemah dengan trestbps (r =
0.28), artinya semakin tua seseorang, tekanan darah istirahat cenderung
sedikit lebih tinggi. Hubungan ini mendukung pemahaman bahwa penuaan
sering diiringi peningkatan tekanan darah. Terakhir, semua variabel
memiliki korelasi sempurna dengan dirinya sendiri (r = 1.00),
sebagaimana yang ditunjukkan pada diagonal utama heatmap.
2. Dari data berikut, Buat diagram yang sama dengan contoh.
Serta jelaskan maksud setiap dari bagian sintag tersebut. Kemudian
interpretasikan.
library(ggplot2) # Memuat library ggplot2 untuk membuat grafik
data <- data.frame( # Membuat data frame berisi 3 kolom: Konsumsi, Biaya, dan jenis Konsumen
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 = c(rep("Rumah Tangga",6), rep("Industri",6),
rep("Kantor Pemerintah",5), rep("UMKM",7))
) # Kolom 'Konsumen' diisi berulang sesuai kelompok
ggplot(data, aes(x = Konsumsi_GWh, y = Biaya_per_kWh, color = Konsumen)) + # Membuat plot awal dengan x = konsumsi, y = biaya, dan warna berdasar konsumen
geom_point() + # Menambahkan titik-titik (scatter plot) untuk masing-masing observasi
geom_smooth(method = "lm", se = FALSE) + # Menambahkan garis tren regresi linier (tanpa area kepercayaan)
labs(
title = "Biaya Listrik per kWh Menurun Seiring Kenaikan Konsumsi", # Judul grafik
x = "Total Konsumsi Listrik (GWh)", # Label sumbu X
y = "Biaya per kWh (Rupiah)", # Label sumbu Y
caption = "Data simulasi untuk keperluan edukasi" # Keterangan tambahan di bawah grafik
) +
theme_minimal() # Tema visual sederhana & bersih untuk grafik
## `geom_smooth()` using formula = 'y ~ x'

Intrepertasinya : Dari diagram di atas, terlihat jelas bahwa
terdapat hubungan terbalik antara total konsumsi listrik dan biaya per
kWh untuk berbagai jenis konsumen. Pada kelompok Rumah Tangga, biaya per
kWh menurun secara bertahap dari Rp 1500 saat konsumsi 10 GWh menjadi Rp
1250 saat konsumsi mencapai 90 GWh. Untuk sektor Industri, biaya per kWh
cenderung lebih rendah dibandingkan kelompok lain, berkisar antara Rp
1300 pada konsumsi 40 GWh hingga menyentuh angka Rp 1050 pada konsumsi
400 GWh, menunjukkan penurunan yang signifikan dengan peningkatan
penggunaan listrik. Kantor Pemerintah menunjukkan tren serupa, dengan
biaya per kWh menurun dari Rp 1600 pada konsumsi 15 GWh menjadi Rp 1400
pada konsumsi 70 GWh. Menariknya, kelompok UMKM memiliki biaya per kWh
tertinggi di antara semua kategori, dimulai dari Rp 1700 pada konsumsi 5
GWh dan menurun menjadi Rp 1350 pada konsumsi 40 GWh, meskipun tarifnya
tetap yang paling tinggi pada tingkat konsumsi yang sebanding dengan
kelompok lain. Secara keseluruhan, diagram ini memperkuat gagasan bahwa
semakin tinggi total konsumsi listrik, semakin rendah biaya per unit
listrik yang harus dibayarkan oleh konsumen, meskipun dengan tingkat
tarif dan penurunan yang berbeda untuk setiap kategori.