Author: Davor Cubranic and Mark Pickup
Date: 2022-06-08

# Introduction to ‘OrthoPanels’

#### Davor Cubranic and Mark Pickup

#### 2022-06-08

We demonstrate how to use the OrthoPanels package with an analysis of a subset of data from the 2010 British Election Study. The data consists of 3 waves of panel survey data with 1845 respondents. Our dependent variable is government approval (“Approve”), while independent variables in the model are evaluations of each party’s leader (“Brown”, “Cameron”, and “Clegg” for Labour, Conservative, and Liberal Party respectively) and government health and security policies (“NHS” and “Terror”); assesment of the economic situation (“Econ”); preference for taxing and spending policy (“Tax”); and personal identification with the governing Labour Party (“PID”).

This subset of BES 2010 data is included with the OrthoPanels package as dataset `BES_panel`. It is a data frame that includes all of the survey variables as described above, plus the variables for the case number (“n”) and the wave (“t”) of each observation:

    head(BES_panel)

    ##   n t Econ Clegg Brown Cameron Approve NHS Terror PID Tax
    ## 1 1 1    3     0     9       0       7   0      0   1   6
    ## 2 2 1    4     0    10       0       8   0      0   1   8
    ## 3 3 1    3     0     5       4       7   0      0   0   6
    ## 4 4 1    2     0     7       3       4   0      0   1   6
    ## 5 5 1    2     0     0       0       0   0      0   0   5
    ## 6 6 1    2     0     7       0       8   0      0   1   4

We begin by specifying our model using a formula, indicating the data to be used, and the case and time variables:

    BES.opm <- opm(Approve~Econ+Clegg+Brown+Cameron-NHS+Terror+PID-Tax,
    data=BES_panel, index = c('n', 't'), n.samp=1000, add.time.indicators=TRUE)

The first argument is a formula specifying the model symbolically: `response ~ term1 + term2`. This is consistent with the `lm()` function. It is not necessary to include the lagged dependent variable or the fixed effects in the model specification. This is done automatically.

The other arguments are: `data` which specifies the data frame, list or environment containing the variables in the model; `n.samp` which specifies the number of samples (MC iterations) to use to estimate the parameters; `index` which is a two-element vector containing the index or name of the case and time variables, respectively; and `add.time.indicators` which is a logical argument. If `add.time.indicators` is `TRUE`, the model includes dummy variables for each wave (time point). The default is `FALSE`. The `data` and `index` arguments are optional; if `data` is missing, variables are looked up in the environment, while the default value of `index` is the first two variables in the data frame. An additional optional argument is `subset`. This is a vector specifying a subset of observations to be used in the estimation.

The function `opm()` returns an object of class `opm` which includes a list,`samples`, with the following elements: `rho`, a vector of `n`.samp parameter samples of \(\rho\); `sig2`, a vector of n.samp parameter samples of \(\sigma^2\); and `beta`, an `n.samp x variable` matrix of parameters samples of \(\beta\). If included in the model, the parameters for the time dummies are included in this matrix:

    str(BES.opm)

    ## List of 11
    ##  $ samples        :List of 3
    ##   ..$ rho : num [1:1000] 0.255 0.175 0.178 0.15 0.189 0.222 0.221 0.242 0.215 0.251 ...
    ##   ..$ sig2: num [1:1000] 1.94 1.62 1.67 1.67 1.79 ...
    ##   ..$ beta: num [1:1000, 1:7] -0.04107 0.04543 0.01163 0.00432 0.0489 ...
    ##   .. ..- attr(*, "dimnames")=List of 2
    ##   .. .. ..$ : NULL
    ##   .. .. ..$ : chr [1:7] "Econ" "Clegg" "Brown" "Cameron" ...
    ##  $ fitted.values  : num [1:2, 1:1845] -0.572 0.572 -0.326 0.326 0.307 ...
    ##  $ residuals      : num [1:2, 1:1845] -0.428 0.428 0.826 -0.826 0.193 ...
    ##   ..- attr(*, "dimnames")=List of 2
    ##   .. ..$ t: chr [1:2] "2" "3"
    ##   .. ..$ i: chr [1:1845] "1" "2" "3" "4" ...
    ##  $ df.residual    : num 3682
    ##  $ logLik         : num -1809
    ##  $ design         : chr "balanced"
    ##  $ call           : language opm(x = Approve ~ Econ + Clegg + Brown + Cameron - NHS + Terror + PID -      Tax, data = BES_panel, index = c("n"| __truncated__
    ##  $ .Environment   :<environment: R_GlobalEnv>
    ##  $ time.indicators: logi TRUE
    ##  $ index          : chr [1:2] "n" "t"
    ##  $ terms          :Classes 'terms', 'formula'  language Approve ~ Econ + Clegg + Brown + Cameron - NHS + Terror + PID - Tax
    ##   .. ..- attr(*, "variables")= language list(Approve, Econ, Clegg, Brown, Cameron, NHS, Terror, PID, Tax)
    ##   .. ..- attr(*, "factors")= int [1:9, 1:6] 0 1 0 0 0 0 0 0 0 0 ...
    ##   .. .. ..- attr(*, "dimnames")=List of 2
    ##   .. .. .. ..$ : chr [1:9] "Approve" "Econ" "Clegg" "Brown" ...
    ##   .. .. .. ..$ : chr [1:6] "Econ" "Clegg" "Brown" "Cameron" ...
    ##   .. ..- attr(*, "term.labels")= chr [1:6] "Econ" "Clegg" "Brown" "Cameron" ...
    ##   .. ..- attr(*, "order")= int [1:6] 1 1 1 1 1 1
    ##   .. ..- attr(*, "intercept")= int 0
    ##   .. ..- attr(*, "response")= int 1
    ##   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv>
    ##   .. ..- attr(*, "predvars")= language list(Approve, Econ, Clegg, Brown, Cameron, NHS, Terror, PID, Tax)
    ##   .. ..- attr(*, "dataClasses")= Named chr [1:9] "numeric" "numeric" "numeric" "numeric" ...
    ##   .. .. ..- attr(*, "names")= chr [1:9] "Approve" "Econ" "Clegg" "Brown" ...
    ##  - attr(*, "class")= chr "opm"

