1.

# 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. 

2.

# 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.