1. Pada data heart desease yang terdapat di link berikut : Data: https://www.kaggle.com/code/farzadnekouei/heart-disease-prediction/input. Lakukan visualisasi yang efektif untuk menjawab pertanyaan berikut tuliskan informasi tentang variabel (pengertian dari variabel tersebut, skala data variabel), sintag, output yang dihasilkan serta interpretasi.

Import data

library(readxl)
## Warning: package 'readxl' was built under R version 4.3.3
data <- read_excel("C:/Users/User/Downloads/heart.xlsx")
head(data)
## # A tibble: 6 × 14
##     age   sex    cp trestbps  chol   fbs restecg thalach exang oldpeak slope
##   <dbl> <dbl> <dbl>    <dbl> <dbl> <dbl>   <dbl>   <dbl> <dbl>   <dbl> <dbl>
## 1    63     1     3      145   233     1       0     150     0     2.3     0
## 2    37     1     2      130   250     0       1     187     0     3.5     0
## 3    41     0     1      130   204     0       0     172     0     1.4     2
## 4    56     1     1      120   236     0       1     178     0     0.8     2
## 5    57     0     0      120   354     0       1     163     1     0.6     2
## 6    57     1     0      140   192     0       1     148     0     0.4     1
## # ℹ 3 more variables: ca <dbl>, thal <dbl>, target <dbl>
  1. [Nilai 10] Lakukan pengecekan apakah terdapat:

Jika ada masalah tersebut, lakukan penanganan yang sesuai. Jelaskan mengapa menggunakan penanganan tersebut. Setelah pembersihan data, lakukan analisis statistika deskriptif untuk semua variabel numberik.

  1. [Nilai 10] 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.

  2. [Nilai 10] Lakukan analisis untuk mengetahui, apakah kadar gula darah seseorang yang lebih besar dari 120 paling banyak mengalami Heart desease?

  3. [Nilai 10] Lakukan identifikasi untuk mengetahui jenis nyeri dada yang paling banyak terjadi pada seseorang mengalami Heart desease

  4. [Nilai 10] Buat visualisasi Bar plot proporsi heart desease terhadap variabel kategorikal cp, ca, dan thal. Interpretasikan.

  5. [Nilai 10] 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?

  6. [Nilai 10] Buat heatmap korelasi antar variabel yang berskala interval atau rasio kemudian interpretasukan hasil yang didapat

  7. [Nilai 10] 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.

Jawaban 1 a

cat("Jumlah nilai yang hilang per kolom:\n")
## Jumlah nilai yang hilang 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
duplicate_rows <- data[duplicated(data), ]
cat("\nJumlah data duplikat:", nrow(duplicate_rows), "\n")
## 
## Jumlah data duplikat: 1
# Pilih kolom numerik
numeric_vars <- sapply(data, is.numeric)
numerics <- data[, numeric_vars]

# Deteksi outlier menggunakan IQR method
detect_outliers <- function(x) {
  Q1 <- quantile(x, 0.25, na.rm = TRUE)
  Q3 <- quantile(x, 0.75, na.rm = TRUE)
  IQR <- Q3 - Q1
  outliers <- which(x < (Q1 - 1.5 * IQR) | x > (Q3 + 1.5 * IQR))
  return(outliers)
}

# Tampilkan jumlah outlier per variabel
cat("\nOutlier per kolom:\n")
## 
## Outlier per kolom:
sapply(names(numerics), function(col) {
  length(detect_outliers(numerics[[col]]))
})
##      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       25        2        0

Penanganan yang sesuai

data_clean <- data  # buat salinan untuk data bersih
for (col in names(numerics)) {
  if (any(is.na(data_clean[[col]]))) {
    median_val <- median(data_clean[[col]], na.rm = TRUE)
    data_clean[[col]][is.na(data_clean[[col]])] <- median_val
  }
}

Penghapusan duplikat data

data_clean <- data_clean[!duplicated(data_clean), ]

Penghapusan Outlier

remove_outliers <- 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)
}

for (col in names(numerics)) {
  data_clean <- data_clean[remove_outliers(data_clean[[col]]), ]
}

Analisis Statistika Deskriptif

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
library(psych)
## Warning: package 'psych' was built under R version 4.3.3
numeric_vars <- data %>%
  select(where(is.numeric))

