library(fpp3)
## ── Attaching packages ──────────────────────────────────────────── fpp3 1.0.3 ──
## ✔ tibble      3.3.1     ✔ tsibble     1.2.0
## ✔ dplyr       1.2.1     ✔ tsibbledata 0.4.1
## ✔ tidyr       1.3.2     ✔ ggtime      1.0.0
## ✔ lubridate   1.9.5     ✔ feasts      0.5.0
## ✔ ggplot2     4.0.3     ✔ fable       0.5.0
## ── Conflicts ───────────────────────────────────────────────── fpp3_conflicts ──
## ✖ lubridate::date()    masks base::date()
## ✖ dplyr::filter()      masks stats::filter()
## ✖ tsibble::intersect() masks base::intersect()
## ✖ tsibble::interval()  masks lubridate::interval()
## ✖ dplyr::lag()         masks stats::lag()
## ✖ tsibble::setdiff()   masks base::setdiff()
## ✖ tsibble::union()     masks base::union()

Exercise 2.1

This exercise explores four time series by identifying their time intervals and creating time plots.

1. Bricks from aus_production

The Bricks series contains quarterly clay-brick production in Australia, measured in millions of bricks.

?aus_production
aus_production
## # A tsibble: 218 x 7 [1Q]
##    Quarter  Beer Tobacco Bricks Cement Electricity   Gas
##      <qtr> <dbl>   <dbl>  <dbl>  <dbl>       <dbl> <dbl>
##  1 1956 Q1   284    5225    189    465        3923     5
##  2 1956 Q2   213    5178    204    532        4436     6
##  3 1956 Q3   227    5297    208    561        4806     7
##  4 1956 Q4   308    5681    197    570        4418     6
##  5 1957 Q1   262    5577    187    529        4339     5
##  6 1957 Q2   228    5651    214    604        4811     7
##  7 1957 Q3   236    5317    227    603        5259     7
##  8 1957 Q4   320    6152    222    582        4735     6
##  9 1958 Q1   272    5758    199    554        4608     5
## 10 1958 Q2   233    5641    229    620        5196     7
## # ℹ 208 more rows

The [1Q] in the output shows that the data are recorded once every quarter.

autoplot(aus_production, Bricks)
## Warning: Removed 20 rows containing missing values or values outside the scale range
## (`geom_line()`).

### 2. Lynx from pelt

The Lynx series contains the number of Canadian lynx pelts traded by the Hudson Bay Company.

?pelt
pelt
## # A tsibble: 91 x 3 [1Y]
##     Year  Hare  Lynx
##    <dbl> <dbl> <dbl>
##  1  1845 19580 30090
##  2  1846 19600 45150
##  3  1847 19610 49150
##  4  1848 11990 39520
##  5  1849 28040 21230
##  6  1850 58000  8420
##  7  1851 74600  5560
##  8  1852 75090  5080
##  9  1853 88480 10170
## 10  1854 61280 19600
## # ℹ 81 more rows

The [1Y] in the output shows that the data are recorded once every year.

autoplot(pelt, Lynx)

### 3. Closing Stock Prices from gafa_stock

The Close series contains the daily closing prices of Google, Amazon, Facebook, and Apple stocks.

?gafa_stock
gafa_stock
## # A tsibble: 5,032 x 8 [!]
## # Key:       Symbol [4]
##    Symbol Date        Open  High   Low Close Adj_Close    Volume
##    <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>     <dbl>
##  1 AAPL   2014-01-02  79.4  79.6  78.9  79.0      67.0  58671200
##  2 AAPL   2014-01-03  79.0  79.1  77.2  77.3      65.5  98116900
##  3 AAPL   2014-01-06  76.8  78.1  76.2  77.7      65.9 103152700
##  4 AAPL   2014-01-07  77.8  78.0  76.8  77.1      65.4  79302300
##  5 AAPL   2014-01-08  77.0  77.9  77.0  77.6      65.8  64632400
##  6 AAPL   2014-01-09  78.1  78.1  76.5  76.6      65.0  69787200
##  7 AAPL   2014-01-10  77.1  77.3  75.9  76.1      64.5  76244000
##  8 AAPL   2014-01-13  75.7  77.5  75.7  76.5      64.9  94623200
##  9 AAPL   2014-01-14  76.9  78.1  76.8  78.1      66.1  83140400
## 10 AAPL   2014-01-15  79.1  80.0  78.8  79.6      67.5  97909700
## # ℹ 5,022 more rows

This is an irregular daily time series because stock prices are recorded only on trading days, excluding weekends and market holidays.

autoplot(gafa_stock, Close)

### 4. Electricity Demand from vic_elec

The Demand series contains electricity demand in Victoria, Australia, measured in megawatt-hours.

