1. Melakukan import dataset

data<- read.csv("C:/Users/LENOVO/Documents/PSD/heart.csv", header = TRUE, sep = ";")
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. Lakukan pengecekan apakah terdapat: Nilai yang hilang (missing values), Data yang tercatat ganda (duplicate records), Nilai ekstrim (outlier) pada variabel numerik. Jika ada masalah tersebut, lakukan penanganan yang sesuai. Jelaskan mengapa menggunakan penanganan tersebut. Setelah pembersihan data, lakukan analisis statistika deskriptif untuk semua variabel numberik.

data <- as.data.frame(data)

# Cek NA
sum(is.na(data))
## [1] 0
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 duplikat
sum(duplicated(data))
## [1] 1
duplikat <- data[duplicated(data) | duplicated(data, fromLast = TRUE),]

# Hapus duplikat
data1 <- data[!duplicated(data), ]

print(str(data1))
## 'data.frame':    302 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 ...
## NULL
# Fungsi untuk cek outlier
outlier <- function(x) {
  q1 <- quantile(x, 0.25, na.rm = TRUE)
  q3 <- quantile(x, 0.75, na.rm = TRUE)
  iqr <- q3 - q1
  x < (q1 - 1.5 * iqr) | x > (q3 + 1.5 * iqr)
}

numeric_data <- data1[sapply(data1, is.numeric)]
outlier_flags <- lapply(numeric_data, outlier)
outlier_df <- as.data.frame(outlier_flags)

# Hitung jumlah outlier per kolom
colSums(outlier_df, na.rm = TRUE)
##      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
# penanganan outlier dengan winsorizing
library(DescTools)
## Warning: package 'DescTools' was built under R version 4.3.3
data1$trestbps <- Winsorize(data1$trestbps)
data1$oldpeak <- Winsorize(data1$oldpeak)

# Ringkasan data
summary(data1)
##       age             sex               cp            trestbps    
##  Min.   :29.00   Min.   :0.0000   Min.   :0.0000   Min.   :108.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.1  
##  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.   :160.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.008   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.   :3.400   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

Terdapat beberapa outlier di variabel numerik, yaitu pada variabel trestbps, chol, thalach dan oldpeak. Untuk trestbps dapat dilakukan penanganan winsorizing karena nilai terlalu tinggi/rendah bisa berarti klinis dan winsorizing menjaga pengaruh esktrem tanpa membuang data. untuk variabel chol, outlier dipertahankan karena kolestrol tinggi merupakan indokator penyakit jantung sehingga penting. Untuk variabel thalach terdapat 1 outlier yang berarti bisa jadi penting sehingga data di pertahankan. Dan oldpeak diatas 3 biasanya sudah masuk kategorii abnormal dan dapat mengganggu model karna skala ekstrem serta nilai yang tinggu bisa bermakna risiko jantung, sehingga menanganinya dengan winsorizing agar adata tidak terbuang.

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.3.2
# Buat bar chart jenis kelamin vs penyakit jantung
ggplot(data1, aes(x = factor(sex), fill = factor(target))) +
  geom_bar(position = "dodge") +
  labs(x = "Jenis Kelamin (0 = Perempuan, 1 = Laki-laki)",
       fill = "Heart Disease (1 = Ada)") +
  ggtitle("Distribusi Heart Disease berdasarkan Jenis Kelamin")

ggplot(data1[data1$target == 1, ], aes(x = age)) +
  geom_histogram(binwidth = 5, fill = "skyblue", color = "black") +
  labs(x = "Usia", y = "Jumlah Kasus", title = "Usia Penderita Heart Disease")

#chart usia yang memiliki fbs>120
ggplot(data1[data1$fbs == 1, ], aes(x = age)) +
  geom_histogram(binwidth = 5, fill = "blue", color = "black") +
  labs(x = "Usia", y = "Jumlah", title = "Usia dengan Gula Darah > 120 mg/dL")

