data<- read.csv("D:/Data UTS PSD A/heart.csv")
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 ...
A. Cek dan Tangani Missing Value, Duplikat, Outlier + Stat Deskriptif
# Cek missing value per kolom
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
# Cek dan hapus duplikat
sum(duplicated(data))
## [1] 1
df_clean <- data[!duplicated(data), ]
# Fungsi untuk mendeteksi outlier (metode IQR)
detect_outliers <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
sum(x < (Q1 - 1.5 * IQR) | x > (Q3 + 1.5 * IQR))
}
# Hitung jumlah outlier pada setiap kolom numerik
outlier_counts <- sapply(df_clean[, sapply(df_clean, is.numeric)], detect_outliers)
# Tampilkan jumlah outlier
cat("\nJumlah outlier per kolom numerik:\n")
##
## Jumlah outlier per kolom numerik:
print(outlier_counts)
## 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
# Statistik deskriptif kolom numerik
summary(df_clean[, sapply(df_clean, 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. Lakukan visualisasi untuk menunjukkan jenis kelamin apa yang paling banyak mengalami Heart desease, dan usia berapa yang paling banyak mengalami heart desease,dan usia berapa yang memiliki gula darah lebih besar dari 120 mg/dl.
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.4.3
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.4.2
##
## 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
# Ubah kolom kategori ke factor
df_clean$sex <- factor(df_clean$sex, levels = c(0,1), labels = c("Perempuan", "Laki-laki"))
df_clean$target <- factor(df_clean$target, levels = c(0,1), labels = c("Tidak", "Ya"))
# Visualisasi Usia yang Paling Banyak Mengalami Heart Disease
ggplot(df_clean %>% filter(target == "Ya"), aes(x = sex)) +
geom_bar(fill = "red", color = "black") +
labs(title = "Jenis Kelamin yang Mengalami Heart Disease",
x = "Jenis Kelamin", y = "Jumlah") +
theme_minimal()
# Visualisasi Usia Penderita Heart Disease
ggplot(df_clean %>% filter(target == "Ya"), aes(x = age)) +
geom_histogram(binwidth = 1, fill = "skyblue", color = "black") +
labs(title = "Distribusi Usia Penderita Heart Disease",
x = "Usia", y = "Jumlah") +
theme_minimal()
# Visualisasi Usia dengan Kadar Gula Darah > 120 mg/dL
ggplot(df_clean %>% filter(fbs == 1), aes(x = age)) +
geom_histogram(binwidth = 1, fill = "purple", color = "white") +
labs(title = "Distribusi Usia dengan Gula Darah > 120 mg/dL",
x = "Usia", y = "Jumlah") +
theme_minimal()
C. Lakukan analisis untuk mengetahui, apakah kadar gula darah seseorang yang lebih besar dari 120 paling banyak mengalami Heart desease?
# Pastikan library dplyr dan ggplot2 sudah dimuat
library(dplyr)
library(ggplot2)
# Pastikan kembali target dalam bentuk karakter
df_clean <- df_clean %>%
mutate(
fbs_label = ifelse(fbs == 1, ">120 mg/dL", "<=120 mg/dL"),
target_label = ifelse(target == "Ya", "Heart Disease", "Tidak")
)
# Hitung jumlah kombinasi fbs dan target
fbs_heart_table <- df_clean %>%
group_by(fbs_label, target_label) %>%
summarise(jumlah = n(), .groups = "drop")
# Tampilkan tabel hasil
print(fbs_heart_table)
## # A tibble: 4 × 3
## fbs_label target_label jumlah
## <chr> <chr> <int>
## 1 <=120 mg/dL Heart Disease 141
## 2 <=120 mg/dL Tidak 116
## 3 >120 mg/dL Heart Disease 23
## 4 >120 mg/dL Tidak 22
# Visualisasi barplot
ggplot(fbs_heart_table, aes(x = fbs_label, y = jumlah, fill = target_label)) +
geom_bar(stat = "identity", position = position_dodge()) +
labs(title = "Distribusi Heart Disease Berdasarkan Kadar Gula Darah",
x = "Kadar Gula Darah", y = "Jumlah",
fill = "Status Penyakit") +
scale_fill_manual(values = c("Heart Disease" = "yellow", "Tidak" = "blue")) +
theme_minimal()
D. Lakukan identifikasi untuk mengetahui jenis nyeri dada yang paling banyak terjadi pada seseorang mengalami Heart desease
# Label untuk jenis nyeri dada (chest pain)
# 0 = Typical angina
# 1 = Atypical angina
# 2 = Non-anginal pain
# 3 = Asymptomatic
df_clean <- df_clean %>%
mutate(
cp_label = factor(cp,
levels = c(0, 1, 2, 3),
labels = c("Typical angina", "Atypical angina", "Non-anginal pain", "Asymptomatic"))
)
# Hitung jumlah masing-masing jenis nyeri dada pada penderita heart disease
chest_pain_count <- df_clean %>%
filter(target == "Ya") %>%
group_by(cp_label) %>%
summarise(jumlah = n(), .groups = 'drop') %>%
arrange(desc(jumlah))
# Tampilkan tabel
chest_pain_count
## # A tibble: 4 × 2
## cp_label jumlah
## <fct> <int>
## 1 Non-anginal pain 68
## 2 Atypical angina 41
## 3 Typical angina 39
## 4 Asymptomatic 16
# Visualisasi jenis nyeri dada pada penderita heart disease
ggplot(chest_pain_count, aes(x = reorder(cp_label, -jumlah), y = jumlah, fill = cp_label)) +
geom_bar(stat = "identity") +
labs(title = "Jenis Nyeri Dada pada Penderita Heart Disease",
x = "Jenis Nyeri Dada", y = "Jumlah") +
theme_minimal() +
theme(legend.position = "none")
E. Buat visualisasi Bar plot proporsi heart desease terhadap variabel kategorikal cp, ca, dan thal. Interpretasikan.
library(scales)
# Label kategori cp sudah dibuat sebelumnya (cp_label), kita pakai ulang
# Ubah label faktor untuk ca dan thal agar lebih informatif
df_clean$ca <- factor(df_clean$ca,
levels = c(0, 1, 2, 3, 4),
labels = c("0", "1", "2", "3", "4"))
df_clean$thal <- factor(df_clean$thal,
levels = c(0, 1, 2),
labels = c("Normal", "Fixed Defect", "Reversible Defect"))
# Fungsi untuk membuat barplot proporsi
plot_proporsi <- function(var, title_var) {
ggplot(df_clean, aes_string(x = var, fill = "target")) +
geom_bar(position = "fill") +
scale_y_continuous(labels = percent) +
labs(title = paste("Proporsi Heart Disease berdasarkan", title_var),
x = title_var, y = "Proporsi", fill = "Heart Disease") +
scale_fill_manual(values = c("Tidak" = "blue", "Ya" = "yellow")) +
theme_minimal()
}
# Plot untuk cp, ca, dan thal
plot_proporsi("cp_label", "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 heart disease berdasarkan variabel cp (jenis nyeri dada) menunjukkan bahwa sebagian besar penderita penyakit jantung berada pada kategori Asymptomatic (tidak merasakan nyeri dada). Hal ini menunjukkan bahwa seseorang yang tidak memiliki keluhan nyeri dada khas pun tetap berisiko tinggi mengidap penyakit jantung. Sebaliknya, mereka yang mengalami Typical angina atau Atypical angina justru cenderung tidak memiliki penyakit jantung, yang mungkin disebabkan oleh nyeri dada yang tidak berasal dari jantung.
plot_proporsi("ca", "Jumlah Pembuluh yang Diwarnai (ca)")
variabel ca (jumlah pembuluh darah utama yang terlihat pada angiografi), terlihat bahwa semakin sedikit jumlah pembuluh darah yang terlihat (ca = 0), semakin besar proporsi penderita penyakit jantung. Hal ini dapat mengindikasikan bahwa tidak terlihatnya pembuluh darah bisa jadi menunjukkan adanya penyumbatan atau kerusakan yang signifikan, sehingga meningkatkan risiko penyakit jantung. Sebaliknya, semakin banyak pembuluh yang terlihat (ca = 1 hingga 3), proporsi penderita jantung menurun, menandakan kondisi pembuluh darah yang lebih baik
plot_proporsi("thal", "Hasil Tes Thalassemia (thal)")
variabel thal (hasil tes thalassemia), ditemukan bahwa kategori Reversible Defect memiliki proporsi penderita heart disease yang paling tinggi. Hal ini menunjukkan bahwa defek reversibel—yang muncul saat tes stres—adalah indikator kuat adanya gangguan jantung. Sebaliknya, pada kategori Normal, proporsi penderita jantung jauh lebih rendah, menunjukkan bahwa hasil tes thal yang normal berhubungan erat dengan kondisi jantung yang sehat.
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?.
# Scatter plot biasa hubungan age vs thalach
# Scatter plot dengan garis tren linier
ggplot(df_clean, aes(x = age, y = thalach, color = target)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE) +
labs(title = "Hubungan antara Usia dan Denyut Jantung Maksimum (thalach)",
x = "Usia", y = "Thalach (detak jantung maksimum)",
color = "Heart Disease") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Untuk menganalisis keterkaitan antara usia (age) dan denyut jantung maksimum (thalach), dilakukan visualisasi dalam bentuk scatter plot yang dilengkapi dengan garis tren linier. Visualisasi tersebut memperlihatkan pola penurunan nilai thalach seiring bertambahnya usia, yang mengindikasikan adanya hubungan negatif antara kedua variabel tersebut. Temuan ini kemudian diperkuat dengan analisis korelasi Pearson, yang menghasilkan nilai korelasi negatif, menandakan bahwa semakin lanjut usia seseorang, semakin rendah denyut jantung maksimum yang dapat dicapainya. Selain itu, analisis regresi linier sederhana juga diterapkan untuk menggambarkan hubungan ini secara kuantitatif. Hasil model menunjukkan bahwa usia memiliki koefisien regresi negatif yang signifikan secara statistik, menegaskan bahwa usia berpengaruh secara terbalik terhadap nilai thalach. Berdasarkan hasil visualisasi dan analisis statistik tersebut, dapat disimpulkan bahwa terdapat hubungan negatif yang signifikan antara usia dan denyut jantung maksimum pada data yang dianalisis.
G. Buat heatmap korelasi antar variabel yang berskala interval atau rasio kemudian interpretasukan hasil yang didapat.
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.4.3
# Ambil variabel numerik
numeric_vars <- df_clean %>%
select_if(is.numeric)
# Korelasi
cor_matrix <- cor(numeric_vars, use = "complete.obs")
# Visualisasi heatmap
ggplot(melt(cor_matrix), aes(Var1, Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) +
labs(title = "Heatmap Korelasi Antar Variabel Numerik",
x = "", y = "", fill = "Korelasi") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
Heatmap tersebut menunjukkan korelasi antar variabel numerik dalam data kesehatan jantung. Beberapa korelasi yang menonjol adalah hubungan negatif antara thalach (detak jantung maksimum) dan age (usia), serta antara slope dan oldpeak, yang menunjukkan hubungan terbalik yang cukup kuat. Selain itu, cp (nyeri dada) berkorelasi positif dengan thalach dan negatif dengan exang (angina akibat olahraga). Sebaliknya, variabel seperti fbs dan restecg menunjukkan korelasi lemah atau hampir tidak ada dengan variabel lainnya. Hal ini menunjukkan bahwa tidak semua variabel memiliki hubungan yang signifikan dan beberapa bisa lebih berpengaruh dalam analisis atau pemodelan data.
H. Buat summary hasil analisis yang telah dilakukan. Menurut kalian apa apa saja hal-hal yang dapat mencegah penyakit jantung dan aspek apa saja yang merupakan indikasi penyakit jantung.
Berdasarkan eksplorasi data kesehatan jantung yang dilakukan,
berikut ringkasan hasil analisis:
- Pembersihan Data: Tidak ditemukan nilai hilang, dan duplikat berhasil
dihapus. Beberapa outlier terdeteksi namun tidak langsung
dihilangkan.
- Jenis Kelamin: Laki-laki lebih banyak mengalami penyakit jantung
dibandingkan perempuan.
- Usia: Rentang usia sekitar 50–60 tahun paling banyak mengalami
penyakit jantung dan memiliki kadar gula darah >120 mg/dL.
- Gula Darah: Sebagian besar penderita penyakit jantung justru memiliki
kadar gula darah ≤120 mg/dL, artinya kadar gula tinggi bukan faktor
utama dalam dataset ini.
- Nyeri Dada (cp): Penderita heart disease paling banyak berada di
kategori Asymptomatic, menunjukkan bahwa meski tanpa gejala nyeri dada
khas, risiko tetap tinggi.
- Pembuluh Darah (ca): Semakin sedikit pembuluh darah yang terlihat
(terutama ca = 0), semakin tinggi proporsi penderita heart
disease.
- Thalassemia (thal): Hasil tes “Reversible Defect” paling banyak
dialami oleh penderita heart disease.
- Hubungan Usia dan Thalach: Terdapat hubungan negatif yang cukup
jelas—semakin tua usia, semakin rendah denyut jantung maksimum.
- Heatmap Korelasi: Terlihat beberapa korelasi signifikan, seperti
antara usia dan thalach (negatif), serta cp dan thalach (positif).
Pencegahan Penyakit Jantung Berdasarkan hasil di atas,
beberapa langkah pencegahan yang dapat diambil:
- Rutin cek kesehatan, termasuk tes thalassemia dan pengecekan pembuluh
darah.
- Menjaga kebugaran jantung dengan olahraga teratur agar thalach tetap
optimal, terutama seiring bertambahnya usia.
- Waspadai risiko meski tanpa gejala: Banyak penderita tidak mengalami
nyeri dada klasik.
- Pantau tekanan darah, kadar kolesterol dan gaya hidup meski kadar gula
normal.
- Manajemen stres dan pola makan sehat juga penting untuk menjaga
kondisi jantung.
Buat diagram yang sama dengan contoh. Serta jelaskan maksud setiap dari bagian sintax tersebut
# 1. Input 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 = c(rep("Rumah Tangga", 6),
rep("Industri", 6),
rep("Kantor Pemerintah", 5),
rep("UMKM", 7))
)
# 2. Visualisasi dengan ggplot2 + garis regresi
library(ggplot2)
ggplot(data, aes(x = Konsumsi_GWh, y = Biaya_per_kWh, color = Konsumen)) +
geom_point(size = 3) +
geom_smooth(method = "lm", se = FALSE, linewidth = 1) + # Tambahan garis linear per grup
labs(
title = "Hubungan Konsumsi Listrik dan Biaya per kWh",
x = "Konsumsi (GWh)",
y = "Biaya per kWh (Rp)"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Penjelasan Sintaks:
- data.frame(…): Membuat tabel data dengan tiga kolom: Konsumsi, Biaya,
dan Jenis Konsumen.
- rep(…): Mengulang nama jenis konsumen sesuai banyaknya data
masing-masing kategori.
- library(ggplot2): Memanggil package ggplot2 untuk visualisasi.
- ggplot(data, aes(…)): Membuat objek grafik dari data dengan estetika
dasar:
x = Konsumsi_GWh: sumbu x adalah konsumsi energi.
y = Biaya_per_kWh: sumbu y adalah biaya.
- color = Konsumen: membedakan warna berdasarkan jenis konsumen.
- geom_point(size = 3): Membuat titik-titik berukuran 3.
- labs(…): Menambahkan judul dan label sumbu.
- theme_minimal(): Menggunakan tema bersih dan minimal.
- geom_smooth(method = “lm”, se = FALSE): Menambahkan garis regresi
linear tanpa area standar deviasi.
Interpretasi
Visualisasi hubungan antara konsumsi listrik (dalam GWh) dengan biaya
per kWh pada berbagai segmen konsumen menunjukkan pola yang konsisten,
yaitu semakin besar konsumsi listrik, semakin rendah tarif yang
dikenakan per kWh. Pada segmen rumah tangga, misalnya, pelanggan dengan
konsumsi tinggi cenderung menikmati tarif listrik yang lebih rendah
dibandingkan mereka yang konsumsi listriknya relatif kecil. Tren serupa
juga ditemukan pada sektor industri, di mana perusahaan dengan kebutuhan
energi besar tampaknya mendapatkan keuntungan dari tarif yang lebih
ekonomis. Hal ini dapat mencerminkan adanya kebijakan insentif atau
skema tarif khusus dari pemerintah untuk mendukung produktivitas dan
efisiensi energi di sektor tersebut. Di sisi lain, kantor-kantor
pemerintahan juga menunjukkan kecenderungan serupa, meskipun data yang
tersedia pada segmen ini terbatas sehingga interpretasinya perlu
dilakukan secara hati-hati. Untuk kelompok UMKM, semakin tinggi konsumsi
listrik, semakin rendah pula biaya per kWh yang dikenakan, yang
kemungkinan besar mencerminkan bentuk dukungan tarif terhadap pelaku
usaha kecil. Secara keseluruhan, visualisasi ini mengindikasikan adanya
hubungan negatif antara volume konsumsi dan tarif listrik per kWh di
seluruh kategori pengguna. Meskipun pendekatan tarif berbasis volume ini
menguntungkan konsumen dengan konsumsi besar, penting untuk
mempertimbangkan dampaknya terhadap efisiensi energi dan aspek keadilan
tarif antar segmen pengguna.