Data meteorologi merupakan data multidimensi yang terdiri atas banyak variabel saling berkorelasi, seperti suhu, tekanan udara, kelembaban, dan kecepatan angin. Penelitian ini menerapkan Principal Component Analysis (PCA) dan Factor Analysis (FA) pada Max Planck Weather Dataset (stasiun Jena, Jerman, 2009–2016) dengan tiga tujuan:
library(psych) # u/ KMO, Bartlett, FA
library(FactoMineR) # u/ PCA
library(factoextra) # u/ Visualisasi PCA
## Loading required package: ggplot2
##
## Attaching package: 'ggplot2'
## The following objects are masked from 'package:psych':
##
## %+%, alpha
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(corrplot) # u/ Heatmap korelasi
## corrplot 0.95 loaded
library(tidyverse) # u/ Manipulasi data
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.0 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ lubridate 1.9.5 ✔ tibble 3.3.1
## ✔ purrr 1.2.1 ✔ tidyr 1.3.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ ggplot2::%+%() masks psych::%+%()
## ✖ ggplot2::alpha() masks psych::alpha()
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
df_raw <- read.csv("max_planck_weather_ts.csv", stringsAsFactors = FALSE)
cat("\nDimensi data:", dim(df_raw), "\n")
##
## Dimensi data: 420551 15
Dataset bersumber dari Kaggle - Max Planck Weather Dataset, berisi 420.551 observasi dengan interval pencatatan setiap 10 menit selama 8 tahun (2009–2016).
#Seleksi variabel
df_numeric <- df_raw %>% select(where(is.numeric))
cat("Variabel yang digunakan:\n"); print(names(df_numeric))
## Variabel yang digunakan:
## [1] "p..mbar." "T..degC." "Tpot..K." "Tdew..degC."
## [5] "rh...." "VPmax..mbar." "VPact..mbar." "VPdef..mbar."
## [9] "sh..g.kg." "H2OC..mmol.mol." "rho..g.m..3." "wv..m.s."
## [13] "max..wv..m.s." "wd..deg."
#Mengecek missing values
print(colSums(is.na(df_numeric)))
## p..mbar. T..degC. Tpot..K. Tdew..degC. rh....
## 0 0 0 0 0
## VPmax..mbar. VPact..mbar. VPdef..mbar. sh..g.kg. H2OC..mmol.mol.
## 0 0 0 0 0
## rho..g.m..3. wv..m.s. max..wv..m.s. wd..deg.
## 0 0 0 0
#Menghapus missing values dan anomali -9999
df_clean <- df_numeric %>%
filter(if_all(everything(), ~ . > -999))
cat("Observasi setelah melakukan filter anomali:", nrow(df_clean), "\n")
## Observasi setelah melakukan filter anomali: 420531
#Sampling
set.seed(123)
n_sample <- min(10000, nrow(df_clean))
df_sample <- df_clean %>%
slice_sample(n = n_sample)
cat("Jumlah sampel:", nrow(df_sample))
## Jumlah sampel: 10000
Dari 420.551 observasi awal, 20 data teridentifikasi anomali sensor dan dihapus, menyisakan 420.531 observasi bersih. Sampel acak 10.000 diambil dengan set.seed(123) untuk menjamin reprodusibilitas.
desc_stats <- describe(df_sample)
print(desc_stats[, c("n", "mean", "sd", "min", "max", "skew", "kurtosis")])
## n mean sd min max skew kurtosis
## p..mbar. 10000 989.17 8.33 948.90 1015.29 -0.33 0.64
## T..degC. 10000 9.54 8.45 -23.01 35.36 -0.05 -0.17
## Tpot..K. 10000 283.59 8.53 250.60 309.66 -0.07 -0.12
## Tdew..degC. 10000 5.04 6.76 -25.01 23.06 -0.42 0.06
## rh.... 10000 76.00 16.49 14.30 100.00 -0.66 -0.42
## VPmax..mbar. 10000 13.66 7.76 0.95 57.42 1.27 2.12
## VPact..mbar. 10000 9.59 4.20 0.79 28.24 0.55 -0.21
## VPdef..mbar. 10000 4.07 4.88 0.00 40.45 2.26 6.49
## sh..g.kg. 10000 6.06 2.67 0.50 18.07 0.56 -0.18
## H2OC..mmol.mol. 10000 9.70 4.26 0.80 28.73 0.55 -0.20
## rho..g.m..3. 10000 1215.61 40.11 1102.46 1392.10 0.33 0.15
## wv..m.s. 10000 2.14 1.54 0.00 13.95 1.46 2.88
## max..wv..m.s. 10000 3.54 2.35 0.00 20.49 1.33 2.41
## wd..deg. 10000 176.67 86.17 0.00 359.90 -0.49 -0.53
Interpretasi:
df_long <- df_sample %>%
pivot_longer(cols=everything(), names_to="Variabel", values_to="Nilai")
p_hist <- df_long %>%
ggplot(aes(x = Nilai, fill = Variabel)) +
geom_histogram(bins = 30, show.legend = FALSE, color = "white", alpha = 0.8) +
facet_wrap(~Variabel, scales = "free") +
theme_minimal(base_size = 9) +
labs(title = "Gambar 1. Distribusi Frekuensi Variabel Cuaca") +
scale_fill_brewer(palette = "Set3")
print(p_hist)
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Set3 is 12
## Returning the palette you asked for with that many colors
Gambar 1. Distribusi Variabel Cuaca (Histogram)
Histogram sebelum standardisasi memperlihatkan variabel suhu (T, Tpot, Tdew) dan tekanan udara (p, rho) mendekati distribusi normal simetris, mencerminkan variasi musiman yang teratur. Sebaliknya, variabel kecepatan angin (wv, max.wv), defisit tekanan uap (VPdef), dan tekanan uap maksimum (VPmax) menunjukkan distribusi miring kanan (right-skewed), mengindikasikan kondisi ekstrem yang jarang namun mungkin terjadi. Arah angin (wd) terdistribusi relatif merata (uniform), konsisten dengan sifat angin yang dapat bertiup dari segala arah.
df_scaled <- as.data.frame(scale(df_sample))
cat("Range mean:", round(range(colMeans(df_scaled)),5), "(harus ~0)\n")
## Range mean: 0 0 (harus ~0)
cat("Range SD :", round(range(apply(df_scaled,2,sd)),5), "(harus ~1)\n")
## Range SD : 1 1 (harus ~1)
Range mean = 0 0 dan range SD = 1 1 -> standardisasi berhasil sempurna, seluruh 14 variabel kini setara secara skala.
cor_matrix <- cor(df_scaled)
corrplot(cor_matrix, method="color", type="upper", addCoef.col="black",
number.cex=0.55, tl.cex=0.75, tl.col="black",
col=colorRampPalette(c("#D73027","white","#1A9850"))(200),
title="Heatmap Matriks Korelasi", mar=c(0,0,2,0))
Gambar 2. Heatmap Matriks Korelasi
Heatmap menunjukkan korelasi sangat kuat antar variabel termodinamika (T, Tpot, Tdew, VPmax, VPact, sh, H2OC), sementara wv dan max.wv membentuk kluster tersendiri. Pola ini mengindikasikan adanya struktur laten yang dapat diekstrak.
mat_corr <- cor(df_scaled)
kmo <- KMO(mat_corr)
cat("KMO Overall :", round(kmo$MSA, 3), "\n")
## KMO Overall : 0.746
cat("MSA per variabel:\n"); print(round(kmo$MSAi, 3))
## MSA per variabel:
## p..mbar. T..degC. Tpot..K. Tdew..degC. rh....
## 0.080 0.745 0.761 0.831 0.760
## VPmax..mbar. VPact..mbar. VPdef..mbar. sh..g.kg. H2OC..mmol.mol.
## 0.771 0.764 0.679 0.822 0.843
## rho..g.m..3. wv..m.s. max..wv..m.s. wd..deg.
## 0.826 0.557 0.578 0.198
Interpretasi:
bartlett <- cortest.bartlett(mat_corr, n = nrow(df_scaled))
cat("Chi-Square :", round(bartlett$chisq, 3), "\n")
## Chi-Square : 740419.9
cat("df :", bartlett$df, "\n")
## df : 91
cat("p-value :", format(bartlett$p.value, scientific = TRUE), "\n")
## p-value : 0e+00
Bartlett: Chi-Square = 740.419,9, p-value = 0,000 Nilai Chi-Square yang sangat besar mencerminkan n yang besar (10.000), dengan n besar bahkan korelasi kecil pun signifikan. Maka data layak untuk dilakukan PCA.
pca <- PCA(df_scaled, graph = FALSE)
eig <- pca$eig
tabel_varians <- as.data.frame(eig)
colnames(tabel_varians) <- c("Eigenvalue", "Variance", "Cumulative")
tabel_varians$Komponen <- paste0("PC", 1:nrow(tabel_varians))
n_pc <- sum(eig[, 1] > 1)
cat("Jumlah PC (eigenvalue > 1):", n_pc, "\n")
## Jumlah PC (eigenvalue > 1): 4
cat("Total variance explained :", round(eig[n_pc, 3], 2), "%\n")
## Total variance explained : 92.03 %
Heatmap menunjukkan tiga pola korelasi yang terbentuk secara alami. Variabel termodinamika dan uap air (T, Tpot, VPmax, VPact, sh, H2OC, Tdew) saling berkorelasi kuat (r > 0,80), sementara rho berkorelasi negatif kuat dengan suhu (r = -0,96). Variabel angin (wv dan max.wv) berkorelasi kuat satu sama lain (r = 0,96) namun lemah terhadap kelompok lainnya. Variabel p dan wd berdiri sendiri dengan korelasi rendah terhadap semua variabel, mengindikasikan sifatnya yang independen.
# PCA
pca <- PCA(df_scaled, graph = FALSE)
# Ambil eigenvalue
eig <- pca$eig
tabel_varians <- as.data.frame(eig)
# Rename kolom supaya aman
colnames(tabel_varians) <- c("Eigenvalue",
"Variance",
"Cumulative")
tabel_varians$Komponen <- paste0("PC", 1:nrow(tabel_varians))
# Hitung jumlah PC (Kaiser)
n_pc <- sum(tabel_varians$Eigenvalue > 1)
cat("Jumlah PC (eigenvalue > 1):", n_pc, "\n")
## Jumlah PC (eigenvalue > 1): 4
cat("Total variance explained :",
round(tabel_varians$Cumulative[n_pc], 2), "%\n")
## Total variance explained : 92.03 %
# Scree Plot
ggplot(tabel_varians, aes(x = 1:nrow(tabel_varians), y = Eigenvalue)) +
geom_line(color = "blue", linewidth = 1) +
geom_point(color = "red", size = 3) +
geom_hline(yintercept = 1,
linetype = "dashed",
color = "darkgreen",
linewidth = 1) +
scale_x_continuous(breaks = 1:nrow(tabel_varians),
labels = tabel_varians$Komponen) +
labs(title = "Scree Plot: Eigenvalue vs Komponen Utama",
x = "Komponen Utama (Principal Component)",
y = "Eigenvalue") +
theme_minimal()
Gambar 3. Scree Plot PCA
Scree plot memperlihatkan penurunan tajam dari PC1 ke PC2, kemudian menurun lebih landai hingga PC4. Setelah PC4, kurva sudah mendatar dan seluruh eigenvalue berada di bawah nilai 1. Patahan (elbow) yang jelas setelah PC4 mempertegas bahwa 4 komponen utama cukup untuk merepresentasikan struktur data.
print(round(pca$var$coord[, 1:n_pc], 3))
## Dim.1 Dim.2 Dim.3 Dim.4
## p..mbar. -0.114 -0.194 -0.656 0.246
## T..degC. 0.987 0.040 -0.094 -0.023
## Tpot..K. 0.989 0.055 -0.042 -0.042
## Tdew..degC. 0.920 -0.287 0.181 0.053
## rh.... -0.496 -0.625 0.517 0.161
## VPmax..mbar. 0.961 0.097 -0.194 0.004
## VPact..mbar. 0.920 -0.307 0.164 0.092
## VPdef..mbar. 0.734 0.418 -0.449 -0.072
## sh..g.kg. 0.921 -0.304 0.174 0.088
## H2OC..mmol.mol. 0.921 -0.304 0.174 0.088
## rho..g.m..3. -0.968 -0.065 -0.104 0.084
## wv..m.s. 0.110 0.856 0.374 0.169
## max..wv..m.s. 0.143 0.873 0.337 0.108
## wd..deg. 0.028 -0.047 0.112 -0.929
Interpretasi:
parallel <- fa.parallel(df_scaled, fm = "ml", fa = "fa",
main = "Parallel Analysis Scree Plot")
Gambar 6. Parallel Analysis Scree Plot
## Parallel analysis suggests that the number of factors = 5 and the number of components = NA
n_factors <- parallel$nfact
cat("Jumlah faktor optimal:", n_factors, "\n")
## Jumlah faktor optimal: 5
Parallel analysis menunjukkan bahwa eigenvalue data nyata berada di atas eigenvalue data acak hingga faktor ke-5, dan mulai faktor ke-6 sudah berada di bawahnya. Berdasarkan hal ini, jumlah faktor optimal yang direkomendasikan adalah 5 faktor.
fa_result <- fa(df_scaled, nfactors = n_factors,
rotate = "varimax", fm = "ml")
Hasil FA dengan rotasi varimax menghasilkan 5 faktor yang secara kumulatif menjelaskan 91,3% variansi total. Rata-rata communality sebesar 0,913 menunjukkan bahwa model mampu merepresentasikan hampir seluruh variansi tiap variabel dengan baik, kecuali wd (0,035) yang bersifat sirkular dan independen secara alami.
print(round(fa_result$loadings[, 1:n_factors], 3))
## ML1 ML3 ML4 ML2 ML5
## p..mbar. -0.061 0.027 -0.147 0.969 0.173
## T..degC. 0.843 0.508 0.076 0.029 -0.152
## Tpot..K. 0.842 0.502 0.087 -0.048 -0.164
## Tdew..degC. 0.970 0.107 -0.023 0.013 -0.169
## rh.... -0.097 -0.891 -0.242 -0.053 0.081
## VPmax..mbar. 0.781 0.609 0.040 -0.019 0.126
## VPact..mbar. 0.994 0.079 -0.052 -0.015 0.036
## VPdef..mbar. 0.385 0.898 0.108 -0.017 0.170
## sh..g.kg. 0.994 0.078 -0.050 -0.030 0.036
## H2OC..mmol.mol. 0.994 0.079 -0.049 -0.030 0.034
## rho..g.m..3. -0.832 -0.446 -0.108 0.221 0.217
## wv..m.s. -0.019 0.123 0.962 -0.086 0.074
## max..wv..m.s. -0.009 0.176 0.961 -0.075 0.053
## wd..deg. 0.020 -0.006 -0.023 -0.033 -0.182
Interpretasi faktor:
# 10d. Communalities (Ringkas)
communalities <- round(fa_result$communality, 3)
summary(communalities)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.0350 0.9677 0.9970 0.9131 0.9980 0.9980
cat("Rata-rata communality:", round(mean(communalities), 3), "\n")
## Rata-rata communality: 0.913
cat("Communality minimum :", round(min(communalities), 3), "\n")
## Communality minimum : 0.035
cat("Communality maksimum:", round(max(communalities), 3), "\n")
## Communality maksimum: 0.998
Interpretasi:
print(round(fa_result$Vaccounted, 3))
## ML1 ML3 ML4 ML2 ML5
## SS loadings 6.788 2.759 1.977 1.011 0.252
## Proportion Var 0.485 0.197 0.141 0.072 0.018
## Cumulative Var 0.485 0.682 0.823 0.895 0.913
## Proportion Explained 0.531 0.216 0.155 0.079 0.020
## Cumulative Proportion 0.531 0.747 0.901 0.980 1.000
Variance Explained kumulatif 91,3% ini artinya model FA sangat komprehensif
PCA berhasil mereduksi 14 variabel meteorologi menjadi 4 komponen utama yang menjelaskan 92,03% total variansi, terdiri dari faktor termodinamika dan kandungan uap air (57,37%), dinamika angin (17,71%), tekanan atmosfer (9,60%), dan arah angin (7,36%). Hasil Factor Analysis dengan rotasi varimax mengidentifikasi 5 faktor laten yang menjelaskan 91,3% variansi total, yaitu faktor kandungan uap air dan suhu, defisit uap air dan kekeringan, dinamika angin, tekanan atmosfer, dan faktor residual. Rata-rata communality sebesar 0,913 menunjukkan bahwa model mampu merepresentasikan hampir seluruh variansi tiap variabel, kecuali arah angin (wd) yang bersifat independen dengan communality hanya 0,035. Secara keseluruhan, kedua metode terbukti efektif dalam menyederhanakan struktur data atmosfer yang kompleks tanpa kehilangan informasi utama.
Jolliffe, I. T., & Cadima, J. (2024). Principal component analysis: a review and recent developments. Philosophical transactions. Series A, Mathematical, physical, and engineering sciences, 374(2065), 20150202. https://doi.org/10.1098/rsta.2015.0202
Bashir, R. N., Mzoughi, O., Shahid, M. A., Alturki, N., & Saidani, O. (2024). Principal Component Analysis (PCA) and feature importance‑based dimension reduction for Reference Evapotranspiration (ET0) predictions of Taif, Saudi Arabia. Computers and Electronics in Agriculture, 222, 109036. https://doi.org/10.1016/j.compag.2024.109036
Mannan, Abd., Suparto, Suparto & Kusaeri, Kusaeri. (2025). Practices and Challenges of the Validity of Exploratory Factor Analysis (EFA)-Based Assessment Instruments: A Systematic Literature Review 2020–2025. EDUKASIA Jurnal Pendidikan dan Pembelajaran. 10.62775/edukasia.v6i1.1463
Tavakol, M., & Wetzel, A. (2020). Factor Analysis: a means for theory and instrument development in support of construct validity. International journal of medical education, 11, 245–247. https://doi.org/10.5116/ijme.5f96.0f4a
Wickham, H., & Grolemund, G. (2022). R for data science: Import, tidy, transform, visualize, and model data (Online version). Retrieved from https://r4ds.hadley.nz/missing-values.html
Zhang, Q., Zhou, T., & Li, F. (2021). Climate variability and extreme weather events under global warming: A review of recent advances. Earth-Science Reviews, 221, 103787. https://doi.org/10.1016/j.earscirev.2021.103787
Dataset: Agarwal, R. (n.d.). Max Planck Weather Dataset. Kaggle. https://www.kaggle.com/datasets/arashnic/max-planck-weather-dataset