desc_stats <- describe(numeric_vars)[, c("mean", "sd", "min", "max", "median", "skew")]
print(desc_stats)
##            mean    sd min   max median  skew
## age       54.37  9.08  29  77.0   55.0 -0.20
## sex        0.68  0.47   0   1.0    1.0 -0.78
## cp         0.97  1.03   0   3.0    1.0  0.48
## trestbps 131.62 17.54  94 200.0  130.0  0.71
## chol     246.26 51.83 126 564.0  240.0  1.13
## fbs        0.15  0.36   0   1.0    0.0  1.97
## restecg    0.53  0.53   0   2.0    1.0  0.16
## thalach  149.65 22.91  71 202.0  153.0 -0.53
## exang      0.33  0.47   0   1.0    0.0  0.74
## oldpeak    1.04  1.16   0   6.2    0.8  1.26
## slope      1.40  0.62   0   2.0    1.0 -0.50
## ca         0.73  1.02   0   4.0    0.0  1.30
## thal       2.31  0.61   0   3.0    2.0 -0.47
## target     0.54  0.50   0   1.0    1.0 -0.18

B

# =============================
# 0. Install & Load ggplot2
# =============================
install.packages("ggplot2")
## Installing package into 'C:/Users/User/AppData/Local/R/win-library/4.3'
## (as 'lib' is unspecified)
## 
##   There is a binary version available but the source version is later:
##         binary source needs_compilation
## ggplot2  3.5.1  3.5.2             FALSE
## installing the source package 'ggplot2'
library(ggplot2)
## 
## Attaching package: 'ggplot2'
## The following objects are masked from 'package:psych':
## 
##     %+%, alpha
# =============================
# 1. Jenis Kelamin vs Penyakit Jantung
# =============================
ggplot(data_clean, aes(x = factor(sex), fill = factor(target))) +
  geom_bar(position = "dodge") +
  labs(
    title = "Penyakit Jantung Berdasarkan Jenis Kelamin",
    x = "Jenis Kelamin (0 = Laki-laki, 1 = Perempuan)",
    y = "Jumlah Pasien",
    fill = "Penyakit Jantung (0 = Tidak, 1 = Ya)"
  ) +
  theme_minimal()

# =============================
# 2. Usia yang Paling Banyak Mengalami Penyakit Jantung
# =============================
ggplot(data_clean[data_clean$target == 1, ], aes(x = age)) +
  geom_histogram(binwidth = 2, fill = "tomato", color = "black") +
  labs(
    title = "Distribusi Usia Penderita Penyakit Jantung",
    x = "Usia",
    y = "Jumlah Pasien"
  ) +
  theme_minimal()

# =============================
# 3. Usia dengan Gula Darah > 120 mg/dl (fbs = 1)
# =============================
ggplot(data_clean[data_clean$fbs == 1, ], aes(x = age)) +
  geom_histogram(binwidth = 2, fill = "skyblue", color = "black") +
  labs(
    title = "Distribusi Usia dengan Gula Darah Puasa > 120 mg/dl",
    x = "Usia",
    y = "Jumlah Pasien"
  ) +
  theme_minimal()

C

# Buat tabulasi antara fbs dan target
table_fbs_target <- table(data$fbs, data$target)
colnames(table_fbs_target) <- c("No Disease", "Disease")
rownames(table_fbs_target) <- c("fbs <= 120", "fbs > 120")
print(table_fbs_target)
##             
##              No Disease Disease
##   fbs <= 120        116     142
##   fbs > 120          22      23
# Hitung proporsi per baris (fbs)
prop.table(table_fbs_target, margin = 1)
##             
##              No Disease   Disease
##   fbs <= 120  0.4496124 0.5503876
##   fbs > 120   0.4888889 0.5111111

D

# Filter hanya pasien dengan heart disease
pasien_hd <- data[data$target == 1, ]

# Hitung frekuensi tipe nyeri dada
chestpain_freq <- table(pasien_hd$cp)
names(chestpain_freq) <- c("Typical angina", "Atypical angina", "Non-anginal pain", "Asymptomatic")

