# --- Φόρτωση δεδομένων ---
data("JohnsonJohnson")
jj <- JohnsonJohnson
class(jj) # έλεγχος: είναι ήδη ts object;
## [1] "ts"
start(jj); end(jj); frequency(jj)
## [1] 1960 1
## [1] 1980 4
## [1] 4
length(jj) # 84 παρατηρήσεις (21 χρόνια × 4 τρίμηνα)
## [1] 84
head(jj, 12)
## Qtr1 Qtr2 Qtr3 Qtr4
## 1960 0.71 0.63 0.85 0.44
## 1961 0.61 0.69 0.92 0.55
## 1962 0.72 0.77 0.92 0.60
autoplot(jj) +
ggtitle("Johnson & Johnson Quarterly Earnings") +
xlab("Έτος") + ylab("Κέρδη") +
theme_minimal()
Ως αναλυτής, βλέπω μια σαφή ανοδική τάση στα κέρδη της εταιρείας.
Παράλληλα, παρατηρώ έντονη εποχικότητα που επαναλαμβάνεται κάθε έτος.
Είναι σημαντικό να σημειωθεί ότι το πλάτος των εποχικών διακυμάνσεων
αυξάνεται όσο αυξάνεται η τάση, γεγονός που υποδηλώνει ότι η εποχικότητα
εξαρτάται από το μέγεθος των κερδών (multiplicative decomposition).
# Εποχικό plot (σύγκριση ετών)
ggseasonplot(jj, polar = FALSE) + ggtitle("Εποχικό Plot")
# Subseries plot (μέσος όρος ανά τρίμηνο)
ggsubseriesplot(jj) + ggtitle("Subseries Plot")
Είναι multiplicative γιατί οι διακυμάνσεις έχουν μεγαλύτερο πλάτος καθώς αυξάνεται η τάση. Σε ένα addictive μοντέλο οι διακυμάνσεις θα έπρεπε να έχουν σταθερό πλάτος.
decomp <- decompose(jj, type = "multiplicative")
autoplot(decomp) + theme_minimal()
p1 <- autoplot(jj) + ggtitle("Αρχική Σειρά")
p2 <- autoplot(log(jj)) + ggtitle("Με Log transformation")
grid.arrange(p1, p2, ncol=2)
Μετά τον λογάριθμο, το πλάτος των εποχικών διακυμάνσεων σταθεροποιείται.
Το log() μετατρέπει μια πολλαπλασιαστική σχέση σε μια προσθετική
(additive) σχέση. Αυτό κάνει τα δεδομένα πιο εύκολα στην ανάλυση και
στην πρόβλεψη.
train <- window(jj, end = c(1978, 4))
test <- window(jj, start = c(1979, 1))
adf.test(train)
## Warning in adf.test(train): p-value greater than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: train
## Dickey-Fuller = 0.85296, Lag order = 4, p-value = 0.99
## alternative hypothesis: stationary
train_diff <- diff(diff(log(train), lag = 4))
adf.test(train_diff)
## Warning in adf.test(train_diff): p-value smaller than printed p-value
##
## Augmented Dickey-Fuller Test
##
## data: train_diff
## Dickey-Fuller = -6.3584, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary
ggAcf(train_diff)
ggPacf(train_diff)
fit_snaive <- snaive(train, h = 8)
fit_hw <- hw(train, h = 8, seasonal = "multiplicative")
# ARIMA
fit_arima <- auto.arima(train, lambda = 0)
fc_arima <- forecast(fit_arima, h = 8)
summary(fit_snaive)
##
## Forecast method: Seasonal naive method
##
## Model Information:
## Call: snaive(y = train, h = 8)
##
## Residual sd: 0.8214
##
## Error measures:
## ME RMSE MAE MPE MAPE MASE ACF1
## Training set 0.5884722 0.8214427 0.5920833 14.27463 14.77554 1 0.6642405
##
## Forecasts:
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## 1979 Q1 11.88 10.827279 12.932721 10.270002 13.49000
## 1979 Q2 12.06 11.007279 13.112721 10.450002 13.67000
## 1979 Q3 12.15 11.097279 13.202721 10.540002 13.76000
## 1979 Q4 8.91 7.857279 9.962721 7.300002 10.52000
## 1980 Q1 11.88 10.391227 13.368773 9.603119 14.15688
## 1980 Q2 12.06 10.571227 13.548773 9.783119 14.33688
## 1980 Q3 12.15 10.661227 13.638773 9.873119 14.42688
## 1980 Q4 8.91 7.421227 10.398773 6.633119 11.18688
summary(fit_hw)
##
## Forecast method: Holt-Winters' multiplicative method
##
## Model Information:
## Holt-Winters' multiplicative method
##
## Call:
## hw(y = train, h = 8, seasonal = "multiplicative")
##
## Smoothing parameters:
## alpha = 0.197
## beta = 0.1082
## gamma = 1e-04
##
## Initial states:
## l = 0.5902
## b = 0.0072
## s = 0.8267 1.0468 1.0827 1.0439
##
## sigma: 0.1337
##
## AIC AICc BIC
## 174.6172 177.3444 195.5938
##
## Error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.0420402 0.3595992 0.2602222 0.5285725 9.289055 0.4395027
## ACF1
## Training set 0.1282904
##
## Forecasts:
## Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
## 1979 Q1 12.83495 10.636472 15.03343 9.472669 16.19723
## 1979 Q2 13.76326 11.303396 16.22312 10.001224 17.52529
## 1979 Q3 13.74580 11.122117 16.36949 9.733221 17.75839
## 1979 Q4 11.19950 8.872544 13.52645 7.640730 14.75826
## 1980 Q1 14.57307 11.235132 17.91102 9.468132 19.67802
## 1980 Q2 15.56606 11.610776 19.52135 9.516974 21.61515
## 1980 Q3 15.48923 11.116368 19.86209 8.801514 22.17695
## 1980 Q4 12.57631 8.637829 16.51479 6.552923 18.59970
summary(fit_arima)
## Series: train
## ARIMA(2,0,0)(1,1,0)[4] with drift
## Box Cox transformation: lambda= 0
##
## Coefficients:
## ar1 ar2 sar1 drift
## 0.3131 0.2432 -0.2970 0.0386
## s.e. 0.1244 0.1300 0.1285 0.0046
##
## sigma^2 = 0.008377: log likelihood = 71.78
## AIC=-133.56 AICc=-132.65 BIC=-122.18
##
## Training set error measures:
## ME RMSE MAE MPE MAPE MASE
## Training set 0.001523642 0.3596867 0.2419193 -0.16328 6.770657 0.4085899
## ACF1
## Training set -0.1186641
# Έλεγχος για το καλύτερο μοντέλο (συνήθως το ARIMA ή το HW)
checkresiduals(fit_arima)
##
## Ljung-Box test
##
## data: Residuals from ARIMA(2,0,0)(1,1,0)[4] with drift
## Q* = 3.7985, df = 5, p-value = 0.5788
##
## Model df: 3. Total lags used: 8
autoplot(train) +
autolayer(test, series = "Πραγματικά") +
autolayer(fit_snaive$mean, series = "Seasonal Naïve") +
autolayer(fit_hw$mean, series = "Holt-Winters") +
autolayer(fc_arima$mean, series = "ARIMA") +
ggtitle("Σύγκριση Προβλέψεων με Πραγματικά Δεδομένα") +
xlab("Έτος") + ylab("Κέρδη") +
guides(colour=guide_legend(title="Μοντέλο")) +
theme_minimal()
#Accurasy Metrics
acc_snaive <- accuracy(fit_snaive, test)[2,]
acc_hw <- accuracy(fit_hw, test)[2,]
acc_arima <- accuracy(fc_arima, test)[2,]
comparison_table <- rbind(acc_snaive, acc_hw, acc_arima)
rownames(comparison_table) <- c("SNaive", "Holt-Winters", "ARIMA")
# Εμφάνιση του πίνακα
print(comparison_table[, c("RMSE", "MAE", "MAPE")])
## RMSE MAE MAPE
## SNaive 2.7765401 2.5425000 17.899110
## Holt-Winters 1.0865532 1.0427583 7.763851
## ARIMA 0.8136629 0.7225012 5.419212
Το μοντέλο που νικά είναι αυτό με τη μικρότερη τιμή RMSE δηλαδή το ARIMA
final_model <- auto.arima(jj, lambda = 0)
final_fc <- forecast(final_model, h = 12)
autoplot(final_fc) +
ggtitle("Τελική Πρόβλεψη κερδών J&J για τα επόμενα 3 χρόνια") +
xlab("Έτος") + ylab("Κέρδη") +
theme_minimal()