Peubah yang digunakan: - TMA = Tinggi Muka Air (peubah respon) - RH = Kelembapan relatif Kota Bogor (peubah penjelas)
library(readxl)
## Warning: package 'readxl' was built under R version 4.5.2
library(dplyr)
##
## 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(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.5.3
library(moments)
## Warning: package 'moments' was built under R version 4.5.2
library(ggcorrplot)
## Warning: package 'ggcorrplot' was built under R version 4.5.3
library(corrplot)
## Warning: package 'corrplot' was built under R version 4.5.2
## corrplot 0.95 loaded
library(forecast)
## Warning: package 'forecast' was built under R version 4.5.3
library(urca)
library(tseries)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
library(dynlm)
## Warning: package 'dynlm' was built under R version 4.5.3
## Loading required package: zoo
##
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
##
## as.Date, as.Date.numeric
library(dLagM)
## Warning: package 'dLagM' was built under R version 4.5.3
## Loading required package: nardl
## Warning: package 'nardl' was built under R version 4.5.3
##
## Attaching package: 'dLagM'
## The following object is masked from 'package:forecast':
##
## forecast
library(lmtest)
library(car)
## Warning: package 'car' was built under R version 4.5.2
## Loading required package: carData
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
library(ARDL)
## Warning: package 'ARDL' was built under R version 4.5.3
## To cite the ARDL package in publications:
##
## Use this reference to refer to the validity of the ARDL package.
##
## Natsiopoulos, Kleanthis, and Tzeremes, Nickolaos G. (2022). ARDL
## bounds test for cointegration: Replicating the Pesaran et al. (2001)
## results for the UK earnings equation using R. Journal of Applied
## Econometrics, 37(5), 1079-1090. https://doi.org/10.1002/jae.2919
##
## Use this reference to cite this specific version of the ARDL package.
##
## Kleanthis Natsiopoulos, Nickolaos Tzeremes and Daniel Finnan (2026).
## ARDL: ARDL, ECM and Bounds-Test for Cointegration. R package version
## 0.2.5. https://CRAN.R-project.org/package=ARDL
library(tidyr)
## Warning: package 'tidyr' was built under R version 4.5.3
library(MASS)
##
## Attaching package: 'MASS'
## The following object is masked from 'package:dplyr':
##
## select
library(patchwork)
## Warning: package 'patchwork' was built under R version 4.5.2
##
## Attaching package: 'patchwork'
## The following object is masked from 'package:MASS':
##
## area
library(dynlm)
library(nardl)
library(writexl)
## Warning: package 'writexl' was built under R version 4.5.2
library(openxlsx2)
## Warning: package 'openxlsx2' was built under R version 4.5.3
##
## Attaching package: 'openxlsx2'
## The following object is masked from 'package:writexl':
##
## write_xlsx
## The following object is masked from 'package:readxl':
##
## read_xlsx
library(dynamac)
## Warning: package 'dynamac' was built under R version 4.5.3
##
## Attaching package: 'dynamac'
## The following object is masked from 'package:nardl':
##
## pssbounds
library(e1071)
## Warning: package 'e1071' was built under R version 4.5.3
##
## Attaching package: 'e1071'
## The following objects are masked from 'package:moments':
##
## kurtosis, moment, skewness
## The following object is masked from 'package:ggplot2':
##
## element
dataset <- read_excel("C:\\Users\\ASUS\\Downloads\\Data_Harian_2022_2024.xlsx")
str(dataset)
## tibble [1,096 × 6] (S3: tbl_df/tbl/data.frame)
## $ Date: POSIXct[1:1096], format: "2022-01-01" "2022-01-02" ...
## $ TMA : num [1:1096] 595 588 580 576 574 ...
## $ TM : num [1:1096] 24.1 24.2 24.8 24.9 25.5 ...
## $ PC : num [1:1096] 0.85 1.79 0.4 0.22 5.7 ...
## $ RH : num [1:1096] 86.4 88.1 83.2 80.3 83.2 ...
## $ WS : num [1:1096] 2.08 2.25 1.56 1.11 0.79 1.38 1.92 1.35 1.82 1.41 ...
summary(dataset)
## Date TMA TM
## Min. :2022-01-01 00:00:00 Min. :555.4 Min. :22.85
## 1st Qu.:2022-10-01 18:00:00 1st Qu.:597.7 1st Qu.:24.57
## Median :2023-07-02 12:00:00 Median :620.0 Median :25.10
## Mean :2023-07-02 12:00:00 Mean :625.3 Mean :25.18
## 3rd Qu.:2024-04-01 06:00:00 3rd Qu.:650.1 3rd Qu.:25.78
## Max. :2024-12-31 00:00:00 Max. :781.2 Max. :27.97
## PC RH WS
## Min. : 0.0000 Min. :67.03 Min. :0.460
## 1st Qu.: 0.7375 1st Qu.:82.92 1st Qu.:1.010
## Median : 4.0000 Median :86.29 Median :1.230
## Mean : 6.5700 Mean :85.29 Mean :1.377
## 3rd Qu.: 9.1325 3rd Qu.:88.53 3rd Qu.:1.583
## Max. :145.0300 Max. :94.31 Max. :3.700
sd_rh <- sd(dataset$RH, na.rm = TRUE)
sd_rh
## [1] 4.710888
skew_rh <- skewness(dataset$RH, na.rm = TRUE)
skew_rh
## [1] -0.986807
kurt_rh <- kurtosis(dataset$RH, na.rm = TRUE)
kurt_rh
## [1] 1.017691
ggplot(data = dataset, aes(x = Date, y = RH)) +
geom_line() +
labs(title = "Time Series Plot of RH", x = "Date", y = "RH") +
theme_minimal()
total_rows <- 1096
test_size <- 160
train_index <- 1:(total_rows - test_size)
test_index <- (total_rows - test_size + 1):total_rows
train_2225 <- dataset[train_index, ]
test_2225 <- dataset[test_index, ]
str(train_2225)
## tibble [936 × 6] (S3: tbl_df/tbl/data.frame)
## $ Date: POSIXct[1:936], format: "2022-01-01" "2022-01-02" ...
## $ TMA : num [1:936] 595 588 580 576 574 ...
## $ TM : num [1:936] 24.1 24.2 24.8 24.9 25.5 ...
## $ PC : num [1:936] 0.85 1.79 0.4 0.22 5.7 ...
## $ RH : num [1:936] 86.4 88.1 83.2 80.3 83.2 ...
## $ WS : num [1:936] 2.08 2.25 1.56 1.11 0.79 1.38 1.92 1.35 1.82 1.41 ...
Data dibagi menjadi data train sebesar 86% dari total data (936 data) dan data test sebesar 14% (160 data).
str(test_2225)
## tibble [160 × 6] (S3: tbl_df/tbl/data.frame)
## $ Date: POSIXct[1:160], format: "2024-07-25" "2024-07-26" ...
## $ TMA : num [1:160] 600 600 600 600 600 ...
## $ TM : num [1:160] 24.4 24.9 24.9 24.7 24.5 ...
## $ PC : num [1:160] 0.01 0.01 0 0 0 ...
## $ RH : num [1:160] 85.3 84.4 82.3 82.3 81.6 ...
## $ WS : num [1:160] 1.32 1.13 1.24 1.01 1.16 1.35 1.25 1.01 0.98 0.99 ...
train_2225.ts<-ts(train_2225)
test_2225.ts<-ts(test_2225)
train_2225 <- train_2225 %>%
mutate(DataType = "Train")
test_2225 <- test_2225 %>%
mutate(DataType = "Test")
combined_data <- bind_rows(train_2225, test_2225)
data_long <- combined_data %>%
pivot_longer(cols = c(RH),
names_to = "Variabel",
values_to = "Nilai")
ggplot(data_long, aes(x = Date, y = Nilai, color = DataType)) +
geom_line() +
facet_wrap(~ Variabel, scales = "free_y", ncol = 2) +
scale_color_manual(values = c("Train" = "#00BFC4", "Test" = "#F8766D")) +
labs(title = "Time Series of RH (Train vs. Test)",
x = "Date",
y = "Kelembapan Relatif (persen)",
color = "Data Type") +
theme_minimal()
acf_RH <- ggAcf(train_2225$RH) + labs(title = "ACF RH")
acf_RH
plot ACF yang menurun secara perlahan mengindikasikan data tidak stasioner.
acf_RH <- ggAcf(train_2225$RH) +
labs(title = "ACF RH") +
theme(
axis.text.x = element_text(size = 14),
axis.text.y = element_text(size = 14)
)
acf_RH
pacf_RH <- ggPacf(train_2225$RH) + labs(title = "PACF RH")
pacf_RH
adf.test(train_2225$RH)
##
## Augmented Dickey-Fuller Test
##
## data: train_2225$RH
## Dickey-Fuller = -3.3561, Lag order = 9, p-value = 0.06101
## alternative hypothesis: stationary
ccf_result3 <- ggCcf(train_2225$TMA, train_2225$RH, lag.max=9, plot = TRUE)+ggtitle("CCF antara TMA dan RH")
ccf_result3
DTMA <- diff(train_2225$TMA, differences = 1)
DPC <- diff(train_2225$PC, differences = 1)
DTM <- diff(train_2225$TM, differences = 1)
DRH <- diff(train_2225$RH, differences = 1)
DWS <- diff(train_2225$WS, differences = 1)
# Gabungkan dalam dataframe
df <- data.frame(DTMA, DPC, DTM, DRH, DWS)
df.ts<-ts(df)
head(df)
## DTMA DPC DTM DRH DWS
## 1 -7.708333 0.94 0.12 1.75 0.17
## 2 -7.500000 -1.39 0.54 -4.93 -0.69
## 3 -4.375000 -0.18 0.16 -2.91 -0.45
## 4 -1.458333 5.48 0.57 2.87 -0.32
## 5 9.583333 3.75 -0.58 2.39 0.59
## 6 -10.208333 6.72 -0.80 4.06 0.54
acf_DRH <- ggAcf(DRH) + labs(title = "ACF DRH")
acf_DRH
acf_DRH <- ggAcf(DRH) +
labs(title = "ACF DRH") +
theme(
axis.text.x = element_text(size = 14),
axis.text.y = element_text(size = 14)
)
acf_DRH
pacf_DRH <- ggPacf(DRH) + labs(title = "PACF DRH")
pacf_DRH
adf.test(DRH)
## Warning in adf.test(DRH): p-value smaller than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: DRH
## Dickey-Fuller = -13.91, Lag order = 9, p-value = 0.01
## alternative hypothesis: stationary
ccf_result3 <- ggCcf(DTMA, DRH, lag.max=9, plot = TRUE)+ggtitle("CCF antara DTMA dan DRH")
ccf_result3
ccf_result1 <- ggCcf(DTMA, DRH, lag.max = 9) +
ggtitle("CCF antara DTMA dan DRH") +
theme(
axis.text.x = element_text(size = 14), # Besarkan angka di sumbu X
axis.text.y = element_text(size = 14) # Besarkan angka di sumbu Y
)
ccf_result1
modelbound <- ardlBound(
data = as.data.frame(train_2225[, c("TMA", "RH")]),
formula = TMA ~ RH,
case = 2,
max.p = 1,
max.q = 9
)
##
## Orders being calculated with max.p = 1 and max.q = 9 ...
##
## Autoregressive order: 10 and p-orders: 2
## ------------------------------------------------------
##
## Breusch-Godfrey Test for the autocorrelation in residuals:
##
## Breusch-Godfrey test for serial correlation of order up to 1
##
## data: modelFull$model
## LM test = 0.72021, df1 = 1, df2 = 911, p-value = 0.3963
##
## ------------------------------------------------------
##
## Ljung-Box Test for the autocorrelation in residuals:
##
## Box-Ljung test
##
## data: res
## X-squared = 0.011403, df = 1, p-value = 0.915
##
## ------------------------------------------------------
##
## Breusch-Pagan Test for the homoskedasticity of residuals:
##
## studentized Breusch-Pagan test
##
## data: modelFull$model
## BP = 28.001, df = 13, p-value = 0.009047
##
## The p-value of Breusch-Pagan test for the homoskedasticity of residuals: 0.009046565 < 0.05!
## ------------------------------------------------------
##
## Shapiro-Wilk test of normality of residuals:
##
## Shapiro-Wilk normality test
##
## data: modelFull$model$residual
## W = 0.88414, p-value < 2.2e-16
##
## The p-value of Shapiro-Wilk test normality of residuals: 9.937552e-26 < 0.05!
## ------------------------------------------------------
##
## PESARAN, SHIN AND SMITH (2001) COINTEGRATION TEST
##
## Observations: 935
## Number of Regressors (k): 1
## Case: 2
##
## ------------------------------------------------------
## - F-test -
## ------------------------------------------------------
## <------- I(0) ------------ I(1) ----->
## 10% critical value 3.02 3.51
## 5% critical value 3.62 4.16
## 1% critical value 4.94 5.58
##
##
## F-statistic = 12.5612281845871
##
## ------------------------------------------------------
## F-statistic note: Asymptotic critical values used.
##
## ------------------------------------------------------
##
## Ramsey's RESET Test for model specification:
##
## RESET test
##
## data: modelECM$model
## RESET = 0.1483, df1 = 1, df2 = 913, p-value = 0.7003
##
## ------------------------------------------------------
## ------------------------------------------------------
## Error Correction Model Output:
##
## Time series regression with "ts" data:
## Start = 10, End = 935
##
## Call:
## dynlm(formula = as.formula(model.text), data = data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -47.265 -13.466 -3.586 7.973 146.539
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## ec.1 -0.15913 0.02589 -6.145 1.19e-09 ***
## dRH.t 1.51125 0.30519 4.952 8.75e-07 ***
## dRH.1 1.16648 0.31250 3.733 0.000201 ***
## dTMA.1 -0.36909 0.03683 -10.022 < 2e-16 ***
## dTMA.2 -0.22712 0.03788 -5.996 2.91e-09 ***
## dTMA.3 -0.12968 0.03848 -3.370 0.000783 ***
## dTMA.4 -0.08047 0.03843 -2.094 0.036546 *
## dTMA.5 -0.11085 0.03803 -2.915 0.003649 **
## dTMA.6 -0.09482 0.03769 -2.516 0.012051 *
## dTMA.7 -0.07525 0.03701 -2.033 0.042304 *
## dTMA.8 -0.03551 0.03548 -1.001 0.317201
## dTMA.9 0.02205 0.03196 0.690 0.490471
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.1 on 914 degrees of freedom
## Multiple R-squared: 0.2548, Adjusted R-squared: 0.245
## F-statistic: 26.04 on 12 and 914 DF, p-value: < 2.2e-16
##
## ------------------------------------------------------
## Long-run coefficients:
## TMA.1 RH.1
## -0.1591344 1.0241813
##
Kointegrasi terjadi jika F-statistic > batas atas (I(1)) critical value.
modelardl <- dynardl(
DTMA ~ DRH,
data = df,
lags = list(
"DTMA" = 1:9,
"DRH" = 1
),
ec = TRUE
)
## [1] "Error correction (EC) specified; dependent variable to be run in differences."
summary(modelardl)
##
## Call:
## lm(formula = as.formula(paste(paste(dvnamelist), "~", paste(colnames(IVs),
## collapse = "+"), collapse = " ")))
##
## Residuals:
## Min 1Q Median 3Q Max
## -50.489 -12.860 -3.271 6.958 148.496
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.082860 0.780800 0.106 0.915509
## l.1.DTMA -1.485002 0.032839 -45.220 < 2e-16 ***
## l.2.DTMA -0.317888 0.036136 -8.797 < 2e-16 ***
## l.3.DTMA -0.217508 0.037437 -5.810 8.62e-09 ***
## l.4.DTMA -0.156467 0.037898 -4.129 3.98e-05 ***
## l.5.DTMA -0.178432 0.037740 -4.728 2.62e-06 ***
## l.6.DTMA -0.145611 0.037801 -3.852 0.000125 ***
## l.7.DTMA -0.115795 0.037439 -3.093 0.002042 **
## l.8.DTMA -0.070884 0.036129 -1.962 0.050068 .
## l.9.DTMA 0.003252 0.032739 0.099 0.920900
## l.1.DRH 1.270363 0.296897 4.279 2.08e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 23.76 on 915 degrees of freedom
## (9 observations deleted due to missingness)
## Multiple R-squared: 0.7056, Adjusted R-squared: 0.7024
## F-statistic: 219.3 on 10 and 915 DF, p-value: < 2.2e-16
AIC(modelardl$model)
## [1] 8507.914
res1 <- residuals(modelardl$model)
Box.test(res1, lag = 20, type = "Ljung-Box")
##
## Box-Ljung test
##
## data: res1
## X-squared = 18.846, df = 20, p-value = 0.5318
H0: tidak ada autokorelasi dalam residual; H1: terdapat autokorelasi dalam residual. Jika p-value > 0.05, tak tolak H0.
jarque.bera.test(res1)
##
## Jarque Bera Test
##
## data: res1
## X-squared = 1499.7, df = 2, p-value < 2.2e-16
bptest(modelardl$model)
##
## studentized Breusch-Pagan test
##
## data: modelardl$model
## BP = 18.654, df = 10, p-value = 0.04489
Dengan satu peubah penjelas (RH) di model, multikolinearitas antar peubah penjelas tidak perlu diuji. Lag DRH dan lag DTMA dalam model tetap dapat dicek dengan VIF bila diperlukan.
vif(modelardl$model)
## l.1.DTMA l.2.DTMA l.3.DTMA l.4.DTMA l.5.DTMA l.6.DTMA l.7.DTMA l.8.DTMA
## 1.249778 1.513953 1.625276 1.665838 1.652173 1.657539 1.625984 1.514292
## l.9.DTMA l.1.DRH
## 1.243479 1.020193
# Differencing
DTMA <- diff(train_2225$TMA, differences = 1)
DRH <- diff(train_2225$RH, differences = 1)
train_baru <- data.frame(DRH)
coefs <- summary(modelardl$model)$coefficients
intercept <- coefs["(Intercept)", "Estimate"]
b1 <- coefs["l.1.DRH", "Estimate"]
train_baru$DTMA_pred <- intercept + b1 * train_baru$DRH
train_baru$TMA_pred <- NA
train_baru$TMA_pred[1] <- train_2225$TMA[1] + train_baru$DTMA_pred[1]
for (i in 2:nrow(train_baru)) {
train_baru$TMA_pred[i] <- train_baru$TMA_pred[i - 1] + train_baru$DTMA_pred[i]
}
TMA_actual <- train_2225$TMA[-1]
TMA_pred <- train_baru$TMA_pred
plot(TMA_actual, type = "l", col = "black", main = "Train: Actual vs Predicted TMA")
lines(TMA_pred, col = "blue")
legend("topleft", legend = c("Actual", "Predicted"), col = c("black", "blue"), lty = 1)
# Evaluasi
MAE <- mean(abs(TMA_pred - TMA_actual), na.rm = TRUE)
RMSE <- sqrt(mean((TMA_pred - TMA_actual)^2, na.rm = TRUE))
MAPE <- mean(abs((TMA_actual - TMA_pred) / TMA_actual), na.rm = TRUE) * 100
cat("MAE :", MAE, "\n")
## MAE : 31.5902
cat("RMSE:", RMSE, "\n")
## RMSE: 40.80613
cat("MAPE:", MAPE, "%\n")
## MAPE: 5.095374 %
DRH_test <- diff(c(tail(train_2225$RH, 1), test_2225$RH))
test_baru <- data.frame(DRH = DRH_test)
test_baru$DTMA_pred <- intercept + b1 * test_baru$DRH
test_baru$TMA_pred <- tail(train_2225$TMA, 1) + cumsum(test_baru$DTMA_pred)
TMA_actual_test <- test_2225$TMA
TMA_pred_test <- test_baru$TMA_pred
plot(TMA_actual_test, type = "l", col = "black",
ylim = range(c(TMA_actual_test, TMA_pred_test)),
main = "Test: Actual vs Predicted TMA")
lines(TMA_pred_test, col = "red")
legend("topleft", legend = c("Actual", "Predicted"), col = c("black", "red"), lty = 1)
MAE_t <- mean(abs(TMA_pred_test - TMA_actual_test))
RMSE_t <- sqrt(mean((TMA_pred_test - TMA_actual_test)^2))
MAPE_t <- mean(abs((TMA_actual_test - TMA_pred_test) / TMA_actual_test)) * 100
cat("MAE :", MAE_t, "\n")
## MAE : 19.67632
cat("RMSE:", RMSE_t, "\n")
## RMSE: 27.58166
cat("MAPE:", MAPE_t, "%\n")
## MAPE: 3.056368 %