library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.3.3
data <- read.csv("D:/Kuliah Semester 4/PSD/heart.csv")
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 ...
ggplot(data, aes(x = factor(target), y = chol, fill = factor(target))) +
geom_boxplot() +
labs(x = "Status Penyakit Jantung (0 = Tidak, 1 = Ya)",
y = "Kadar Kolesterol (mg/dl)",
title = "Distribusi Kolesterol berdasarkan Status Penyakit Jantung") +
theme_minimal()
Interpretasi: Median kadar kolestrol pada penderita penyakit jantung sedikit lebih rendah dibanding yang tidak sakit. Kedua kelompok punya sebaran data yang mirip dan sama-sama memiliki outliner(kolesterol tinggi). Tidak ada perbedaan mencolok, jadi kolesterol bukan satu-satunya indikator kuat penyakit jantung dalam data ini.
data <- read.csv("D:/Kuliah Semester 4/PSD/heart.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 <- read.csv("D:/Kuliah Semester 4/PSD/heart.csv")
sum(duplicated(data))
## [1] 1
#menghapus agar analisis tidak bias
data <- data[!duplicated(data), ]
data <- read.csv("D:/Kuliah Semester 4/PSD/heart.csv")
num_vars <- sapply(data, is.numeric)
numeric_data <- data[, num_vars]
# Boxplot untuk melihat outlier
boxplot(numeric_data, main = "Boxplot Variabel Numerik", las = 2)
# Contoh menangani outlier dengan winsorizing (memotong ujung distribusi)
data <- read.csv("D:/Kuliah Semester 4/PSD/heart.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
# 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
library(ggplot2)
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.3.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
data$sex <- factor(data$sex, labels = c("Perempuan", "Laki-laki"))
ggplot(data %>% filter(target == 1), aes(x = sex)) +
geom_bar(fill = "tomato") +
labs(title = "Jumlah Penderita Penyakit Jantung Berdasarkan Jenis Kelamin",
x = "Jenis Kelamin",
y = "Jumlah Kasus")
ggplot(data %>% filter(target == 1), aes(x = age)) +
geom_histogram(binwidth = 2, fill = "steelblue", color = "black") +
labs(title = "Distribusi Usia Penderita Penyakit Jantung",
x = "Usia",
y = "Jumlah")
ggplot(data %>% filter(fbs == 1), aes(x = age)) +
geom_histogram(binwidth = 2, fill = "darkgreen", color = "black") +
labs(title = "Distribusi Usia dengan Gula Darah > 120 mg/dl",
x = "Usia",
y = "Jumlah")
data$fbs_tabel <- factor(data$fbs, labels = c("≤ 120 mg/dl", "> 120 mg/dl"))
data$target_tabel <- factor(data$target, labels = c("Tidak", "Ya"))
table_fbs <- table(data$fbs_tabel, data$target_tabel)
print(table_fbs)
##
## Tidak Ya
## ≤ 120 mg/dl 116 142
## > 120 mg/dl 22 23
prop_fbs <- prop.table(table_fbs, 1)
print(round(prop_fbs, 2))
##
## Tidak Ya
## ≤ 120 mg/dl 0.45 0.55
## > 120 mg/dl 0.49 0.51
#Visualisasi perbandingan
library(ggplot2)
ggplot(data, aes(x = fbs_tabel, fill = target_tabel)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent_format()) +
labs(title = "Proporsi Heart Disease berdasarkan Kadar Gula Darah",
x = "Kadar Gula Darah",
y = "Proporsi",
fill = "Heart Disease")
data$cp_tabel <- factor(data$cp,
levels = c(0,1,2,3),
labels = c("Typical angina",
"Atypical angina",
"Non-anginal pain",
"Asymptomatic"))
data$target_tabel <- factor(data$target, labels = c("Tidak", "Ya"))
table_cp <- table(data$cp_tabel, data$target_tabel)
print(table_cp)
##
## Tidak Ya
## Typical angina 104 39
## Atypical angina 9 41
## Non-anginal pain 18 69
## Asymptomatic 7 16
# Visualisasi
library(ggplot2)
ggplot(subset(data, target == 1), aes(x = cp_tabel)) +
geom_bar(fill = "#E74C3C") +
labs(title = "Jenis Nyeri Dada pada Penderita Penyakit Jantung",
x = "Jenis Nyeri Dada",
y = "Jumlah Penderita")
# Label untuk variabel kategorikal
data$target_tabel <- factor(data$target, labels = c("Tidak", "Ya"))
data$cp <- factor(data$cp, labels = c("Typical angina", "Atypical angina", "Non-anginal pain", "Asymptomatic"))
data$thal <- factor(data$thal, labels = c("Unknown", "Fixed defect", "Normal", "Reversible defect"))
data$ca <- as.factor(data$ca)
#cp
library(ggplot2)
ggplot(data, aes(x = cp, fill = target_tabel)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent) +
labs(title = "Proporsi Heart Disease berdasarkan Jenis Nyeri Dada (cp)",
x = "Jenis Nyeri Dada", y = "Proporsi", fill = "Heart Disease") +
theme_minimal()
#ca
ggplot(data, aes(x = ca, fill = target_tabel)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent) +
labs(title = "Proporsi Heart Disease berdasarkan Jumlah Pembuluh Darah (ca)",
x = "Jumlah Pembuluh Darah", y = "Proporsi", fill = "Heart Disease") +
theme_minimal()
#thal
ggplot(data, aes(x = thal, fill = target_tabel)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent) +
labs(title = "Proporsi Heart Disease berdasarkan Tipe Thalassemia (thal)",
x = "Tipe Thalassemia", y = "Proporsi", fill = "Heart Disease") +
theme_minimal()
Interpretasi - cp: Kelompok Atypical angina memiliki proporsi terbesar yang mengalami penyakit jantung. Dan Typical angina lebih banyak pada kelompok yang tidak memiliki penyakit jantung - ca: Makin banyak pembuluh darah (ca = 2 atau 3), proporsi penderita penyakit jantung cenderung lebih rendah. Pembuluh darah 0 dan 4 memiliki proporsi lebih tinggi terkena penyakit jantung -thal: Kondisi Normal cenderung memiliki proporsi tertinggi terkena penyakit jantung. Dan kondisi Reversible defect lebih banyak ditemukan pada yang tidak mengalami penyakit jantung
library(ggplot2)
data$target_tabel <- factor(data$target, labels = c("Tidak", "Ya"))
ggplot(data, aes(x = age, y = thalach, color = target_tabel)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "lm", se = FALSE) + # linear trend
labs(title = "Hubungan antara Age dan Thalach berdasarkan Heart Disease",
x = "Usia (age)", y = "Detak Jantung Maksimal (thalach)",
color = "Heart Disease") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
#Uji Korelasi
# Korelasi keseluruhan
cor(data$age, data$thalach)
## [1] -0.3985219
# Korelasi terpisah
cor(data$age[data$target == 1], data$thalach[data$target == 1]) # Penderita
## [1] -0.5258007
cor(data$age[data$target == 0], data$thalach[data$target == 0]) # Non-penderita
## [1] -0.1327507
# Menentukan Linier atau Non-Linier
# Tambahkan tren non-linear (LOESS)
ggplot(data, aes(x = age, y = thalach, color = target_tabel)) +
geom_point(alpha = 0.6) +
geom_smooth(method = "loess", se = FALSE) + # untuk mendeteksi pola non-linear
labs(title = "Hubungan non-linear Age dan Thalach berdasarkan Heart Disease",
x = "Usia", y = "Detak Jantung Maksimal") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
selected_data <- data[, c("chol", "trestbps")]
cor_matrix <- cor(selected_data, use = "complete.obs")
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.3.3
## corrplot 0.95 loaded
# Buat heatmap
corrplot(cor_matrix, method = "color", addCoef.col = "black",
tl.col = "black", title = "Korelasi chol dan trestbps",
mar = c(0,0,1,0), type = "upper")
Interpretasi: Nilai korelasi antara chol dan trestbps adalah 0.12 . Nilai ini berada dekat 0 yang mengartikan bahwa hubungan antara kadar kolestrol dan tekanan darah sengat lemah dan hampir tidak ada korelasi linier diantara keduanya
Hal-hal yang dapat mencegah penyakit jantung: - Menjaga tekanan darah (trestbps) dalam batas normal - Menjaga berat badan dan kolesterol (chol) stabil - Rutin berolahraga → meningkatkan thalach (kapasitas detak jantung maksimum) - Menghindari rokok dan pola makan tinggi lemak - Menjaga kadar gula darah (fbs) dengan pola makan sehat
Aspek apa saja yang merupakan indikasi penyakit jantung: - Jenis kelamin laki-laki - Usia di atas 50 tahun - Jenis nyeri dada tertentu seperti asymptomatic atau non-anginal - Jumlah pembuluh darah (ca) yang mengalami penyumbatan - Kelainan pada thalassemia (thal) - Detak jantung maksimum (thalach) yang rendah
library(ggplot2)
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))
)
# Buat scatter plot dengan garis regresi linier per kategori
ggplot(data, aes(x = Konsumsi_GWh, y = Biaya_per_kWh, color = Konsumen)) +
geom_point() + # Titik-titik data
geom_smooth(method = "lm", se = FALSE) + # Garis regresi tanpa area kepercayaan
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"
) +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
Syntax - geom_point(): Membuat titik-titik scatter untuk setiap data. - geom_smooth(method = “lm”, se = FALSE): Membuat garis regresi linier untuk setiap kelompok konsumen, tanpa area kepercayaan (confidence interval). - color = Konsumen: Mewarnai titik dan garis berdasarkan kategori konsumen. - theme_minimal(): Tema grafik bersih dan minimalis.
Interpretasi Garis tren untuk semua kategori menurun, yang artinya: Semakin tinggi konsumsi listrik, maka biaya per kWh semakin rendah — hal ini menunjukkan adanya diskon tarif berdasarkan volume penggunaan (biasanya diberikan ke industri besar). Industri memiliki tren biaya per kWh yang paling rendah untuk konsumsi tinggi.