Specifying plotting settings plot(ACF(data))

Your second question is a bit more involved (if we continue to use ACF to get the autocorrelation function values), because the plot.ACF function hard-codes the y-axis limits to be the range of the autocorrelations. More on that in a moment. First, an easy way around this: In my example above, m1 is the model. We can directly extract the residuals with resid(m1). Then we can use the base acf function to plot their autocorrelation function. The acf function allows us to explicitly set the y-axis range, rather than hard-coding it inside the function.

acf(resid(m1), lag.max=4, ylim=c(-1,1))

If you still want to use the ACF function, we need to modify the function, plot.ACF that plots ACF objects. To see the function that plots ACF objects, run getAnywhere(plot.ACF) and the code for this function will appear in the console (see the explanatory note at the bottom for some background on why we're looking for the plot.ACF function when we actually called the plot function in our code).

Note that the second line of the function body is ylim <- range(object$ACF). A way around this is to modify the function to accept a ylim argument. Note in the code below that I've created a new function called my_plot.ACF. I've commented out the ylim line in the original function and added a new function argument ylim=c(-1.0, 1.0), so it defaults to full range, but can be changed, if desired, when calling the function.

my_plot.ACF = function (x, alpha = 0, xlab = "Lag", ylab = "Autocorrelation", 
          grid = FALSE, ylim=c(-1.0,1.0), ...) {
  object <- x
  #ylim <- range(object$ACF)
  if (alpha) {
    assign("stdv", qnorm(1 - alpha/2)/sqrt(attr(object, "n.used")))
    stMax <- max(stdv)
    ylim <- c(min(c(-stMax, ylim[1])), max(c(ylim[2], stMax)))
  }
  assign("alpha", as.logical(alpha))
  assign("grid", grid)
  xyplot(ACF ~ lag, object, ylim = ylim, panel = function(x, 
                                                          y, ...) {
    x <- as.numeric(x)
    y <- as.numeric(y)
    if (grid) 
      panel.grid()
    panel.xyplot(x, y, type = "h")
    panel.abline(0, 0)
    if (alpha) {
      llines(x, stdv, lty = 2)
      llines(x, -stdv, lty = 2)
    }
  }, xlab = xlab, ylab = ylab, ...)
}

Now we run the function. We also need to load the lattice package, since plot.ACF (and therefore our new function) use the xyplot function from lattice.

library(lattice)
my_plot.ACF(ACF(m1, maxLag=4))

Explanatory note in case you're not already familiar with generic functions, methods, and method dispatch: plot is a "generic" function. When you run the plot function, what it does depends on the type of object you pass to it. If you type plot(mtcars) you'll get a scatterplot matrix. If you type plot(lm(mpg ~ hp, data=mtcars)) you'll get several diagnostic plots for a linear regression model. If you type plot(ACF(m1)) you'll get a plot of an autocorrelation function. And so on.

plot does different things with each of these objects because each of them has a different class, specifically, "data.frame", "lm", and "ACF", respectively (for example, run class(ACF(m1)). plot itself just "dispatches" the appropriate "plot method" (the actual function that does the plotting) for each of these objects. To see what these methods are, run methods(plot). They'll all be called plot.zzz where zzz is the class of the object.. For example, note that one of the functions is plot.ACF. You can see the code for this function by typing getAnywhere(plot.ACF).

1 Like