?vic_elec
vic_elec
## # A tsibble: 52,608 x 5 [30m] <Australia/Melbourne>
##    Time                Demand Temperature Date       Holiday
##    <dttm>               <dbl>       <dbl> <date>     <lgl>  
##  1 2012-01-01 00:00:00  4383.        21.4 2012-01-01 TRUE   
##  2 2012-01-01 00:30:00  4263.        21.0 2012-01-01 TRUE   
##  3 2012-01-01 01:00:00  4049.        20.7 2012-01-01 TRUE   
##  4 2012-01-01 01:30:00  3878.        20.6 2012-01-01 TRUE   
##  5 2012-01-01 02:00:00  4036.        20.4 2012-01-01 TRUE   
##  6 2012-01-01 02:30:00  3866.        20.2 2012-01-01 TRUE   
##  7 2012-01-01 03:00:00  3694.        20.1 2012-01-01 TRUE   
##  8 2012-01-01 03:30:00  3562.        19.6 2012-01-01 TRUE   
##  9 2012-01-01 04:00:00  3433.        19.1 2012-01-01 TRUE   
## 10 2012-01-01 04:30:00  3359.        19.0 2012-01-01 TRUE   
## # ℹ 52,598 more rows

The [30m] in the output shows that electricity demand is recorded every 30 minutes.

autoplot(vic_elec, Demand) +
  labs(
    title = "Half-Hourly Electricity Demand in Victoria",
    x = "Date and Time",
    y = "Electricity Demand (MWh)"
  )

Exercise 2.2

This exercise uses filter() to identify the date of the highest closing price for each stock in the gafa_stock dataset.

gafa_stock |>
  group_by(Symbol) |>
  filter(Close == max(Close))
## # A tsibble: 4 x 8 [!]
## # Key:       Symbol [4]
## # Groups:    Symbol [4]
##   Symbol Date        Open  High   Low Close Adj_Close   Volume
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
## 1 AAPL   2018-10-03  230.  233.  230.  232.      230. 28654800
## 2 AMZN   2018-09-04 2026. 2050. 2013  2040.     2040.  5721100
## 3 FB     2018-07-25  216.  219.  214.  218.      218. 58954200
## 4 GOOG   2018-07-26 1251  1270. 1249. 1268.     1268.  2405600

The peak closing prices occurred on the following dates:

Exercise 2.3

The tute1.csv dataset contains quarterly observations for Sales, Advertising Budget, and Gross Domestic Product from 1981 through 2005. All three series have been adjusted for inflation.

tute1 <- readr::read_csv("tute1.csv")
## Rows: 100 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl  (3): Sales, AdBudget, GDP
## date (1): Quarter
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# View(tute1)
tute1
## # A tibble: 100 × 4
##    Quarter    Sales AdBudget   GDP
##    <date>     <dbl>    <dbl> <dbl>
##  1 1981-03-01 1020.     659.  252.
##  2 1981-06-01  889.     589   291.
##  3 1981-09-01  795      512.  291.
##  4 1981-12-01 1004.     614.  292.
##  5 1982-03-01 1058.     647.  279.
##  6 1982-06-01  944.     602   254 
##  7 1982-09-01  778.     531.  296.
##  8 1982-12-01  932.     608.  272.
##  9 1983-03-01  996.     638.  260.
## 10 1983-06-01  908.     582.  280.
## # ℹ 90 more rows

Convert the Data to Time Series

mytimeseries <- tute1 |>
  mutate(Quarter = yearquarter(Quarter)) |>
  as_tsibble(index = Quarter)

mytimeseries
## # A tsibble: 100 x 4 [1Q]
##    Quarter Sales AdBudget   GDP
##      <qtr> <dbl>    <dbl> <dbl>
##  1 1981 Q1 1020.     659.  252.
##  2 1981 Q2  889.     589   291.
##  3 1981 Q3  795      512.  291.
##  4 1981 Q4 1004.     614.  292.
##  5 1982 Q1 1058.     647.  279.
##  6 1982 Q2  944.     602   254 
##  7 1982 Q3  778.     531.  296.
##  8 1982 Q4  932.     608.  272.
##  9 1983 Q1  996.     638.  260.
## 10 1983 Q2  908.     582.  280.
## # ℹ 90 more rows

The [1Q] confirms that the three series contain quarterly observations.

Time-Series Plots with Separate Scales

mytimeseries |>
  pivot_longer(-Quarter) |>
  ggplot(aes(x = Quarter, y = value, colour = name)) +
  geom_line() +
  facet_grid(name ~ ., scales = "free_y")

### Time-Series Plot Without facet_grid()

mytimeseries |>
  pivot_longer(-Quarter) |>
  ggplot(aes(x = Quarter, y = value, colour = name)) +
  geom_line()

With facet_grid(), the three series appear in separate panels with their own y-axis scales, making the patterns easier to examine. Without facet_grid(), Sales, AdBudget, and GDP appear together on one graph using the same scale. This makes the individual patterns more difficult to see clearly.