c. Lakukan analisis untuk mengetahui, apakah kadar gula darah seseorang yang lebih besar dari 120 paling banyak mengalami Heart desease?

data1$fbs_group <- ifelse(data1$fbs > 120, "High (>120)", "Normal (≤120)")

# Tabel kontingensi antara fbs_group dan target
table_fbs_target <- table(data1$fbs_group, data1$target)
print(table_fbs_target)
##                
##                   0   1
##   Normal (≤120) 138 164
# Hitung proporsi masing-masing
prop.table(table_fbs_target, margin = 1)
##                
##                         0         1
##   Normal (≤120) 0.4569536 0.5430464
# Visualisasi
library(ggplot2)
ggplot(data1, aes(x = fbs_group, fill = as.factor(target))) +
  geom_bar(position = "fill") +
  labs(
    title = "Proporsi Penyakit Jantung Berdasarkan Kadar Gula Darah",
    x = "Kategori Kadar Gula Darah",
    y = "Proporsi",
    fill = "Heart Disease (1 = Ya, 0 = Tidak)"
  ) +
  scale_y_continuous(labels = scales::percent_format()) +
  theme_minimal()

table_fbs <- table(data1$fbs, data1$target)
print(table_fbs)
##    
##       0   1
##   0 116 141
##   1  22  23
# Uji chi-square
chisq.test(table_fbs)
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  table_fbs
## X-squared = 0.092408, df = 1, p-value = 0.7611

d. Lakukan identifikasi untuk mengetahui jenis nyeri dada yang paling banyak terjadi pada seseorang mengalami Heart desease

library(ggplot2)
ggplot(data1, aes(x = factor(cp), fill = factor(target))) +
  geom_bar(position = "dodge") +
  labs(x = "Tipe Nyeri Dada (cp)", fill = "Heart Disease (1 = Ada)") +
  ggtitle("Distribusi Tipe Nyeri Dada dan Heart Disease")

e. Buat visualisasi Bar plot proporsi heart desease terhadap variabel kategorikal cp, ca, dan thal. Interpretasikan.

library(ggplot2)
#untuk cp
ggplot(data1, aes(x = factor(cp), fill = factor(target))) +
  geom_bar(position = "fill") +
  labs(title = "Proporsi Heart Disease berdasarkan Tipe Nyeri Dada",
       x = "Tipe Nyeri Dada (cp)", y = "Proporsi",
       fill = "Heart Disease")

#untuk ca
ggplot(data1, aes(x = factor(ca), fill = factor(target))) +
  geom_bar(position = "fill") +
  labs(title = "Proporsi Heart Disease berdasarkan Jumlah Pmebuluh Darah",
       x = "Jumlah Pembuluh Darah (ca)", y = "Proporsi",
       fill = "Heart Disease")

#untuk thal
ggplot(data1, aes(x = factor(thal), fill = factor(target))) +
  geom_bar(position = "fill") +
  labs(title = "Proporsi Heart Disease berdasarkan Nilai Thalium",
       x = "Nilai Thalium (thal)", y = "Proporsi",
       fill = "Heart Disease")

Untuk cp tipe = 1 banyak mengalami penyakit jantung dapat dilihat dari proporsi barplot yang berwarna biru lebih banyak dibandingkan dengan merah. dan cp = 3 terlihat proporsi warna biru lebih banyak dibandingkan merah ini berarti nyeri dada tidak selalu muncul meski ada penyakit jantung.

untuk ca, biasanya nilai ca semakin besar maka semakin menurunkan resiko penyakit jantung terbukti dengan ca = 0 memiliki banyak penderita jantung lalu semakin naik semakin menurun kecuali ca = 4 menandakan bahwa ada indikasi lain selain pembuluh darah yang dapat memicu penyakit jantung.