# Tampilkan hasil
print(chestpain_freq)
##   Typical angina  Atypical angina Non-anginal pain     Asymptomatic 
##               39               41               69               16
# (Opsional) Visualisasikan dengan barplot
barplot(chestpain_freq, 
        col = "steelblue", 
        main = "Jenis Nyeri Dada pada Pasien dengan Penyakit Jantung", 
        ylab = "Jumlah Pasien", 
        las = 2)

E

library(ggplot2)
library(dplyr)


data$cp <- as.factor(data$cp)
data$ca <- as.factor(data$ca)
data$thal <- as.factor(data$thal)
data$target <- as.factor(data$target)  # 0 = tidak ada penyakit, 1 = ada penyakit

# Fungsi bantu buat barplot proporsi
plot_proporsi <- function(var_name) {
  ggplot(data, aes_string(x = var_name, fill = "target")) +
    geom_bar(position = "fill") +
    scale_y_continuous(labels = scales::percent) +
    labs(
      title = paste("Proporsi Heart Disease berdasarkan", var_name),
      x = var_name,
      y = "Proporsi (%)",
      fill = "Heart Disease"
    ) +
    theme_minimal()
}

# Buat plot untuk cp
plot_cp <- plot_proporsi("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.
# Buat plot untuk ca
plot_ca <- plot_proporsi("ca")
# Buat plot untuk thal
plot_thal <- plot_proporsi("thal")

# Tampilkan
plot_cp

plot_ca

plot_thal

F

library(ggplot2)

data$target <- as.factor(data$target)

# Scatter plot dengan loess smoothing (non-linear)
ggplot(data, aes(x = age, y = thalach, color = target)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "loess", se = FALSE) +
  labs(
    title = "Hubungan Age dan Thalach berdasarkan Status Penyakit Jantung",
    x = "Age",
    y = "Thalach (Denyut Jantung Maksimum)",
    color = "Heart Disease"
  ) +
  theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'

Interpretasi

Hubungan antara age dan thalach bersifat non-linear, terutama terlihat dari garis tren yang melengkung. Hal ini menunjukkan bahwa perubahan denyut jantung maksimum terhadap usia tidak mengikuti pola linier sederhana, dan berbeda antara penderita dan non-penderita penyakit jantung karena titik-titik tersebar dan tidak membentuk pola linier yang konsisten. Ini menandakan hubungan kompleks, bukan sekadar naik atau turun terus.

G

# Load library
library(ggplot2)
library(reshape2)
## Warning: package 'reshape2' was built under R version 4.3.3
library(dplyr)

# Pilih hanya variabel numerik
num_vars <- data %>% 
  select_if(is.numeric)

# Hitung matriks korelasi
corr_matrix <- round(cor(num_vars, use = "complete.obs"), 2)

# Ubah ke format long (untuk ggplot heatmap)
melted_corr <- melt(corr_matrix)

# Plot heatmap korelasi
ggplot(melted_corr, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "red", high = "blue", mid = "white", 
                       midpoint = 0, limit = c(-1,1), space = "Lab", 
                       name = "Korelasi") +
  theme_minimal() +
  coord_fixed() +
  geom_text(aes(label = value), color = "black", size = 4) +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) +
  labs(title = "Heatmap Korelasi antar Variabel Numerik",
       x = "", y = "")

Interpretasi

Berdasarkan analisis heatmap korelasi, dapat disimpulkan bahwa terdapat hubungan negatif kuat antara variabel slope (kemiringan segmen ST) dan oldpeak (depresi ST) dengan korelasi -0,58, menunjukkan bahwa semakin tinggi slope, semakin rendah depresi ST atau sebaliknya. Variabel thalach (denyut jantung maksimal) menunjukkan korelasi negatif sedang dengan exang (-0,38) dan oldpeak (-0,34), mengindikasikan bahwa denyut jantung yang lebih tinggi berkaitan dengan risiko angina dan depresi ST yang lebih rendah, sementara exang sendiri berkorelasi positif dengan oldpeak (0,29), menandakan bahwa angina cenderung disertai depresi ST lebih besar. Selain itu, usia berpengaruh signifikan dengan korelasi negatif terhadap thalach (-0,4) dan positif terhadap trestbps (0,28) serta oldpeak (0,21), menunjukkan bahwa semakin tua seseorang, denyut jantung maksimalnya cenderung menurun, sedangkan tekanan darah dan depresi ST meningkat. Sebagian besar variabel lain seperti fbs, chol, dan testecg memiliki korelasi lemah mendekati nol, mengindikasikan tidak adanya hubungan linear yang kuat. Hasil ini menegaskan bahwa faktor-faktor seperti kemiringan segmen ST, depresi ST, denyut jantung, dan angina saling berkaitan dalam konteks kesehatan jantung, sementara usia juga memainkan peran penting dalam memengaruhi parameter-parameter tersebut.