Exercise 2.4

The USgas package contains annual natural-gas consumption data for the United States.

Load and Examine the Data

library(USgas)
head(us_total)
##   year   state      y
## 1 1997 Alabama 324158
## 2 1998 Alabama 329134
## 3 1999 Alabama 337270
## 4 2000 Alabama 353614
## 5 2001 Alabama 332693
## 6 2002 Alabama 379343

Convert us_total to a Tsibble

us_gas <- us_total |>
  as_tsibble(index = year, key = state)

us_gas
## # A tsibble: 1,266 x 3 [1Y]
## # Key:       state [53]
##     year state        y
##    <int> <chr>    <int>
##  1  1997 Alabama 324158
##  2  1998 Alabama 329134
##  3  1999 Alabama 337270
##  4  2000 Alabama 353614
##  5  2001 Alabama 332693
##  6  2002 Alabama 379343
##  7  2003 Alabama 350345
##  8  2004 Alabama 382367
##  9  2005 Alabama 353156
## 10  2006 Alabama 391093
## # ℹ 1,256 more rows

The [1Y] output shows that the natural-gas data are recorded annually, and state identifies each separate time series.

New England Natural-Gas Consumption

new_england <- c(
  "Maine",
  "Vermont",
  "New Hampshire",
  "Massachusetts",
  "Connecticut",
  "Rhode Island"
)

us_gas |>
  filter(state %in% new_england) |>
  autoplot(y) +
  labs(
    title = "Annual Natural Gas Consumption in New England",
    x = "Year",
    y = "Natural Gas Consumption (Million Cubic Feet)",
    colour = "State"
  )

The plot compares annual natural-gas consumption across the six New England states. Consumption differs by state and changes from year to year. Using a separate colored line for each state makes these differences easier to compare.

Exercise 2.5

Import the Excel Data

tourism_excel <- readxl::read_excel("tourism.xlsx")
tourism_excel
## # A tibble: 24,320 × 5
##    Quarter    Region   State           Purpose  Trips
##    <chr>      <chr>    <chr>           <chr>    <dbl>
##  1 1998-01-01 Adelaide South Australia Business  135.
##  2 1998-04-01 Adelaide South Australia Business  110.
##  3 1998-07-01 Adelaide South Australia Business  166.
##  4 1998-10-01 Adelaide South Australia Business  127.
##  5 1999-01-01 Adelaide South Australia Business  137.
##  6 1999-04-01 Adelaide South Australia Business  200.
##  7 1999-07-01 Adelaide South Australia Business  169.
##  8 1999-10-01 Adelaide South Australia Business  134.
##  9 2000-01-01 Adelaide South Australia Business  154.
## 10 2000-04-01 Adelaide South Australia Business  169.
## # ℹ 24,310 more rows

Convert the Data to a Tsibble

tourism_tsibble <- tourism_excel |>
  mutate(Quarter = yearquarter(Quarter)) |>
  as_tsibble(
    index = Quarter,
    key = c(Region, State, Purpose)
  )

tourism_tsibble
## # A tsibble: 24,320 x 5 [1Q]
## # Key:       Region, State, Purpose [304]
##    Quarter Region   State           Purpose  Trips
##      <qtr> <chr>    <chr>           <chr>    <dbl>
##  1 1998 Q1 Adelaide South Australia Business  135.
##  2 1998 Q2 Adelaide South Australia Business  110.
##  3 1998 Q3 Adelaide South Australia Business  166.
##  4 1998 Q4 Adelaide South Australia Business  127.
##  5 1999 Q1 Adelaide South Australia Business  137.
##  6 1999 Q2 Adelaide South Australia Business  200.
##  7 1999 Q3 Adelaide South Australia Business  169.
##  8 1999 Q4 Adelaide South Australia Business  134.
##  9 2000 Q1 Adelaide South Australia Business  154.
## 10 2000 Q2 Adelaide South Australia Business  169.
## # ℹ 24,310 more rows

Region and Purpose with the Highest Average Trips

average_trips <- tourism_tsibble |>
  as_tibble() |>
  group_by(Region, Purpose) |>
  summarise(
    AverageTrips = mean(Trips),
    .groups = "drop"
  )

average_trips |>
  filter(AverageTrips == max(AverageTrips))
## # A tibble: 1 × 3
##   Region Purpose  AverageTrips
##   <chr>  <chr>           <dbl>
## 1 Sydney Visiting         747.

Sydney for the purpose of Visiting had the maximum average number of overnight trips, with an average of 747.27 thousand trips per quarter.

Total Trips by State

tourism_by_state <- tourism_tsibble |>
  group_by(State) |>
  summarise(Trips = sum(Trips))