untuk thal, indikasi terkuat dan memiliki potensi besar terhadap penyakit jantung yaitu thal=2. untuk thal = 0 dapat terjadi kesalahan atau abnormal sehingga hasil yang didapat tidak pasti.

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(data1, aes(x = age, y = thalach, color = factor(target))) +
  geom_point(alpha = 0.7) +
  labs(color = "Heart Disease", x = "Usia", y = "Detak Jantung Maksimum") +
  ggtitle("Hubungan antara Usia dan Thalach berdasarkan Kondisi Jantung")

ggplot(data1, aes(x = age, y = thalach, color = factor(target))) +
  geom_point(alpha = 0.7) +
  geom_smooth(method = "loess", se = FALSE) +
  labs(color = "Heart Disease") +
  ggtitle("Cek Hubungan Linear/Non-Linear")
## `geom_smooth()` using formula = 'y ~ x'

jika garis melengkung maka non linear dan lurus maka linear. dari visualisasi di atas menungjukkan bahwa age dengan thalach memiliki hubunngan yang non linear.

g. Buat heatmap korelasi antar variabel yang berskala interval atau rasio kemudian interpretasukan hasil yang didapat

library(corrplot)
## Warning: package 'corrplot' was built under R version 4.3.3
## corrplot 0.95 loaded
# ambil data numerik
numeric_data <- data1[sapply(data1, is.numeric)]

# hitung korelasi
cor_matrix <- cor(numeric_data, use = "complete.obs")

# tampilkan heatmap
corrplot(cor_matrix, method = "color", addCoef.col = "black",
         tl.col = "black", number.cex = 0.7,
         title = "Heatmap Korelasi Variabel Numerik",
         mar = c(0,0,2,0))

Korelasi negatif lemah yang paling menonjol adalah antara exang dengan slope dan oldpeak dengan slope. yang artinya semakin besar nilai salah satu variabel akan menaikkan nilai dari variabel satunya. sedangkan untuk korelasi positif yang lemah yaitu target dengan cp, thalach dengan target, artinya adalah semakin naik nilai cp dan thalach merupakan indikasi memiliki penyakit jantung. sedangkan lainnya memiliki korelasi yang sangat lemah dan hampir tidak ada sehingga tidak memiliki hubungan yang kuat antar variabel.

h. kesimpulan:

Beberapa langkah pencegahan yang dapat diambil:

2. Dari data berikut, Buat diagram yang sama dengan contoh. Serta jelaskan maksud setiap dari bagian sintag tersebut. Kemudian interpretasikan.

data2<- 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("Rumah Tangga","Rumah Tangga","Rumah Tangga","Rumah Tangga","Rumah Tangga","Rumah Tangga", "Industri","Industri","Industri","Industri","Industri","Industri","Kantor Pemerintah","Kantor Pemerintah","Kantor Pemerintah","Kantor Pemerintah","Kantor Pemerintah","UMKM","UMKM","UMKM","UMKM","UMKM","UMKM","UMKM")
)

library(ggplot2)

ggplot(data2, aes(x = konsumsi_GWH, y = Biaya_per_KWH, color = Konsumen)) +
  geom_line(aes(group = Konsumen), linewidth = 1.2) +
  geom_point(size = 2) +
  labs(title = "Biaya Listrik per kWh Berdasarkan Segmen Konsumen",
       x = "Konsumsi Listrik (GWh)",
       y = "Biaya per kWh (Rp)",
       color = "Konsumen") +
  theme_minimal() 

a. sintag disetiap bagian: data.frame = membuat tabel data perkolom library(ggplot2) = memanggil package ggplot2 untuk visualisasi ggplot = untuk membuat objek grafik dari data dengan estetika dasar color = konsumen artinya, membedakan jenis konsumen dengan warna geom_line untuk membuat garisnya per jenis konsumen geom_point untuk membuat titik-titik pada garis labs untuk judul atau title sumbu x dan y agar lebih jelas variabelnya apa saja theme_minimal untuk tema apa yang digunakan pada visualisasi

b. Interpretasi