Search code examples
rtime-seriesforecastingautocorrelation

How to do the Ljung-Box test in R?


I'm trying to do a Ljung-Box test in R, but I'm getting an error and I don't understand where is the problem.

Let's use the code from example in "Forecasting: Principles and Practice" to get Google’s daily closing stock price

library(fpp3)
google_stock <- gafa_stock  %>%
  filter(Symbol == "GOOG")  %>%
  mutate(day = row_number()) %>%
  update_tsibble(index = day, regular = TRUE)

google_2015 <- google_stock %>% filter(year(Date) == 2015)

I obtain the residuals from forecasting the series using the naïve method

aug <- google_2015 %>% model(NAIVE(Close)) %>% augment()

Now I want to do a formal test for autocorrelation in the residuals using the Ljung-Box test

aug %>% features(.resid, ljung_box, lag=10, dof=0)

But I get this error in the output:

# A tibble: 1 x 2
  Symbol .model      
  <chr>  <chr>       
1 GOOG   NAIVE(Close)
Warning message:
1 error encountered for feature 1
[1] 'ts' object must have one or more observations

What am I doing wrong?

This is a sample of the dataset (with dput() ):

    > dput(head(google_stock, 10))
structure(list(Symbol = c("GOOG", "GOOG", "GOOG", "GOOG", "GOOG", 
"GOOG", "GOOG", "GOOG", "GOOG", "GOOG"), Date = structure(c(16072, 
16073, 16076, 16077, 16078, 16079, 16080, 16083, 16084, 16085
), class = "Date"), Open = c(554.125916, 553.897461, 552.908875, 
558.865112, 569.297241, 568.025513, 565.859619, 559.595398, 565.298279, 
572.769714), High = c(555.26355, 554.856201, 555.814941, 566.162659, 
569.953003, 568.413025, 565.859619, 569.749329, 571.781128, 573.768188
), Low = c(550.549194, 548.894958, 549.645081, 556.95752, 562.983337, 
559.143311, 557.499023, 554.975403, 560.400146, 568.199402), 
    Close = c(552.963501, 548.929749, 555.049927, 565.750366, 
    566.927673, 561.468201, 561.438354, 557.861633, 570.986267, 
    570.598816), Adj_Close = c(552.963501, 548.929749, 555.049927, 
    565.750366, 566.927673, 561.468201, 561.438354, 557.861633, 
    570.986267, 570.598816), Volume = c(3666400, 3355000, 3561600, 
    5138400, 4514100, 4196000, 4314700, 4869100, 4997400, 3925700
    ), day = 1:10), row.names = c(NA, -10L), key = structure(list(
    Symbol = "GOOG", .rows = list(1:10)), row.names = c(NA, -1L
), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE), index = structure("day", ordered = TRUE), index2 = "day", interval = structure(list(
    year = 0, quarter = 0, month = 0, week = 0, day = 0, hour = 0, 
    minute = 0, second = 0, millisecond = 0, microsecond = 0, 
    nanosecond = 0, unit = 1), class = "interval"), class = c("tbl_ts", 
"tbl_df", "tbl", "data.frame"))

Solution

  • It looks like you need to select the column of interest (.resid) first, before passing onto the features() function:

    aug %>% 
    select(.resid) %>% 
    features(.resid, ljung_box, lag = 10, dof = 0)
    # Output
    # Selecting index: "day"
    # A tibble: 1 x 2
      lb_stat lb_pvalue
        <dbl>     <dbl>
    1    7.91     0.637
    

    If you don't specify .resid in the features() function, it will still work, by automatically selecting that column (as it's the only one other than the index column):

    aug %>% 
    select(.resid) %>% 
    features(features = ljung_box, lag = 10, dof = 0)
    # Selecting index: "day"
    # Feature variable not specified, automatically selected `.var = .resid`
    # A tibble: 1 x 2
      lb_stat lb_pvalue
        <dbl>     <dbl>
    1    7.91     0.637