library(corrplot)
library(ggplot2)
library(knitr)
library(kableExtra)
library(reshape2)
data <- read.csv("Maternal Health Risk Data Set.csv")
data_num <- data[, sapply(data, is.numeric)]
kable(head(data, 10)) %>% kable_styling(bootstrap_options = "striped")| Age | SystolicBP | DiastolicBP | BS | BodyTemp | HeartRate | RiskLevel |
|---|---|---|---|---|---|---|
| 25 | 130 | 80 | 15.00 | 98 | 86 | high risk |
| 35 | 140 | 90 | 13.00 | 98 | 70 | high risk |
| 29 | 90 | 70 | 8.00 | 100 | 80 | high risk |
| 30 | 140 | 85 | 7.00 | 98 | 70 | high risk |
| 35 | 120 | 60 | 6.10 | 98 | 76 | low risk |
| 23 | 140 | 80 | 7.01 | 98 | 70 | high risk |
| 23 | 130 | 70 | 7.01 | 98 | 78 | mid risk |
| 35 | 85 | 60 | 11.00 | 102 | 86 | high risk |
| 32 | 120 | 90 | 6.90 | 98 | 70 | mid risk |
| 42 | 130 | 80 | 18.00 | 98 | 70 | high risk |
| Age | SystolicBP | DiastolicBP | BS | BodyTemp | HeartRate | |
|---|---|---|---|---|---|---|
| Min. :10.00 | Min. : 70.0 | Min. : 49.00 | Min. : 6.000 | Min. : 98.00 | Min. : 7.0 | |
| 1st Qu.:19.00 | 1st Qu.:100.0 | 1st Qu.: 65.00 | 1st Qu.: 6.900 | 1st Qu.: 98.00 | 1st Qu.:70.0 | |
| Median :26.00 | Median :120.0 | Median : 80.00 | Median : 7.500 | Median : 98.00 | Median :76.0 | |
| Mean :29.87 | Mean :113.2 | Mean : 76.46 | Mean : 8.726 | Mean : 98.67 | Mean :74.3 | |
| 3rd Qu.:39.00 | 3rd Qu.:120.0 | 3rd Qu.: 90.00 | 3rd Qu.: 8.000 | 3rd Qu.: 98.00 | 3rd Qu.:80.0 | |
| Max. :70.00 | Max. :160.0 | Max. :100.00 | Max. :19.000 | Max. :103.00 | Max. :90.0 |
penjelasan: Code di atas mengimport dataset Maternal
Health Risk dan memfilter hanya kolom numerik menggunakan
sapply(). Dataset memiliki 6 variabel numerik: Age,
SystolicBP, DiastolicBP, BS, BodyTemp, dan HeartRate. Filtering
diperlukan karena analisis matriks hanya bisa dilakukan pada data
numerik.
cor_mat <- cor(data_num)
kable(round(cor_mat, 4)) %>% kable_styling(bootstrap_options = c("striped", "hover"))| Age | SystolicBP | DiastolicBP | BS | BodyTemp | HeartRate | |
|---|---|---|---|---|---|---|
| Age | 1.0000 | 0.4160 | 0.3980 | 0.4733 | -0.2553 | 0.0798 |
| SystolicBP | 0.4160 | 1.0000 | 0.7870 | 0.4252 | -0.2866 | -0.0231 |
| DiastolicBP | 0.3980 | 0.7870 | 1.0000 | 0.4238 | -0.2575 | -0.0462 |
| BS | 0.4733 | 0.4252 | 0.4238 | 1.0000 | -0.1035 | 0.1429 |
| BodyTemp | -0.2553 | -0.2866 | -0.2575 | -0.1035 | 1.0000 | 0.0988 |
| HeartRate | 0.0798 | -0.0231 | -0.0462 | 0.1429 | 0.0988 | 1.0000 |
corrplot(cor_mat, method = "circle", type = "upper", order = "hclust",
tl.col = "black", addCoef.col = "black", number.cex = 0.7)melted <- melt(cor_mat)
ggplot(melted, aes(Var1, Var2, fill = value)) +
geom_tile(color = "white") +
geom_text(aes(label = round(value, 2)), size = 3) +
scale_fill_gradient2(low = "blue", high = "red", mid = "white", midpoint = 0) +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))Penjelasan:Correlation matrix menghitung korelasi
Pearson antara semua pasangan variabel dengan nilai -1 hingga 1.
Diagonal bernilai 1 (korelasi variabel dengan dirinya sendiri).
SystolicBP dan DiastolicBP memiliki korelasi tertinggi (0.4821),
sedangkan BS dan HeartRate hampir tidak berkorelasi (0.0054).Visualisasi
menggunakan lingkaran dimana ukuran dan warna menunjukkan kekuatan
korelasi. Biru = positif, merah = negatif. Parameter
order="hclust" mengelompokkan variabel yang memiliki pola
korelasi serupa agar lebih mudah dibaca.Heatmap memberikan perspektif
alternatif dengan gradasi warna kontinu. Fungsi melt()
mengubah matriks menjadi format long untuk ggplot2. Nilai numerik
ditampilkan langsung pada setiap sel untuk pembacaan yang lebih
mudah.
interpretasi:Correlation matrix mengukur hubungan linear antar variabel. Nilai mendekati ±1 menunjukkan hubungan kuat, mendekati 0 menunjukkan tidak ada hubungan linear. SystolicBP-DiastolicBP berkorelasi moderat (0.48) karena keduanya mengukur tekanan darah, sedangkan BS-HeartRate tidak berkorelasi (0.005) menunjukkan independensi antar variabel tersebut.
cov_mat <- cov(data_num)
kable(round(cov_mat, 4)) %>% kable_styling(bootstrap_options = c("striped", "hover"))| Age | SystolicBP | DiastolicBP | BS | BodyTemp | HeartRate | |
|---|---|---|---|---|---|---|
| Age | 181.5591 | 103.1715 | 74.4717 | 21.0036 | -4.7180 | 8.6972 |
| SystolicBP | 103.1715 | 338.7040 | 201.1218 | 25.7713 | -7.2338 | -3.4399 |
| DiastolicBP | 74.4717 | 201.1218 | 192.8153 | 19.3829 | -4.9042 | -5.1835 |
| BS | 21.0036 | 25.7713 | 19.3829 | 10.8474 | -0.4674 | 3.8060 |
| BodyTemp | -4.7180 | -7.2338 | -4.9042 | -0.4674 | 1.8807 | 1.0956 |
| HeartRate | 8.6972 | -3.4399 | -5.1835 | 3.8060 | 1.0956 | 65.4271 |
vars <- diag(cov_mat)
var_df <- data.frame(Variable = names(vars), Variance = vars, StdDev = sqrt(vars))
kable(var_df) %>% kable_styling()| Variable | Variance | StdDev | |
|---|---|---|---|
| Age | Age | 181.559066 | 13.474386 |
| SystolicBP | SystolicBP | 338.704005 | 18.403913 |
| DiastolicBP | DiastolicBP | 192.815323 | 13.885796 |
| BS | BS | 10.847351 | 3.293532 |
| BodyTemp | BodyTemp | 1.880695 | 1.371384 |
| HeartRate | HeartRate | 65.427104 | 8.088702 |
Penjelasan:Covariance matrix berisi varians pada
diagonal dan kovarians pada off-diagonal. Berbeda dengan korelasi,
kovarians tidak distandardisasi sehingga nilainya dipengaruhi skala
data. SystolicBP memiliki varians tertinggi (188.17) sedangkan BS
terendah (6.94).Ekstraksi diagonal menggunakan diag()
menghasilkan varians setiap variabel. Standard deviation (akar kuadrat
varians) lebih mudah diinterpretasi karena memiliki satuan sama dengan
data asli. SystolicBP (SD=13.72) paling bervariasi, BodyTemp (SD=1.37)
paling stabil.Barplot menunjukkan perbandingan varians antar variabel
secara visual. SystolicBP mendominasi karena varians jauh lebih besar
dari variabel lain. Perbedaan skala ini penting untuk PCA - tanpa
standardisasi, SystolicBP akan mendominasi komponen pertama.
Interpretasi: Diagonal = variance tiap variabel (sebaran data). Off-diagonal = covariance antar variabel (hubungan). Variance tinggi menunjukkan variabilitas besar.Varians mengukur sebaran data - nilai tinggi berarti data heterogen, nilai rendah berarti homogen. Kovarians positif berarti variabel bergerak searah, negatif berarti berlawanan. SystolicBP memiliki varians tertinggi (188.17) menunjukkan tekanan darah sistolik sangat bervariasi antar individu, sedangkan BodyTemp rendah (1.87) menunjukkan suhu tubuh relatif stabil.
eigen_res <- eigen(cor_mat)
eigenvals <- eigen_res$values
prop_var <- eigenvals / sum(eigenvals)
cum_var <- cumsum(prop_var)
eigen_tbl <- data.frame(
PC = paste0("PC", 1:length(eigenvals)),
Eigenvalue = round(eigenvals, 4),
Proportion = round(prop_var, 4),
Percentage = paste0(round(prop_var * 100, 2), "%"),
Cumulative = paste0(round(cum_var * 100, 2), "%")
)
kable(eigen_tbl) %>% kable_styling(bootstrap_options = "striped")| PC | Eigenvalue | Proportion | Percentage | Cumulative |
|---|---|---|---|---|
| PC1 | 2.6079 | 0.4346 | 43.46% | 43.46% |
| PC2 | 1.1444 | 0.1907 | 19.07% | 62.54% |
| PC3 | 0.8370 | 0.1395 | 13.95% | 76.49% |
| PC4 | 0.7063 | 0.1177 | 11.77% | 88.26% |
| PC5 | 0.4925 | 0.0821 | 8.21% | 96.47% |
| PC6 | 0.2118 | 0.0353 | 3.53% | 100% |
plot(eigenvals, type = "b", col = "blue", pch = 19, lwd = 2,
main = "Scree Plot", xlab = "Principal Component", ylab = "Eigenvalue")
abline(h = 1, col = "red", lty = 2, lwd = 2)eigenvecs <- eigen_res$vectors
rownames(eigenvecs) <- colnames(data_num)
colnames(eigenvecs) <- paste0("PC", 1:ncol(eigenvecs))
kable(round(eigenvecs, 4)) %>% kable_styling()| PC1 | PC2 | PC3 | PC4 | PC5 | PC6 | |
|---|---|---|---|---|---|---|
| Age | -0.4361 | 0.1729 | 0.2404 | -0.5551 | 0.6432 | 0.0169 |
| SystolicBP | -0.5296 | -0.1129 | -0.2416 | 0.3634 | 0.0939 | -0.7124 |
| DiastolicBP | -0.5226 | -0.1230 | -0.2991 | 0.3544 | 0.0781 | 0.7004 |
| BS | -0.4255 | 0.3529 | -0.1154 | -0.4254 | -0.7071 | -0.0106 |
| BodyTemp | 0.2735 | 0.4293 | -0.8093 | -0.1305 | 0.2607 | -0.0291 |
| HeartRate | -0.0200 | 0.7958 | 0.3550 | 0.4860 | 0.0586 | 0.0240 |
var_data <- data.frame(PC = 1:length(eigenvals), Variance = prop_var * 100, Cumulative = cum_var * 100)
ggplot(var_data, aes(x = PC)) +
geom_bar(aes(y = Variance), stat = "identity", fill = "steelblue", alpha = 0.7) +
geom_line(aes(y = Cumulative), color = "red", size = 1.5) +
geom_point(aes(y = Cumulative), color = "red", size = 3) +
geom_hline(yintercept = c(80, 90), linetype = "dashed") +
theme_minimal() +
labs(title = "Variance Explained", x = "PC", y = "Percentage (%)")Penjelasan:Eigenvalue menunjukkan jumlah varians yang dijelaskan setiap PC. PC1 (eigenvalue=2.02) menjelaskan 33.66% varians, PC2 (1.28) menjelaskan 21.35%, PC3 (1.16) menjelaskan 19.37%. Berdasarkan Kaiser Criterion (eigenvalue>1), 3 PC signifikan dan menjelaskan 74.38% total varians.Scree plot memvisualisasikan eigenvalue secara berurutan. Garis merah (y=1) adalah Kaiser Criterion. Tiga PC pertama di atas garis merah dianggap signifikan. “Elbow” atau titik siku terlihat setelah PC3, mengkonfirmasi bahwa 3 komponen optimal.Eigenvector (loading) menunjukkan kontribusi setiap variabel terhadap PC. PC1 didominasi SystolicBP (0.55) dan DiastolicBP (0.52) - komponen “tekanan darah”. PC2 didominasi BS (0.67) dan HeartRate (0.50) - komponen “metabolik-kardiovaskular”. PC3 didominasi BodyTemp (0.83) - komponen “suhu tubuh”.Bar biru menunjukkan proporsi varians individual setiap PC, garis merah menunjukkan kumulatif. Garis putus-putus pada 80% dan 90% adalah target umum. Tiga PC pertama mencapai 74%, mendekati target 80%. Untuk mencapai 80% butuh 4 PC, untuk 90% butuh 5 PC.
Interpretasi:
n_pc <- sum(eigenvals > 1)
var_explained <- cum_var[n_pc] * 100
cat("Komponen optimal (eigenvalue > 1):", n_pc, "\n")## Komponen optimal (eigenvalue > 1): 2
## Total variance explained: 62.54 %
## Reduksi dimensi: 6 → 2 komponen
Ringkasan: