Kalibrasi Data GPM dengan Data BMKG
Latar Belakang
GPM IMERG adalah produk curah hujan satelit presisi tinggi dari NASA dengan resolusi 0.1° × 0.1° dan temporal 30 menit. Namun dalam analisis hidrologi — khususnya untuk menentukan Hujan Harian Maksimum Tahunan (HHMT) sebagai input desain bangunan air — data mentah (raw) GPM sering menunjukkan bias sistematis negatif yang signifikan dibandingkan observasi BMKG di lapangan.
PBIAS = −31.9% artinya GPM Raw secara rata-rata meremehkan curah hujan sebesar hampir sepertiga dari nilai sesungguhnya. NSE = −1.06 menunjukkan model bahkan lebih buruk dari sekedar menggunakan nilai rata-rata — tidak layak digunakan langsung untuk desain hidrologi.
Setelah kalibrasi dengan metode Year-Specific Scaling Factor (M4), PBIAS turun menjadi +3.5% — hampir tidak ada bias. NSE meningkat ke 0.77 dan KGE ke 0.88, keduanya masuk kategori Sangat Baik menurut SNI 2415:2016.
Data & Wilayah Studi
Analisis berfokus pada satu piksel GPM IMERG V07 yang merepresentasikan wilayah Kota Banjarmasin, yang selanjutnya disebut Piksel B4.
114.60°E, 3.30°S
Bounding Box: 114.487–114.687°E, 3.197–3.397°S
GPM IMERG V07 Final Run (NASA Giovanni)
Resolusi: 0.1° × 0.1° · Temporal: Daily
Variabel: Presipitasi harian (mm)
Lokasi: Banjarmasin, Kalimantan Selatan
Piksel GPM-nya: 114.80°E, 3.40°S
Periode: 1998–2025 (28 tahun)
Catatan: Tahun 2010 data = 0 mm (tidak valid, hanya BMKG Kalsel yang digunakan)
Lokasi: Banjarbaru, Kalimantan Selatan
Piksel GPM-nya: 114.85°E, 3.45°S
Periode: 1998–2025 (28 tahun)
Catatan: Digunakan sebagai data pembanding & pengisi ketika SY tidak tersedia
| Tahun | GPM Raw (mm) | Fk M4 | GPM M4 (mm) | Obs BMKG (mm) | Error Raw (mm) | Error M4 (mm) |
|---|
Metode Koreksi Bias M4
Terdapat beberapa metode koreksi bias yang umum digunakan dalam hidrologi berbasis data satelit. Analisis ini membandingkan empat metode (M1–M4) dan memilih M4: Year-Specific Scaling Factor sebagai yang terbaik.
| Metode | Prinsip | Keunggulan | Keterbatasan | Status |
|---|---|---|---|---|
| M1 — CF Bulanan | GPM × faktor koreksi per bulan HHMT | Mempertimbangkan musim | CF dihitung hanya dari 1 stasiun | Cukup Baik |
| M2 — Direct Scaling | GPM × (rerata Obs / rerata GPM) global | Sangat sederhana | Satu faktor untuk semua tahun | Cukup Baik |
| M3 — Quantile Mapping | Rank-to-rank GPM vs Obs (CDF matching) | Koreksi distribusi penuh | Butuh data lebih banyak; asumsi stasioner | Baik |
| M4 — Year-Specific ✅ | GPM × Fk per tahun dari semua stasiun tersedia | Fk unik tiap tahun, multi-stasiun | Butuh data BMKG per tahun | 🏆 Terbaik |
Hasil Visualisasi

GPM Raw secara konsisten berada di bawah observasi BMKG sepanjang 28 tahun — mencerminkan bias negatif yang sistematis. Setelah kalibrasi M4, GPM M4 (garis navy) mengikuti pola observasi BMKG dengan sangat baik, termasuk menangkap puncak ekstrem tahun 2021 (252.2 mm) yang berkorelasi dengan banjir besar Banjarmasin Januari 2021.


Metrik Validasi Statistik
| Metrik | GPM Raw (M0) | GPM M4 | Threshold SB | Status M4 |
|---|---|---|---|---|
| R (Korelasi Pearson) | 0.373 | 0.900 | ≥ 0.75 | ✅ SB |
| R² (Koef. Determinasi) | 0.139 | 0.811 | ≥ 0.75 | ✅ SB |
| NSE (Nash-Sutcliffe Eff.) | −1.062 | 0.772 | ≥ 0.75 | ✅ SB |
| KGE (Kling-Gupta Eff.) | 0.206 | 0.879 | ≥ 0.75 | ✅ SB |
| PBIAS (%) | −31.9% | +3.5% | |PBIAS| < 10% | ✅ SB |
| RMSE (mm) | 47.44 mm | 15.79 mm | Min (↓) | ✅ −67% |
| MAE (mm) | 38.72 mm | 11.14 mm | Min (↓) | ✅ −71% |
NSE = 1 adalah sempurna. NSE = 0 berarti model sama akuratnya dengan rata-rata observasi. NSE < 0 berarti model lebih buruk dari rata-rata. GPM Raw dengan NSE = −1.06 sangat tidak layak. GPM M4 dengan NSE = 0.77 masuk kategori Sangat Baik.
KGE menggabungkan korelasi, bias, dan variabilitas dalam satu metrik. KGE ≥ 0.75 = Sangat Baik. KGE GPM M4 = 0.879 menunjukkan keseimbangan yang baik antara tiga komponen tersebut — model tidak hanya berkorelasi tinggi, tapi juga reproduksi variabilitasnya bagus.
Distribusi Faktor Koreksi (Fk)
1.402
GPM secara rata-rata meremehkan observasi sebesar ~40%. Fk > 1 artinya observasi lebih tinggi dari GPM.
Min: 0.842 (2011) — tahun saat GPM justru lebih tinggi
Max: 2.466 (2014) — GPM sangat meremehkan
StDev: ±0.37 (variasi antar tahun tinggi)
Tahun dengan Fk > 2.0 (2014, 2020, 2021, 2022, 2023) adalah tahun-tahun dengan curah hujan ekstrem tinggi di Banjarmasin — satelit GPM secara struktural kesulitan menangkap puncak intensitas.
Kode R — Reproduksi Analisis
Seluruh analisis dikerjakan menggunakan R dengan package ggplot2, patchwork, readxl, dan dplyr. Kode di bawah dapat langsung dijalankan dengan file Excel yang disediakan.
library(ggplot2); library(readxl); library(patchwork) library(scales); library(dplyr); library(tidyr) library(ggrepel) # label titik scatter plot # ── Baca data utama dari Excel ─────────────────────────────── xl <- "Input_Plot_GPM_NoWMO.xlsx" df <- read_excel(xl, sheet = "DATA_UTAMA", skip = 3) met <- read_excel(xl, sheet = "METRIK_VALIDASI", skip = 3) # ── Bersihkan nama kolom & konversi tipe data ──────────────── df <- df |> rename(raw = `GPM_Raw (mm)`, m4 = `M4_Baru (mm)`, obs = `Obs_BMKG (mm)`, fk = `Fk_Baru (rata²)`) |> filter(!is.na(Tahun)) |> mutate(across(c(Tahun, raw, m4, obs, fk), as.numeric), tahun = as.integer(Tahun), err_raw = raw - obs, err_m4 = m4 - obs)
# ── Data referensi: HHMT dari stasiun BMKG & piksel GPM ───── # Asumsi: df sudah memiliki kolom gnd_sy, gnd_ks, gpm_b4 df <- df |> mutate( # Fk per stasiun = BMKG / GPM_B4 (untuk setiap tahun) fk_sy = gnd_sy / gpm_b4, fk_ks = gnd_ks / gpm_b4, # Fk final = rata-rata stasiun yang tersedia # Jika salah satu NA (mis. 2010: gnd_sy = 0), gunakan yang ada fk_m4 = case_when( is.na(fk_sy) | gnd_sy == 0 ~ fk_ks, is.na(fk_ks) ~ fk_sy, .default ~ mean(c(fk_sy, fk_ks)) ), # Terapkan Fk ke GPM Raw piksel B4 gpm_m4 = gpm_b4 * fk_m4 ) # ── Ringkasan statistik ────────────────────────────────────── cat("Median Fk:", round(median(df$fk_m4, na.rm = TRUE), 3), " ") cat("Rentang:", round(min(df$fk_m4), 3), "–", round(max(df$fk_m4), 3), " ")
# ── Fungsi hitung metrik validasi ─────────────────────────── hitung_metrik <- function(sim, obs) { n <- length(sim) bias <- sim - obs R_val <- cor(obs, sim) NSE <- 1 - sum(bias^2) / sum((obs - mean(obs))^2) KGE <- 1 - sqrt((R_val-1)^2 + (sd(sim)/sd(obs)-1)^2 + (mean(sim)/mean(obs)-1)^2) PBIAS <- sum(bias) / sum(obs) * 100 RMSE <- sqrt(mean(bias^2)) MAE <- mean(abs(bias)) data.frame(R=R_val, NSE=NSE, KGE=KGE, PBIAS=PBIAS, RMSE=RMSE, MAE=MAE) } # ── Bandingkan M0 (Raw) vs M4 ──────────────────────────────── metrik_raw <- hitung_metrik(df$raw, df$obs) metrik_m4 <- hitung_metrik(df$m4, df$obs) bind_rows( mutate(metrik_raw, Metode = "GPM Raw"), mutate(metrik_m4, Metode = "GPM M4") ) |> select(Metode, R, NSE, KGE, PBIAS, RMSE, MAE)
# ── Reshape ke long format untuk ggplot ────────────────────── df_long <- df |> select(tahun, raw, m4, obs) |> pivot_longer(c(raw, m4, obs), names_to = "seri", values_to = "hhmt") |> mutate(seri = factor(seri, levels = c("obs", "m4", "raw"), labels = c("Obs BMKG", "GPM M4 (Koreksi)", "GPM Raw"))) p1 <- ggplot(df_long, aes(x = tahun, y = hhmt, color = seri, linetype = seri, linewidth = seri)) + geom_line(na.rm = TRUE) + geom_point(data = . |> filter(seri == "Obs BMKG"), size = 1.8, shape = 21) + geom_label(data = df |> filter(m4 > 200), aes(x = tahun, y = m4 + 8, label = paste0(tahun, " ", m4, "mm")), inherit.aes = FALSE, size = 2.8, color = "#1A5276") + scale_color_manual( values = c("Obs BMKG"="#B45309", "GPM M4 (Koreksi)"="#1A5276", "GPM Raw"="#B91C1C"), name = NULL) + scale_linetype_manual( values = c("Obs BMKG"="dashed", "GPM M4 (Koreksi)"="solid", "GPM Raw"="solid"), name = NULL) + scale_y_continuous( limits = c(0, 280), labels = function(x) paste0(x, " mm")) + labs( title = "Time Series HHMT Tahunan", subtitle = "GPM Raw vs GPM M4 vs Observasi BMKG | 1998–2025", x = NULL, y = "HHMT (mm)", caption = "Sumber: GPM IMERG V07 (NASA) | BMKG Syamsuddin Noor + BMKG Kalsel" ) + theme_minimal(base_size = 11) + theme(plot.title = element_text(face = "bold")) # ── Scatter Plot: M4 vs Obs ─────────────────────────────────── p_scatter <- ggplot(df, aes(x = obs, y = m4)) + geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "#94A3B8") + geom_point(color = "#1A5276", size = 3, shape = 21) + ggrepel::geom_text_repel(aes(label = tahun), size = 2.5, color = "#475569") + geom_smooth(method = "lm", se = TRUE, color = "#1A5276", fill = "#1A527622") + coord_equal() + labs(title = "Scatter: GPM M4 vs Obs BMKG", x = "Observasi BMKG (mm)", y = "GPM M4 (mm)") # ── Gabung & simpan ────────────────────────────────────────── fig_final <- p1 / p_scatter + plot_annotation( title = "Koreksi Bias GPM IMERG V07 — WPG Banjarmasin", caption = "SNI 2415:2016 | Teutschbein & Seibert (2012)") ggsave("hasil_kalibrasi_gpm.png", fig_final, width = 36, height = 30, units = "cm", dpi = 300)
Kesimpulan
📚 Moriasi et al. (2007) — Model Evaluation Guidelines
📚 Teutschbein & Seibert (2012) — Bias Correction Methods
📚 Knoben et al. (2019) — KGE Commentary
📚 SNI 2415:2016 — Tata Cara Perhitungan Debit Banjir Rencana
🛰️ NASA GPM IMERG V07 Final Run
🌧️ BMKG Stasiun Syamsuddin Noor & BMKG Kalsel
⚠️ Fk bersifat historis — proyeksi masa depan asumsi Fk = median
⚠️ Hanya 2 stasiun BMKG — wilayah DAS besar butuh lebih banyak
⚠️ Koreksi bias pada level HHMT — bukan distribusi harian penuh
🔭 Pengembangan: uji pada stasiun lain & periode lebih panjang
🔭 Kombinasikan M4 dengan M3 (Quantile Mapping) untuk distribusi
Diskusi metodologi, data, atau implementasi di proyekmu
Hubungi saya →