# Memuat data dari file CSV
data <- read.csv("C:/Users/fikri/Downloads/heart.csv")
# Tampilkan beberapa baris pertama dan struktur data
head(data)
## 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)
## '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 ...
# 1. Pemeriksaan missing values
cat("Total nilai hilang pada tiap kolom:\n")
## Total nilai hilang pada tiap kolom:
print(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
# 2. Identifikasi dan hapus data duplikat
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.3
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
duplikat <- data[duplicated(data), ]
cat("Banyaknya baris yang duplikat:", nrow(duplikat), "\n")
## Banyaknya baris yang duplikat: 1
# Menghapus baris yang duplikat
data_bersih <- data %>% distinct()
# 3. Fungsi deteksi outlier menggunakan IQR
hitung_outlier <- function(col) {
Q1 <- quantile(col, 0.25, na.rm = TRUE)
Q3 <- quantile(col, 0.75, na.rm = TRUE)
rentang_IQR <- Q3 - Q1
jumlah <- sum(col < (Q1 - 1.5 * rentang_IQR) | col > (Q3 + 1.5 * rentang_IQR))
return(jumlah)
}
# Hitung outlier untuk kolom numerik
outlier_per_kolom <- sapply(select_if(data_bersih, is.numeric), hitung_outlier)
cat("\nJumlah nilai outlier pada tiap variabel numerik:\n")
##
## Jumlah nilai outlier pada tiap variabel numerik:
print(outlier_per_kolom)
## 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 24 2 0
# 4. Statistik deskriptif untuk data numerik
cat("\nRingkasan statistik deskriptif:\n")
##
## Ringkasan statistik deskriptif:
summary(select_if(data_bersih, 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
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
# Ubah kolom 'sex' dan 'target' menjadi faktor dengan label yang lebih deskriptif
data_bersih$sex <- factor(data_bersih$sex, labels = c("Perempuan", "Laki-laki"))
data_bersih$target <- factor(data_bersih$target, labels = c("Tidak", "Ya"))
# Grafik: Perbandingan jenis kelamin pada penderita penyakit jantung
ggplot(data_bersih %>% filter(target == "Ya"), aes(x = sex)) +
geom_bar(fill = "red") +
labs(title = "Jumlah Penderita Penyakit Jantung Berdasarkan Jenis Kelamin",
x = "Jenis Kelamin", y = "Total")
# Grafik: Distribusi usia penderita penyakit jantung
ggplot(data_bersih %>% filter(target == "Ya"), aes(x = age)) +
geom_histogram(binwidth = 1, fill = "yellow", color = "black") +
labs(title = "Sebaran Usia Penderita Penyakit Jantung",
x = "Umur", y = "Jumlah Kasus")
# Grafik: Distribusi usia dengan gula darah puasa > 120 mg/dL
ggplot(data_bersih %>% filter(fbs == 1), aes(x = age)) +
geom_histogram(binwidth = 1, fill = "green", color = "white") +
labs(title = "Usia Pasien dengan Gula Darah > 120 mg/dL",
x = "Usia", y = "Frekuensi")
# Menambahkan kolom label untuk kadar gula darah dan status penyakit jantung
data_bersih <- data_bersih %>%
mutate(
label_fbs = ifelse(fbs == 1, ">120 mg/dL", "<=120 mg/dL"),
label_target = ifelse(target == "Ya", "Penyakit Jantung", "Tidak")
)
# Menghitung jumlah observasi berdasarkan kategori fbs dan target
tabel_gula_jantung <- data_bersih %>%
group_by(label_fbs, label_target) %>%
summarise(total = n(), .groups = 'drop')
# Menampilkan hasil tabulasi
tabel_gula_jantung
## # A tibble: 4 × 3
## label_fbs label_target total
## <chr> <chr> <int>
## 1 <=120 mg/dL Penyakit Jantung 141
## 2 <=120 mg/dL Tidak 116
## 3 >120 mg/dL Penyakit Jantung 23
## 4 >120 mg/dL Tidak 22
# Membuat grafik batang berdasarkan data gabungan fbs dan target
ggplot(tabel_gula_jantung, aes(x = label_fbs, y = total, fill = label_target)) +
geom_bar(stat = "identity", position = "dodge") +
labs(title = "Distribusi Penyakit Jantung Berdasarkan Gula Darah Puasa",
x = "Kategori Gula Darah", y = "Jumlah Kasus",
fill = "Status Jantung") +
scale_fill_manual(values = c("red", "green")) +
theme_minimal()
# Menambahkan label kategorik untuk jenis nyeri dada
# 0: Typical angina, 1: Atypical angina, 2: Non-anginal pain, 3: Asymptomatic
data_bersih <- data_bersih %>%
mutate(
jenis_cp = factor(cp,
levels = c(0, 1, 2, 3),
labels = c("Typical angina", "Atypical angina", "Non-anginal pain", "Asymptomatic"))
)
# Menghitung jumlah kasus heart disease berdasarkan jenis nyeri dada
jumlah_nyeri_dada <- data_bersih %>%
filter(target == "Ya") %>%
group_by(jenis_cp) %>%
summarise(total = n(), .groups = 'drop') %>%
arrange(desc(total))
# Menampilkan tabel hasil
jumlah_nyeri_dada
## # A tibble: 4 × 2
## jenis_cp total
## <fct> <int>
## 1 Non-anginal pain 68
## 2 Atypical angina 41
## 3 Typical angina 39
## 4 Asymptomatic 16
# Visualisasi distribusi jenis nyeri dada pada penderita penyakit jantung
ggplot(jumlah_nyeri_dada, aes(x = reorder(jenis_cp, -total), y = total, fill = jenis_cp)) +
geom_col() +
labs(title = "Distribusi Jenis Nyeri Dada pada Pasien Penyakit Jantung",
x = "Kategori Nyeri Dada", y = "Jumlah Kasus") +
theme_minimal() +
theme(legend.position = "none")
library(scales)
# Konversi nilai pada kolom 'ca' menjadi faktor dengan label yang deskriptif
data_bersih$ca <- factor(data_bersih$ca,
levels = c(0, 1, 2, 3, 4),
labels = c("0", "1", "2", "3", "4"))
# Konversi nilai pada kolom 'thal' menjadi faktor dengan nama kategori yang jelas
data_bersih$thal <- factor(data_bersih$thal,
levels = c(0, 1, 2),
labels = c("Normal", "Fixed Defect", "Reversible Defect"))
# Fungsi untuk membuat grafik batang proporsi berdasarkan variabel kategori tertentu
buat_plot_proporsi <- function(kolom, judul) {
ggplot(data_bersih, aes_string(x = kolom, fill = "target")) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent) +
labs(title = paste("Persentase Penyakit Jantung Berdasarkan", judul),
x = judul, y = "Proporsi", fill = "Status") +
scale_fill_manual(values = c("Tidak" = "red", "Ya" = "green")) +
theme_minimal()
}
# Membuat grafik untuk kategori: jenis nyeri dada, jumlah pembuluh yang diwarnai, dan hasil thalassemia
buat_plot_proporsi("jenis_cp", "Jenis Nyeri Dada (cp)")
## Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
## ℹ Please use tidy evaluation idioms with `aes()`.
## ℹ See also `vignette("ggplot2-in-packages")` for more information.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Visualisasi proporsi penyakit jantung berdasarkan variabel cp (jenis
nyeri dada) menunjukkan bahwa sebagian besar pasien penyakit jantung
termasuk dalam kategori Asymptomatic (tanpa nyeri dada). Ini menunjukkan
bahwa individu yang tidak mengalami keluhan nyeri dada khas tetap
memiliki risiko tinggi terkena penyakit jantung. Sebaliknya, individu
yang mengalami Typical angina atau Atypical angina cenderung tidak
menderita penyakit jantung, kemungkinan karena nyeri dada yang tidak
berasal dari jantung.
buat_plot_proporsi("ca", "Jumlah Pembuluh Darah (ca)")
Variabel ca (jumlah pembuluh darah utama yang tampak pada angiografi)
menunjukkan bahwa semakin sedikit jumlah pembuluh darah yang terpantau
(ca = 0), semakin tinggi proporsi penderita penyakit jantung. Hal ini
bisa mengindikasikan bahwa tidak adanya pembuluh darah mungkin
mencerminkan adanya penyumbatan atau kerusakan yang serius, yang dapat
meningkatkan risiko penyakit jantung. Sebaliknya, semakin banyak
pembuluh yang tampak (ca = 1 hingga 3), proporsi pasien jantung
berkurang, menunjukkan keadaan pembuluh darah yang lebih optimal.
buat_plot_proporsi("thal", "Hasil Pemeriksaan Thalassemia (thal)")
Variabel thal (hasil tes thalassemia) menunjukkan bahwa kategori
Reversible Defect memiliki proporsi pasien penyakit jantung tertinggi.
Hal ini mengindikasikan bahwa defek yang dapat reversibel—yang terjadi
saat pengujian stres—merupakan tanda kuat adanya masalah pada jantung.
Sebaliknya, dalam kategori Normal, jumlah penderita jantung sangat jauh
lebih sedikit, mengindikasikan bahwa hasil tes thal yang normal
berkaitan erat dengan kesehatan jantung yang baik.
# Scatter plot antara usia dan denyut jantung maksimum, dilengkapi garis regresi linier
ggplot(data_bersih, aes(x = age, y = thalach, color = target)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE) +
labs(title = "Korelasi Usia dan Detak Jantung Maksimal (thalach)",
x = "Usia Pasien", y = "Detak Jantung Maksimum (Thalach)",
color = "Status Jantung") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Untuk memahami hubungan antara usia (age) dan denyut jantung maksimum
(thalach), dilakukan analisis visual melalui scatter plot yang
dilengkapi dengan garis tren linier. Dari grafik tersebut, tampak bahwa
seiring bertambahnya usia individu, nilai thalach cenderung mengalami
penurunan, yang menunjukkan adanya hubungan negatif antara usia dan
denyut jantung maksimum. Untuk mendukung temuan ini, telah dilakukan
analisis korelasi Pearson yang menunjukkan nilai korelasi negatif, yang
menyiratkan bahwa semakin tua usia, semakin rendah denyut jantung
maksimum yang dimiliki. Selain itu, regresi linier sederhana juga
digunakan untuk memodelkan hubungan ini. Hasil dari model itu
menunjukkan bahwa variabel usia memiliki koefisien negatif yang
signifikan secara statistik, yang menegaskan bahwa usia berbanding
terbalik dengan nilai thalach. Dengan begitu, dapat disimpulkan bahwa
ada hubungan negatif yang signifikan antara usia dan denyut jantung
maksimum dalam data yang diteliti.
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.4.3
# Menyaring hanya kolom dengan tipe numerik
variabel_numerik <- data_bersih %>%
select_if(is.numeric)
# Membuat matriks korelasi
matriks_korelasi <- cor(variabel_numerik, use = "complete.obs")
# Visualisasi heatmap dari korelasi antar variabel numerik
ggplot(melt(matriks_korelasi), aes(x = Var1, y = Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "red", high = "green", mid = "white", midpoint = 0) +
labs(title = "Peta Korelasi Variabel Numerik",
x = NULL, y = NULL, fill = "Nilai Korelasi") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Peta panas tersebut menggambarkan hubungan antara variabel numerik dalam
data kesehatan jantung. Beberapa korelasi yang signifikan adalah
hubungan negatif antara thalach (denyut jantung maksimum) dan age
(usia), serta antara slope dan oldpeak, yang menunjukkan hubungan
terbalik yang cukup kuat. Selain itu, cp (nyeri dada) memiliki hubungan
positif dengan thalach dan hubungan negatif dengan exang (angina yang
disebabkan oleh aktivitas fisik). Sebaliknya, variabel seperti fbs dan
restecg menunjukkan hubungan yang lemah atau hampir tidak ada dengan
variabel lain. Ini menunjukkan bahwa tidak semua variabel memiliki
hubungan yang signifikan, dan beberapa mungkin memiliki pengaruh yang
lebih besar dalam analisis atau pemodelan data.
Berdasarkan kajian data kesehatan jantung yang telah dilakukan, berikut adalah ringkasan hasil analisis:
- Pembersihan Data: Nilai hilang tidak terdeteksi, dan duplikat telah berhasil dihapus. Terdeteksi beberapa outlier, tetapi tidak segera dihapus.
Jenis Kelamin: Pria lebih sering mengalami penyakit jantung dibandingkan wanita.
Usia: Kelompok usia sekitar 50–60 tahun paling banyak menderita penyakit jantung dan memiliki kadar gula darah >120 mg/dL.
Gula Darah: Mayoritas pasien penyakit jantung justru menunjukkan kadar gula darah ≤120 mg/dL, yang menunjukkan bahwa kadar gula tinggi bukanlah faktor utama dalam kumpulan data ini.
Nyeri Dada (cp): Mayoritas penderita penyakit jantung tergolong dalam kategori Asymptomatic, yang menunjukkan bahwa meski tidak menunjukkan gejala nyeri dada khas, risikonya tetap tinggi.
- Pembuluh Darah (ca): Semakin sedikit pembuluh darah yang nampak (khususnya ca = 0), semakin besar proporsi pasien penyakit jantung.
- Thalassemia (thal): Hasil uji "Reversible Defect" paling sering ditemukan pada penderita penyakit jantung.
- Hubungan Usia dan Thalach: Ada hubungan negatif yang terlihat jelas—semakin bertambah usia, semakin rendah denyut jantung maksimal.
- Peta Panas Korelasi: Terlihat adanya sejumlah korelasi signifikan, contohnya antara usia dan thalach (negatif), serta cp dan thalach (positif).
Pencegahan Penyakit Jantung
Berdasarkan hasil tersebut, ada beberapa langkah pencegahan yang bisa diambil:
- Melakukan pemeriksaan kesehatan rutin, seperti uji thalassemia dan pemeriksaan pembuluh darah.
- Mempertahankan kesehatan jantung melalui aktivitas fisik yang rutin supaya thalach tetap dalam kondisi baik, terutama seiring bertambahnya usia.
Hati-hati terhadap risiko meski tanpa tanda: Banyak pasien tidak merasakan nyeri dada yang khas.
- Awasi tekanan darah, tingkat kolesterol, dan pola hidup meskipun gula darah normal.
Pengelolaan stres dan pola makan yang seimbang juga krusial untuk mempertahankan kesehatan jantung.
# 1. Data awal
listrik_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),
Tarif_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),
Tipe_Konsumen = c(rep("Rumah Tangga", 6),
rep("Industri", 6),
rep("Instansi Pemerintah", 5),
rep("UMKM", 7))
)
# 2. Visualisasi scatter plot + garis tren linier per kategori
library(ggplot2)
ggplot(listrik_data, aes(x = Konsumsi_GWh, y = Tarif_kWh, color = Tipe_Konsumen)) +
geom_point(size = 3) +
geom_smooth(method = "lm", se = FALSE, linewidth = 1) +
labs(
title = "Korelasi antara Konsumsi dan Tarif Listrik",
x = "Jumlah Konsumsi (GWh)",
y = "Tarif Listrik per kWh (Rp)"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Penjelasan Sintaks: - data.frame(…): Membentuk tabel data yang terdiri
dari tiga kolom: Konsumsi, Biaya, dan Tipe Konsumen. - rep(…):
Mengulangi nama tipe konsumen berdasarkan jumlah data di setiap
kategori. - library(ggplot2): Mengaktifkan paket ggplot2 untuk tujuan
visualisasi. - ggplot(data, aes(…)): Menghasilkan objek visual dari data
dengan estetika utama: x = Konsumsi_GWh: sumbu x mewakili konsumsi
energi. y = Biaya_per_kWh: sumbu y mewakili pengeluaran. - warna =
Konsumen: membedakan warna sesuai kategori konsumen. - geom_point(size =
3): Menghasilkan titik-titik dengan ukuran 3. - labs(…): Menyisipkan
judul dan penanda sumbu. - theme_minimal(): Menerapkan tema yang
sederhana dan bersih. - geom_smooth(method = “lm”, se = FALSE):
Menambahkan garis regresi linier tanpa daerah deviasi standar.
Interpretasi Visualisasi keterkaitan antara pemakaian listrik (dalam
GWh) dan tarif per kWh pada berbagai kategori konsumen menunjukkan pola
yang seragam, yakni semakin besar pemakaian listrik, semakin kecil tarif
per kWh yang dibayarkan. Dalam segmen rumah tangga, tampak bahwa
pelanggan yang mengkonsumsi listrik dalam jumlah banyak cenderung
membayar tarif listrik per kWh yang lebih rendah dibandingkan pelanggan
yang mengkonsumsi listrik sedikit. - Pola yang sama juga tampak pada
sektor industri, di mana industri dengan penggunaan tinggi mendapatkan
tarif listrik yang lebih rendah. Ini dapat menunjukkan adanya kebijakan
tarif khusus atau insentif pemerintah bagi pelaku industri guna
mendorong produksi dan efisiensi energi. Segmen kantor pemerintahan juga
memperlihatkan kecenderungan serupa, meskipun jumlah data yang ada tidak
sebanyak segmen lain, sehingga dibutuhkan kehati-hatian dalam menarik
kesimpulan lebih lanjut. Sementara itu, di UMKM, tampak bahwa semakin
meningkat konsumsi listrik, semakin rendah biaya per kWh yang harus
dibayarkan, yang menunjukkan adanya bantuan tarif untuk pelaku usaha
kecil. Secara keseluruhan, visualisasi ini menunjukkan adanya hubungan
negatif antara konsumsi dan biaya listrik per kWh di seluruh segmen
konsumen, yang mengindikasikan kebijakan tarif yang didasarkan pada
volume konsumsi. Walaupun strategi ini menguntungkan bagi konsumen
besar, penting untuk mempertimbangkan efeknya terhadap efisiensi energi
serta keadilan tarif di antara berbagai segmen pengguna.