tourism_by_state
## # A tsibble: 640 x 3 [1Q]
## # Key:       State [8]
##    State Quarter Trips
##    <chr>   <qtr> <dbl>
##  1 ACT   1998 Q1  551.
##  2 ACT   1998 Q2  416.
##  3 ACT   1998 Q3  436.
##  4 ACT   1998 Q4  450.
##  5 ACT   1999 Q1  379.
##  6 ACT   1999 Q2  558.
##  7 ACT   1999 Q3  449.
##  8 ACT   1999 Q4  595.
##  9 ACT   2000 Q1  600.
## 10 ACT   2000 Q2  557.
## # ℹ 630 more rows

This new tsibble combines all Regions and Purposes and shows the total number of trips for each State in every quarter.

Exercise 2.8

This exercise explores five time series using time plots, seasonal plots, seasonal-subseries plots, lag plots, and autocorrelation plots.

Total Private Employment

total_private <- us_employment |>
  filter(Title == "Total Private")

autoplot(total_private, Employed)

gg_season(total_private, Employed)

gg_subseries(total_private, Employed)

gg_lag(total_private, Employed)

total_private |>
  ACF(Employed) |>
  autoplot()

Total private employment has a strong long-term upward trend. There are some periods of decline, especially around economic recessions, including 2008–2009. The seasonal plots show a repeating monthly pattern, although the upward trend is more noticeable. The lag plots and ACF show strong positive relationships between nearby months, meaning employment changes gradually over time rather than randomly.

Australian Brick Production

bricks <- aus_production |>
  select(Quarter, Bricks)

autoplot(bricks, Bricks)
## Warning: Removed 20 rows containing missing values or values outside the scale range
## (`geom_line()`).

gg_season(bricks, Bricks)
## Warning: Removed 20 rows containing missing values or values outside the scale range
## (`geom_line()`).

gg_subseries(bricks, Bricks)
## Warning: Removed 20 rows containing missing values or values outside the scale range
## (`geom_line()`).

gg_lag(bricks, Bricks)
## Warning: Removed 20 rows containing missing values (gg_lag).

bricks |>
  ACF(Bricks) |>
  autoplot()

Australian brick production shows clear quarterly seasonality, with production generally lower in the first quarter than in the later quarters. Production increased during the earlier years, reached higher levels around the 1970s and 1980s, and then generally declined. The series also contains cyclical rises and falls. The strong correlations at seasonal lags, especially lag 4, confirm the repeating yearly pattern. Some unusually sharp decreases are visible during economic downturns.

Canadian Hare Pelts

hare <- pelt |>
  select(Year, Hare)

autoplot(hare, Hare)

gg_lag(hare, Hare)

hare |>
  ACF(Hare) |>
  autoplot()

The hare series has no seasonal pattern because the observations are annual. It has a strong cycle lasting approximately 10 years, with repeated increases and decreases in the number of hare pelts. There is no clear long-term upward or downward trend. The ACF also supports this cyclical pattern, with correlations changing from positive to negative and then becoming positive again. Some unusually high peaks appear around the 1860s and 1880s.

H02 Pharmaceutical Costs

h02 <- PBS |>
  filter(ATC2 == "H02") |>
  select(Month, Concession, Type, Cost) |>
  summarise(TotalC = sum(Cost)) |>
  mutate(Cost = TotalC / 1e6)

autoplot(h02, Cost)

gg_season(h02, Cost)

gg_subseries(h02, Cost)

gg_lag(h02, Cost)

h02 |>
  ACF(Cost) |>
  autoplot()

Monthly H02 pharmaceutical costs show a nonlinear upward trend and strong yearly seasonality. Costs generally increase toward the end of the year and then decrease sharply near the beginning of the next year. The ACF shows strong correlations at nearby lags and at lag 12, confirming the annual seasonal pattern. Some individual months contain unusually large changes, and 2008 is incomplete because the data end in June.

United States Gasoline Supply

autoplot(us_gasoline, Barrels)

gg_season(us_gasoline, Barrels)

gg_subseries(us_gasoline, Barrels)

gg_lag(us_gasoline, Barrels)

us_gasoline |>
  ACF(Barrels) |>
  autoplot()

United States gasoline supply shows an upward trend from the early 1990s through the mid-2000s, followed by periods of decline and recovery. The seasonal plot shows that gasoline supply is generally higher during the summer and lower during the winter. The ACF remains strongly positive across many weekly lags, showing that nearby weeks are closely related. Unusually sharp decreases are visible around 2005 and near the end of the series in 2017.

Overall Findings

The five series contain different time-series patterns. Total private employment, H02 pharmaceutical costs, and gasoline production show trends and seasonality. Brick production shows quarterly seasonality and cyclical changes, while the annual hare series shows a strong cycle but no seasonality. The plots and ACFs also help identify unusual decreases, peaks, and years in each series.