The summary of the object provides us with the median, 68% equal tailed credible intervals and 95% equal tailed credible intervals for each parameter:

    summary(BES.opm)

    ## Call:
    ## opm(x = Approve ~ Econ + Clegg + Brown + Cameron - NHS + Terror +
    ##     PID - Tax, data = BES_panel, index = c("n", "t"), n.samp = 1000,
    ##     add.time.indicators = TRUE)
    ##
    ## Parameter estimates:
    ##                  <--95CI      <--68CI         med     68CI-->     95CI-->
    ## rho             0.135975    0.1700000    0.202000    0.234000    0.270050
    ## sig2            1.632579    1.7118831    1.789958    1.883582    1.966033
    ## beta.Econ      -0.038460    0.0034027    0.044043    0.084722    0.125141
    ## beta.Clegg     -0.018057    0.0037315    0.024038    0.047105    0.072435
    ## beta.Brown      0.313800    0.3350275    0.359479    0.384245    0.404603
    ## beta.Cameron   -0.134145   -0.1084041   -0.086719   -0.061846   -0.038346
    ## beta.Terror    -0.163748   -0.1267264   -0.090208   -0.048586   -0.014698
    ## beta.PID        0.500555    0.6493085    0.815215    0.975794    1.112262
    ## beta.tind.2     0.294678    0.3435501    0.403777    0.459513    0.531986

The package includes functions that may be of use in exploring the results. Method `confint` for objects of `opm` class computes equal-tailed credible intervals for one or more parameters in the fitted opm model. We can calculate 90% equal-tailed credible intervals as follows:

    confint(BES.opm, level=0.9)

    ##                       5%         95%
    ## rho           0.15000000  0.25900000
    ## sig2          1.65941383  1.93889163
    ## beta.Econ    -0.02529902  0.11143611
    ## beta.Clegg   -0.01008631  0.06241999
    ## beta.Brown    0.31987212  0.39924565
    ## beta.Cameron -0.12317409 -0.04604077
    ## beta.Terror  -0.15131367 -0.02500343
    ## beta.PID      0.54094938  1.07417054
    ## beta.tind.2   0.31075261  0.50583644

The function `caterplot` creates side-by-side plots of credible intervals of the opm model parameters. The intervals are displayed as horizontal lines, with the 90% interval using a thicker line width and the 95% interval a thinner one. The posterior median is indicated with a dot.

    caterplot(BES.opm, main = "BES 2010 opm parameter estimates")
    abline(v=0)

We can use the function `plot()` to obtain the posterior density of each parameter:

    plot(BES.opm, 'rho')

In a dynamic model, the \(\beta\) coefficients are the immediate effects of a change in each of the covariates. This is known as the short run effect. However, in a dynamic model, the short run effect is not the full effect of a change in a covariate. As the future value of the dependent variable depends on the current value, the effect of a change in a covariate has a knock on effect into the future. The effect builds at a declining rate until it asymptotically reaches its full effect. This is known as the long-run effect and is estimated as \(\frac{\beta}{1-\rho}\), where \(\rho\) is the autoregressive parameter (Wooldridge, 2013; Pickup, 2014). We can calculate the median and 95% equal tailed credible intervals for the long-run effects from the parameter samples. For example, for the first independent variable (the economy):

    quantile(BES.opm$samples$beta[,1]/(1-BES.opm$samples$rho), probs=c(0.025, 0.5, 0.975))

    ##        2.5%         50%       97.5%
    ## -0.04930539  0.05493104  0.15581732

The function `longRunEffects` Computes long term effects and confidence intervals of Model Parameters, using the formula as per explanation above. By default, it computes the median and 95% equal tailed credible intervals for the long-run effects from the parameter samples.

    longRunEffects(BES.opm,prob=c(0.025,0.5,0.975))

    ##              Econ       Clegg     Brown     Cameron      Terror       PID
    ## 2.5%  -0.04930539 -0.02213175 0.3829210 -0.16891226 -0.20939605 0.6289061
    ## 50%    0.05493104  0.03055054 0.4508522 -0.10819835 -0.11241031 1.0256048
    ## 97.5%  0.15581732  0.09152870 0.5266484 -0.04892669 -0.01834949 1.4335055
    ##          tind.2
    ## 2.5%  0.3560684
    ## 50%   0.5038267
    ## 97.5% 0.6858649

The function `caterplot_longRun` creates side-by-side plots of credible intervals of the opm model long-run effects, which are computed using the function The function `longRunEffects`. The intervals are displayed as horizontal lines, with the 90% interval using a thicker line width and the 95% interval a thinner one. The posterior median is indicated with a dot.

    caterplot_longRun(BES.opm)