H

Summary Hasil Analisis:

  1. Kadar Gula Darah (>120) dan Heart Disease
    • Proporsi penderita penyakit jantung (Heart Disease = 1) lebih tinggi pada individu dengan kadar gula darah > 120.
    • Kesimpulan: Gula darah tinggi berpotensi menjadi salah satu faktor risiko penyakit jantung.
  2. Jenis Nyeri Dada (cp)
    • Jenis nyeri dada paling sering dialami oleh penderita penyakit jantung adalah typical angina atau asymptomatic (tergantung data yang dianalisis).
    • Kesimpulan: Tipe nyeri dada tertentu dapat menjadi indikasi dini adanya gangguan jantung.
  3. Bar Plot: Proporsi Heart Disease terhadap Variabel Kategorikal
    • Variabel cp (chest pain), ca (jumlah pembuluh darah utama), dan thal (tes thalassemia) memperlihatkan perbedaan proporsi signifikan antara penderita dan bukan penderita.
    • Interpretasi: Variabel-variabel ini penting untuk deteksi dini penyakit jantung.
  4. Hubungan Age dan Thalach (Detak Jantung Maksimum)
    • Terdapat hubungan non-linear: makin tua, detak jantung maksimum cenderung menurun, terutama pada penderita penyakit jantung.
    • Kesimpulan: Penurunan detak jantung maksimum bisa menjadi tanda melemahnya fungsi jantung, terutama pada usia lanjut.
  5. Heatmap Korelasi
    • Korelasi negatif antara age dan thalach, serta korelasi positif antara chol (kolesterol) dan trestbps (tekanan darah).
    • Kesimpulan: Beberapa variabel memiliki keterkaitan kuat yang bisa digunakan untuk membangun model prediksi penyakit jantung.

Hal-Hal yang Dapat Mencegah Penyakit Jantung:


Aspek yang Menjadi Indikasi Penyakit Jantung:

  1. [Nilai 20] Dari data berikut, Buat diagram yang sama dengan contoh. Serta jelaskan maksud setiap dari bagian sintag tersebut. Kemudian interpretasikan.
library(readxl)
data2 <- read_excel("C:/Users/User/OneDrive/Documents/Data2.xlsx")
head(data)
## # A tibble: 6 × 14
##     age   sex cp    trestbps  chol   fbs restecg thalach exang oldpeak slope
##   <dbl> <dbl> <fct>    <dbl> <dbl> <dbl>   <dbl>   <dbl> <dbl>   <dbl> <dbl>
## 1    63     1 3          145   233     1       0     150     0     2.3     0
## 2    37     1 2          130   250     0       1     187     0     3.5     0
## 3    41     0 1          130   204     0       0     172     0     1.4     2
## 4    56     1 1          120   236     0       1     178     0     0.8     2
## 5    57     0 0          120   354     0       1     163     1     0.6     2
## 6    57     1 0          140   192     0       1     148     0     0.4     1
## # ℹ 3 more variables: ca <fct>, thal <fct>, target <fct>
install.packages(c("readxl", "ggplot2", "dplyr"))
## Warning: packages 'readxl', 'ggplot2', 'dplyr' are in use and will not be
## installed
library(readxl)
library(ggplot2)
library(dplyr)

