global_economy %>%
mutate(GDP_per_capita = GDP/Population) %>%
autoplot(GDP_per_capita) +
theme_minimal() +
labs(title = "Global GDP Per Capita Trends") +
theme(legend.position = "none")
gdp_leaders <- global_economy %>%
mutate(GDP_per_capita = GDP/Population) %>%
filter(!is.na(GDP_per_capita)) %>%
as_tibble() %>%
group_by(Year) %>%
slice_max(GDP_per_capita, n = 1)
gdp_leaders %>%
tail(5) %>%
select(Year, Country, GDP_per_capita) %>%
mutate(
GDP_per_capita = scales::comma(round(GDP_per_capita, 0))
) %>%
knitr::kable(
col.names = c("Year", "Country", "GDP per Capita (USD)"),
caption = "Countries with Highest GDP per Capita by Year"
)
Year | Country | GDP per Capita (USD) |
---|---|---|
2013 | Liechtenstein | 173,528 |
2014 | Monaco | 185,153 |
2015 | Liechtenstein | 167,591 |
2016 | Monaco | 168,011 |
2017 | Luxembourg | 104,103 |
Monaco and Liechtenstein consistently lead in GDP per capita. Over time, Luxembourg seems to have come to the forefront, surpassing them both in 2017.
us_data <- global_economy %>% filter(Country == "United States")
us_data %>% autoplot(GDP) + labs(title = "US GDP - Raw Data")
lambda_us <- us_data %>% features(GDP, guerrero) %>% pull(lambda_guerrero)
us_data %>% autoplot(box_cox(GDP, lambda_us)) +
labs(title = paste("US GDP Transformed, λ =", round(lambda_us, 3)))
Box-Cox transformation linearizes the exponential growth pattern and stabilizes variance, making the series easier to model for forecasting.
bulls_data <- aus_livestock %>%
filter(State == "Victoria", Animal == "Bulls, bullocks and steers")
bulls_data %>% autoplot(Count) + labs(title = "Bulls Processing - Victoria")
lambda_bulls <- bulls_data %>% features(Count, guerrero) %>% pull(lambda_guerrero)
bulls_data %>% autoplot(box_cox(Count, lambda_bulls)) +
labs(title = paste("Bulls Data Transformed, λ =", round(lambda_bulls, 3)))
The box cox transformation reduces the volatility that increases with higher slaughter counts, creating more consistent seasonal patterns.
vic_elec %>%
filter(year(Time) == 2014) %>%
autoplot(Demand) +
labs(title = "VIC Power Demand 2014")
No transformation needed - electricity demand shows relatively stable variance across different demand levels.
aus_production %>% autoplot(Gas) + labs(title = "Gas Production - Australia")
lambda_gas <- aus_production %>% features(Gas, guerrero) %>% pull(lambda_guerrero)
aus_production %>% autoplot(box_cox(Gas, lambda_gas)) +
labs(title = paste("Gas Data Stabilized, λ =", round(lambda_gas, 3)))
Box-Cox transformation smooths out the increasing variability in seasonal fluctuations as production levels rise over time.
canadian_gas %>% autoplot(Volume) + labs(title = "Canadian Gas Output Patterns")
canadian_gas %>% gg_season(Volume) + labs(title = "Seasonal Behavior Changes")
Box-Cox doesn’t work well here because the data basically flips its seasonal behavior over time. In the early years, gas production peaked in winter, but later on it switched to peaking in summer instead. Since Box-Cox just tries to stabilize variance, it can’t handle this kind of fundamental pattern shift.
set.seed(98765)
retail_series <- aus_retail %>%
filter(`Series ID` == sample(aus_retail$`Series ID`, 1))
retail_series %>% autoplot(Turnover) + labs(title = "Selected Retail Category")
lambda_retail <- retail_series %>% features(Turnover, guerrero) %>% pull(lambda_guerrero)
cat("Recommended λ:", round(lambda_retail, 3))
## Recommended λ: 0.225
retail_series %>% autoplot(box_cox(Turnover, lambda_retail)) +
labs(title = "Retail Series - Variance Adjusted")
The Guerrero method suggests λ = 0.225, which will help stabilize the variance in this retail series.
lambda_tobacco <- aus_production %>% features(Tobacco, guerrero) %>% pull(lambda_guerrero)
aus_production %>% autoplot(box_cox(Tobacco, lambda_tobacco)) +
labs(title = paste("Tobacco Output Stabilized, λ =", round(lambda_tobacco, 3)))
melb_syd <- ansett %>% filter(Airports == "MEL-SYD", Class == "Economy")
lambda_flights <- melb_syd %>% features(Passengers, guerrero) %>% pull(lambda_guerrero)
melb_syd %>% autoplot(box_cox(Passengers, lambda_flights)) +
labs(title = paste("Flight Passengers Adjusted, λ =", round(lambda_flights, 3)))
pedestrian_daily <- pedestrian %>%
filter(Sensor == "Southern Cross Station") %>%
index_by(Date = as_date(Date_Time)) %>%
summarise(Daily_Count = sum(Count))
lambda_ped <- pedestrian_daily %>% features(Daily_Count, guerrero) %>% pull(lambda_guerrero)
pedestrian_daily %>% autoplot(box_cox(Daily_Count, lambda_ped)) +
labs(title = paste("Pedestrian Flow Adjusted, λ =", round(lambda_ped, 3)))
gas_recent <- tail(aus_production, 5*4) %>% select(Gas)
head(gas_recent)
## # A tsibble: 6 x 2 [1Q]
## Gas Quarter
## <dbl> <qtr>
## 1 221 2005 Q3
## 2 180 2005 Q4
## 3 171 2006 Q1
## 4 224 2006 Q2
## 5 233 2006 Q3
## 6 192 2006 Q4
gas_recent %>% autoplot(Gas) + labs(title = "Recent Gas Production Trends")
The plot shows am upward trend with winter peaks.
gas_decomp <- gas_recent %>%
model(classical = classical_decomposition(Gas, type = "multiplicative")) %>%
components()
gas_decomp %>% autoplot() + labs(title = "Gas Production Components")
This plot shows a strong trend with regular seasonal peaks.
gas_decomp %>% autoplot(season_adjust) + labs(title = "Gas Data - Seasonal Effects Removed")
# Middle outlier
gas_outlier1 <- gas_recent
gas_outlier1$Gas[10] <- gas_outlier1$Gas[10] + 300
outlier1_decomp <- gas_outlier1 %>%
model(classical_decomposition(Gas, type = "multiplicative")) %>%
components()
# End outlier
gas_outlier2 <- gas_recent
gas_outlier2$Gas[20] <- gas_outlier2$Gas[20] + 300
outlier2_decomp <- gas_outlier2 %>%
model(classical_decomposition(Gas, type = "multiplicative")) %>%
components()
# Compare seasonally adjusted
gas_decomp %>%
ggplot(aes(x = Quarter)) +
geom_line(aes(y = season_adjust), color = "black") +
geom_line(data = outlier1_decomp, aes(y = season_adjust), color = "red") +
geom_line(data = outlier2_decomp, aes(y = season_adjust), color = "blue") +
labs(title = "Outlier Effects: Original/Middle/End")
Middle outliers affect neighboring periods more due to moving average spillover. End outliers have localized impact.
retail_decomp <- retail_series %>%
model(stl = STL(Turnover)) %>%
components()
retail_decomp %>% autoplot() + labs(title = "Retail Decomposition Analysis")
retail_decomp %>% autoplot(remainder) + labs(title = "Irregular Component - Anomaly Detection")
STL decomposition shows clear trend and seasonal patterns with irregular spikes visible in the remainder component
Looking at the top panel of Figure 3.19, you can see the original data climbing steadily from about 6500 to around 9000 on the y-axis scale. The second panel shows the smooth trend line that captures this growth pattern. In the third panel, the seasonal component reveals a consistent yearly cycle - notice how it peaks around November-December and dips in January-February every year. The gray scale bars on the left show that the trend component (second panel) has the largest variation, while the seasonal component (third panel) is much smaller, and the remainder at the bottom is smallest of all.
You can spot the early 90s recession clearly in the bottom panel (remainder component) of Figure 3.19 - there’s a dramatic spike downward around 1991-1992 that goes way below the normal random fluctuations. This shows the recession was such an unusual event that it couldn’t be captured by the normal trend or seasonal patterns, so it shows up as a major disruption in the leftover component.