UTS PENGANTAR SAINS DATA A

1. Melakukan Visualisasi menggunakan data Heart

A. Melakukan pengecekan data/data cleaning
df <- read.csv("C:/Users/Asus/Downloads/heart.csv")

head(df)
##   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(df)
## '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. Cek missing values
cat("Jumlah missing values per kolom:\n")
## Jumlah missing values per kolom:
colSums(is.na(df))
##      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
library(dplyr)
## 
## 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
# 2. Cek duplikat dan tangani
duplicate_rows <- df[duplicated(df), ]
cat("Jumlah baris duplikat:", nrow(duplicate_rows), "\n")
## Jumlah baris duplikat: 1
# Menghapus duplikat
df_clean <- df[!duplicated(df), ]
# 3. Deteksi outlier dengan 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))
}

outlier_counts <- sapply(df_clean[, sapply(df_clean, is.numeric)], detect_outliers)
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
# 4. Analisis statistik deskriptif untuk variabel numerik
cat("\nStatistik deskriptif:\n")
## 
## Statistik deskriptif:
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 banyakmengalami 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)
# Visualisasi Jenis Kelamin yang Mengalami Heart Disease

df_clean$sex <- factor(df_clean$sex, labels = c("Perempuan", "Laki-laki"))
df_clean$target <- factor(df_clean$target, labels = c("Tidak", "Ya"))

ggplot(df_clean %>% filter(target == "Ya"), aes(x = sex)) +
  geom_bar(fill = "tomato") +
  labs(title = "Jenis Kelamin yang Mengalami Heart Disease",
       x = "Jenis Kelamin", y = "Jumlah")

# Visualisasi Usia yang Paling Banyak Mengalami 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")

# 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")

C. Lakukan analisis untuk mengetahui, apakah kadar gula darah seseorang yang lebih besar dari 120 paling banyak mengalami Heart desease?
# Tambah label kategorik untuk fbs dan target
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 berdasarkan kombinasi fbs dan target
fbs_heart_table <- df_clean %>%
  group_by(fbs_label, target_label) %>%
  summarise(jumlah = n(), .groups = 'drop')

# Tampilkan tabel
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
ggplot(fbs_heart_table, aes(x = fbs_label, y = jumlah, fill = target_label)) +
  geom_bar(stat = "identity", position = "dodge") +
  labs(title = "Perbandingan Heart Disease Berdasarkan Kadar Gula Darah",
       x = "Kadar Gula Darah", y = "Jumlah",
       fill = "Heart Disease") +
  scale_fill_manual(values = c("tomato", "skyblue")) +
  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" = "skyblue", "Ya" = "tomato")) +
    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. Eksplorasi hubungan antara age dan thalach, dibedakan berdasarkan heart disease. Apakah hubungan linear atau non-linear?
# 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 mengetahui hubungan antara usia (age) dan denyut jantung maksimum (thalach), dilakukan visualisasi menggunakan scatter plot dengan tambahan garis tren linier. Dari plot tersebut, terlihat bahwa semakin bertambah usia seseorang, nilai thalach cenderung menurun, yang mengindikasikan adanya hubungan negatif antara usia dan detak jantung maksimum. Untuk memperkuat temuan ini, dilakukan analisis korelasi Pearson yang menunjukkan nilai korelasi negatif, yang berarti semakin tua usia, semakin rendah denyut jantung maksimumnya. Selain itu, model regresi linier sederhana juga digunakan untuk memodelkan hubungan ini. Hasil dari model tersebut menunjukkan bahwa variabel usia memiliki koefisien negatif yang signifikan secara statistik, yang menegaskan bahwa usia berbanding terbalik dengan nilai thalach. Dengan demikian, dapat disimpulkan bahwa terdapat hubungan negatif yang signifikan antara usia dan denyut jantung maksimum pada data yang dianalisis.

G. Heatmap korelasi antar variabel interval dan interpretasi
library(reshape2)

# 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. Summary hasil analisis dan pencegahan 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.

2. Melakukan Visualisasi menggunakan data

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) dan biaya per kWh pada berbagai jenis konsumen menunjukkan pola yang konsisten, yaitu semakin tinggi konsumsi listrik, semakin rendah biaya per kWh yang dibayarkan.
- Pada segmen rumah tangga, terlihat bahwa pelanggan dengan konsumsi listrik tinggi cenderung membayar tarif listrik per kWh yang lebih rendah dibandingkan dengan pelanggan yang konsumsi listriknya rendah.
- Pola serupa juga terlihat pada sektor industri, di mana industri dengan konsumsi besar menikmati tarif listrik yang lebih murah. Hal ini dapat mengindikasikan adanya kebijakan tarif khusus atau insentif dari pemerintah bagi pelaku industri untuk mendorong produksi dan efisiensi energi.
- Segmen kantor pemerintahan juga menunjukkan kecenderungan yang sama, meskipun jumlah data yang tersedia tidak sebanyak segmen lainnya, sehingga perlu kehati-hatian dalam menarik kesimpulan lebih lanjut.
- Sementara itu, pada UMKM, terlihat bahwa semakin tinggi konsumsi listrik, semakin rendah pula biaya per kWh yang harus dibayar, yang dapat mencerminkan adanya dukungan tarif bagi pelaku usaha kecil.
- Secara keseluruhan, visualisasi ini menggambarkan adanya korelasi negatif antara konsumsi dan biaya listrik per kWh di semua segmen konsumen, yang mengindikasikan kebijakan tarif berbasis volume konsumsi. Meskipun strategi ini menguntungkan bagi konsumen besar, perlu dipertimbangkan dampaknya terhadap efisiensi energi dan keadilan tarif antar segmen pengguna.