head(data2)  # Preview 6 baris pertama
## # A tibble: 6 × 4
##      No Konsumsi_GWh Biaya_Per_kWh Konsumen    
##   <dbl>        <dbl>         <dbl> <chr>       
## 1     1           10          1500 Rumah Tangga
## 2     2           20          1450 Rumah Tangga
## 3     3           30          1400 Rumah Tangga
## 4     4           50          1350 Rumah Tangga
## 5     5           70          1300 Rumah Tangga
## 6     6           90          1250 Rumah Tangga
str(data2)   # Struktur data
## tibble [24 × 4] (S3: tbl_df/tbl/data.frame)
##  $ No           : num [1:24] 1 2 3 4 5 6 7 8 9 10 ...
##  $ Konsumsi_GWh : num [1:24] 10 20 30 50 70 90 40 80 120 200 ...
##  $ Biaya_Per_kWh: num [1:24] 1500 1450 1400 1350 1300 1250 1300 1250 1200 1150 ...
##  $ Konsumen     : chr [1:24] "Rumah Tangga" "Rumah Tangga" "Rumah Tangga" "Rumah Tangga" ...
scatter_plot <- ggplot(data2, aes(x = Konsumsi_GWh, y = Biaya_Per_kWh, 
                                       color = Konsumen, label = Konsumen)) +
  geom_point(size = 5) +
  geom_smooth(method = "lm", se = FALSE, color = "red") +
  labs(title = "Hubungan Konsumsi dan Biaya Listrik per Kategori",
       subtitle = "Biaya cenderung turun saat konsumsi meningkat",
       x = "Konsumsi (GWh)",
       y = "Biaya per kWh (Rp)",
       caption = "Sumber: Data2.xlsx") +
  theme_minimal() +
  theme(legend.position = "bottom")

print(scatter_plot)
## `geom_smooth()` using formula = 'y ~ x'
## Warning: The following aesthetics were dropped during statistical transformation: label.
## ℹ This can happen when ggplot fails to infer the correct grouping structure in
##   the data.
## ℹ Did you forget to specify a `group` aesthetic or to convert a numerical
##   variable into a factor?

Penjelasan tiap syntax

ggplot(data2, aes(x = Konsumsi_GWh, y = Biaya_Per_kWh, color = Konsumen, label = Konsumen))

  • ggplot(): Fungsi utama untuk memulai plot.

  • data2: Data frame yang digunakan.

  • aes() (Aesthetics): Mapping variabel ke visual:

  • x = Konsumsi_GWh: Variabel konsumsi listrik (GWh) di sumbu x.

  • y = Biaya_Per_kWh: Variabel biaya listrik (Rp/kWh) di sumbu y.

  • color = Konsumen: Warna titik berbeda berdasarkan kolom Konsumen.

  • label = Konsumen: Label teks untuk setiap titik (digunakan jika ada geom_text()). #### geom_point(size = 5)

  • geom_point(): Menambahkan titik (scatter plot).

  • size = 5: Ukuran titik diperbesar jadi 5 (default = 1).

geom_smooth(method = “lm”, se = FALSE, color = “red”)

  • geom_smooth(): Menambahkan garis tren.

  • method = “lm”: Garis linear regression (model linier).

  • se = FALSE: Menghilangkan area shadow (standard error).

  • color = “red”: Warna garis tren dibuat merah. #### labs() (Labels) Judul dan Anotasi:

  • title: Judul utama plot.

  • subtitle: Subjudul di bawah judul utama.

  • x: Label sumbu x.

  • y: Label sumbu y.

  • caption: Teks kecil di pojok bawah (sumber data).

  • theme_minimal() Menggunakan tema minimalis (tanpa background grid yang rumit).

theme(legend.position = “bottom”)

  • theme(): Modifikasi tampilan elemen non-data.

  • legend.position = “bottom”: Memindahkan legenda ke bawah plot.

Interpretasi

Berdasarkan data yang ditampilkan, terlihat pola penurunan biaya listrik per kWh seiring peningkatan konsumsi, di mana industri sebagai konsumen dengan konsumsi tertinggi (diduga >200 GWh) menikmati biaya terendah (1,200 Rp/kWh), sementara UMKM dengan konsumsi rendah (diduga <50 GWh) justru menghadapi biaya tertinggi (1,500 Rp/kWh), menunjukkan adanya skala ekonomi yang menguntungkan pelanggan besar namun berpotensi memberatkan pelaku UMKM, sehingga perlu evaluasi kebijakan tarif untuk memastikan keadilan, khususnya melalui subsidi bagi pelaku usaha kecil atau penyesuaian struktur tarif yang lebih proporsional.