-1

Is it possible to calculate the effect size from the output of grangertest in package lmtest? I could calculate it by hand, but it only gives the F value, and not the sums of squares.

Granger causality test

Model 1: apwbc ~ Lags(apwbc, 1:1) + Lags(other, 1:1)
Model 2: apwbc ~ Lags(apwbc, 1:1)
  Res.Df Df      F  Pr(>F)  
1    163                    
2    164 -1 4.8495 0.02906 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Steve
  • 945
  • 3
  • 13
  • 22
  • The Granger causality test tells you whether predictions of a variable Y are significantly better when the predictions are based on the past values of Y only or on the past values of both Y and another variable X. What precisely do you mean by effect size for Granger causality? Are you perhaps looking for VAR coefficients or thinking of impulse response analysis? From your mention of sums of squares, you might also be after proportion of variance accounted for, but it's hard to be sure. To get a good answer, you probably need a more specific question. – duckmayr Jan 03 '18 at 15:50
  • The test statistic is F, so I assume it should be possible to calculate eta-squared, i.e. SSbetween/SStotal, to get an estimate of how much better the predictions are when lagged values of Y are included. But graingertest doesn't give the sums of squares. – Steve Jan 03 '18 at 18:08
  • OK, so it is a proportion of variance accounted for you're after. You might want to look into the [sjstats](https://cran.r-project.org/web/packages/sjstats/index.html) package. You should be able to use its `eta_sq()` function for what you want (e.g. `eta_sq(grangertest(x))`) – duckmayr Jan 03 '18 at 18:14
  • I tried it. Got "Error: `.data` must have two rows, not 0" BTW sjstats has some problems with installing dependencies. Had to spend about 15 min installing dependend packages that didn't get installed automatically :-( – Steve Jan 03 '18 at 21:53
  • Sorry to hear you had a hard time installing. Can't help with your error unless you edit your post to include your data, for example via `dput()` (see the [FAQ for asking R questions on Stack Overflow](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)). – duckmayr Jan 03 '18 at 22:05
  • I put the raw data at https://pastebin.com/XaMaVTaY I don't think the problem is with the data though; it runs fine on graingertest(apwbc ~ other, order=1). I only get the error when I embed that call in eta_sq(). Thanks for your help! – Steve Jan 03 '18 at 22:46
  • Sorry Steve, you were right; `eta_sq()` won't work out of the box because it assumes you're not dealing with nested models, but with one model. I've added a solution coded from scratch as an answer. – duckmayr Jan 04 '18 at 21:01

1 Answers1

4

We say a variable X Granger causes a variable Y if predictions of Y based on lagged values of both X and Y are significantly better than predictions of Y based on lagged values of Y alone. This means that a Granger causality test is a test of nested models; the model with lags of both variables is the full model, and the model with lags of Y alone is the nested or restricted model. We can calculate partial η2 from a test of nested models as (SSrestricted - SSfull) / SSrestricted (see for example Wright and London (2009), p. 21).

This is pretty easy to code up:

nested_model_partial_eta_sq <- function(full_mod, rest_mod) {
    # full_mod is the full model (an lm object)
    # rest_mod is the model that omits one or more explanatory variables
    SS_full <- sum(full_mod$residuals^2)
    SS_rest <- sum(rest_mod$residuals^2)
    return((SS_rest - SS_full) / SS_rest)
}

However, we might want a function that generates the regressions for us also, as well as runs the Granger causality test:

custom_granger <- function(x, y, p = 1) {
    # Does x Granger cause y? What is the effect size?
    # We want to test Granger causality,
    # but then also get partial eta squared to measure effect size
    # First it will be convenient to store the variable names
    varnames <- c(deparse(substitute(x)), deparse(substitute(y)))
    lagnames <- paste0(varnames, "_lag", rep(1:p, each = 2))
    # Then we created the lagged variables / data for models
    VAR_data <- embed(as.matrix(cbind(x, y)), p + 1)
    colnames(VAR_data) <- c(varnames, lagnames)
    VAR_data <- VAR_data[, -1]
    # Run the full model
    model_formula <- paste(colnames(VAR_data)[-1], collapse = " + ")
    model_formula <- formula(paste0(varnames[2], " ~ ", model_formula))
    full_mod <- lm(model_formula, data = as.data.frame(VAR_data))
    # Take out the lags of x and run the nested model
    VAR_data <- VAR_data[ , seq(from = 1, to = p * 2 + 1, by = 2)]
    model_formula <- paste(colnames(VAR_data)[-1], collapse = " + ")
    model_formula <- formula(paste0(varnames[2], " ~ ", model_formula))
    rest_mod <- lm(model_formula, data = as.data.frame(VAR_data))
    # Then we can do the Granger test
    granger_test <- anova(full_mod, rest_mod)
    # and get partial eta squared
    SS_full <- granger_test$RSS[1]
    SS_rest <- granger_test$RSS[2]
    partial_eta_squared <- (SS_rest - SS_full) / SS_rest
    # And return all of it
    return(list(VAR_result = full_mod,
                granger_test = granger_test,
                partial_eta_squared = partial_eta_squared))
}

With your data this results in

df <- read.csv('cormanaz-data.txt')
with(df, custom_granger(other, apwbc))

$VAR_result

Call:
lm(formula = model_formula, data = as.data.frame(VAR_data))

Coefficients:
(Intercept)   other_lag1   apwbc_lag1  
    1.97732     -0.01671      0.48997  


$granger_test
Analysis of Variance Table

Model 1: apwbc ~ other_lag1 + apwbc_lag1
Model 2: apwbc ~ apwbc_lag1
  Res.Df    RSS Df Sum of Sq      F  Pr(>F)  
1    163 6267.9                              
2    164 6454.4 -1   -186.48 4.8495 0.02906 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

$partial_eta_squared
[1] 0.02889191

You can see the F statistic for the Granger causality test is the same as from lmtest::grangertest(), but this will also give you the VAR coefficients and the partial η2, which for your particular case (I guess the number you've been after all along) is about 0.029.

duckmayr
  • 16,303
  • 3
  • 35
  • 53