Today we are learning how to use panel data to assess reverse causality, temporal ordering, and reciprocal relationships, implementing some cross-lagged panel models. We will again reshape data between wide and long formats, fit the traditional cross-lagged panel model, and try different model specifications.

Police misconduct and violent crime in Chicago

The relationship between policing and crime is a tricky one. Some researchers argue that heavy-handed policing can contribute to increase crime via legal cynicism and strain. However, more police resources—including use of force—are often deployed in high-crime areas. Here, we examine evidence from Chicago. We use publicly available data on violent crimes (i.e., homicides and robberies) and complaints about police misuse of force across all 343 Chicago neighbourhoods between 1991 and 2016. We will use cross-lagged panel models to examine this relationship.

The chicago.Rdata file contains data on 343 Chicago neighbourhood clusters, and 25 years (1991 through 2016). The data.frame includes the following variables:

Name Description
NC_NUM an ID variable indicating Chicago neighbourhood clusters
year the year, ranging from 1991 to 2016
complaints (logged) number of complaints about police misuse of force in Chicago
violent (logged) number of violent crimes reported
population_density (logged) population density (measured in 1990)
FAC_disadv factor scores indicating concentrated disadvantage (measured in 1990)

Please download the chicago.RData data file from the website. Download the file and store it in a sensible folder in your computer (preferably the folder of your R Project). Then, we can use the load() function to import the dataset into R.

load("data/chicago.RData") # adjust accordingly

Question 1

Is the dataset set up in a wide format or in a long format?

Show me how
# check the first rows of the dataset
head(chicago)
##   NC_NUM year complaints  violent population_density FAC_disadv
## 1      1 1991   2.197225 4.356709           9.708923  0.7612026
## 2      2 1991   1.386294 4.553877           9.280131 -0.6690897
## 3      3 1991   2.564949 4.189655           9.413296 -1.4276494
## 4      4 1991   1.098612 4.521789           9.763880 -1.0023245
## 5      5 1991   1.791759 4.406719           9.582598 -0.5795160
## 6      6 1991   0.000000 4.477337           9.392984 -0.3819274


Question 2

To fit a cross-lagged panel model, we need to have a wide dataset. Let’s use the pivot_wider() function again to reshape it wide. To avoid tedious coding in the next question, let’s filter the dataset so that it includes data from 2011 to 2014 only.

Show me how
# load tidyverse
library(tidyverse)

# filter and reshape the dataset
chicago_wide <- chicago %>%
  filter(year > 2010 & year < 2015) %>%
  pivot_wider(names_from = year,
              values_from = -c(NC_NUM, year, FAC_disadv, population_density))

# check columns of the wide dataset
names(chicago_wide)
##  [1] "NC_NUM"             "population_density" "FAC_disadv"        
##  [4] "complaints_2011"    "complaints_2012"    "complaints_2013"   
##  [7] "complaints_2014"    "violent_2011"       "violent_2012"      
## [10] "violent_2013"       "violent_2014"


Question 3 Using the sem() function from the lavaan() package, let’s fit our first cross-lagged panel model assessing the reciprocal relationship between complaints and violent crime. Let’s start with autoregressive and cross-lagged parameters constrained to equality. What is the average cross-lagged effect of crime on police use-of-force? And what is the average cross-lagged effect of police use-of-force on crime?

Show me how
# load the lavaan package
library(lavaan)

# specify the model
clpm_model <- '
  violent_2014 ~ a * violent_2013 + b * complaints_2013
  violent_2013 ~ a * violent_2012 + b * complaints_2012
  violent_2012 ~ a * violent_2011 + b * complaints_2011
  
  complaints_2014 ~ c * complaints_2013 + d * violent_2013
  complaints_2013 ~ c * complaints_2012 + d * violent_2012
  complaints_2012 ~ c * complaints_2011 + d * violent_2011
  
  violent_2011 ~~ complaints_2011
  violent_2012 ~~ complaints_2012
  violent_2013 ~~ complaints_2013
  violent_2014 ~~ complaints_2014
'

# fit the CLPM
clpm_fit <- sem(clpm_model, estimator = "ML", data = chicago_wide)

# summary results
summary(clpm_fit, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-19 ended normally after 30 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        24
##   Number of equality constraints                     8
## 
##   Number of observations                           342
## 
## Model Test User Model:
##                                                       
##   Test statistic                               244.647
##   Degrees of freedom                                20
##   P-value (Chi-square)                           0.000
## 
## Model Test Baseline Model:
## 
##   Test statistic                              2544.730
##   Degrees of freedom                                28
##   P-value                                        0.000
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.911
##   Tucker-Lewis Index (TLI)                       0.875
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)              -2368.411
##   Loglikelihood unrestricted model (H1)      -2246.088
##                                                       
##   Akaike (AIC)                                4768.822
##   Bayesian (BIC)                              4830.179
##   Sample-size adjusted Bayesian (SABIC)       4779.424
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.181
##   90 Percent confidence interval - lower         0.161
##   90 Percent confidence interval - upper         0.202
##   P-value H_0: RMSEA <= 0.050                    0.000
##   P-value H_0: RMSEA >= 0.080                    1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.060
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## Regressions:
##                     Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   violent_2014 ~                                                         
##     vilnt_2013 (a)     0.887    0.014   64.357    0.000    0.887    0.889
##     cmpln_2013 (b)     0.054    0.015    3.719    0.000    0.054    0.049
##   violent_2013 ~                                                         
##     vilnt_2012 (a)     0.887    0.014   64.357    0.000    0.887    0.882
##     cmpln_2012 (b)     0.054    0.015    3.719    0.000    0.054    0.052
##   violent_2012 ~                                                         
##     vilnt_2011 (a)     0.887    0.014   64.357    0.000    0.887    0.905
##     cmpln_2011 (b)     0.054    0.015    3.719    0.000    0.054    0.054
##   complaints_2014 ~                                                      
##     cmpln_2013 (c)     0.260    0.030    8.637    0.000    0.260    0.248
##     vilnt_2013 (d)     0.286    0.028   10.036    0.000    0.286    0.304
##   complaints_2013 ~                                                      
##     cmpln_2012 (c)     0.260    0.030    8.637    0.000    0.260    0.277
##     vilnt_2012 (d)     0.286    0.028   10.036    0.000    0.286    0.317
##   complaints_2012 ~                                                      
##     cmpln_2011 (c)     0.260    0.030    8.637    0.000    0.260    0.268
##     vilnt_2011 (d)     0.286    0.028   10.036    0.000    0.286    0.303
## 
## Covariances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   violent_2011 ~~                                                       
##     complants_2011    0.392    0.049    8.043    0.000    0.392    0.483
##  .violent_2012 ~~                                                       
##    .complants_2012    0.051    0.013    3.835    0.000    0.051    0.212
##  .violent_2013 ~~                                                       
##    .complants_2013    0.008    0.014    0.576    0.565    0.008    0.031
##  .violent_2014 ~~                                                       
##    .complants_2014    0.041    0.015    2.719    0.007    0.041    0.149
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .violent_2014      0.137    0.010   13.077    0.000    0.137    0.171
##    .violent_2013      0.141    0.011   13.077    0.000    0.141    0.175
##    .violent_2012      0.104    0.008   13.077    0.000    0.104    0.130
##    .complants_2014    0.557    0.043   13.077    0.000    0.557    0.782
##    .complants_2013    0.480    0.037   13.077    0.000    0.480    0.738
##    .complants_2012    0.563    0.043   13.077    0.000    0.563    0.759
##     violent_2011      0.833    0.064   13.077    0.000    0.833    1.000
##     complants_2011    0.790    0.060   13.077    0.000    0.790    1.000


Question 3 Let’s fit the same model, but now not constraining autoregressive and cross-lagged parameters to equality. What happens with the model?

Show me how
# load the lavaan package
library(lavaan)

# specify the model
clpm_model_unconstrained <- '
  violent_2014 ~ violent_2013 + complaints_2013
  violent_2013 ~ violent_2012 + complaints_2012
  violent_2012 ~ violent_2011 + complaints_2011
  
  complaints_2014 ~ complaints_2013 + violent_2013
  complaints_2013 ~ complaints_2012 + violent_2012
  complaints_2012 ~ complaints_2011 + violent_2011
  
  violent_2011 ~~ complaints_2011
  violent_2012 ~~ complaints_2012
  violent_2013 ~~ complaints_2013
  violent_2014 ~~ complaints_2014
'

# fit the CLPM
clpm_unconstrained.fit <- sem(clpm_model_unconstrained, estimator = "ML", data = chicago_wide)

# summary results
summary(clpm_unconstrained.fit, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-19 ended normally after 31 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        24
## 
##   Number of observations                           342
## 
## Model Test User Model:
##                                                       
##   Test statistic                               228.397
##   Degrees of freedom                                12
##   P-value (Chi-square)                           0.000
## 
## Model Test Baseline Model:
## 
##   Test statistic                              2544.730
##   Degrees of freedom                                28
##   P-value                                        0.000
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.914
##   Tucker-Lewis Index (TLI)                       0.799
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)              -2360.286
##   Loglikelihood unrestricted model (H1)      -2246.088
##                                                       
##   Akaike (AIC)                                4768.573
##   Bayesian (BIC)                              4860.608
##   Sample-size adjusted Bayesian (SABIC)       4784.475
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.230
##   90 Percent confidence interval - lower         0.204
##   90 Percent confidence interval - upper         0.256
##   P-value H_0: RMSEA <= 0.050                    0.000
##   P-value H_0: RMSEA >= 0.080                    1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.059
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## Regressions:
##                     Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   violent_2014 ~                                                         
##     violent_2013       0.867    0.024   35.660    0.000    0.867    0.878
##     complants_2013     0.081    0.027    2.982    0.003    0.081    0.073
##   violent_2013 ~                                                         
##     violent_2012       0.950    0.026   36.848    0.000    0.950    0.925
##     complants_2012    -0.026    0.026   -0.990    0.322   -0.026   -0.025
##   violent_2012 ~                                                         
##     violent_2011       0.857    0.022   39.463    0.000    0.857    0.883
##     complants_2011     0.093    0.022    4.154    0.000    0.093    0.093
##   complaints_2014 ~                                                      
##     complants_2013     0.225    0.055    4.098    0.000    0.225    0.219
##     violent_2013       0.279    0.049    5.697    0.000    0.279    0.305
##   complaints_2013 ~                                                      
##     complants_2012     0.255    0.049    5.190    0.000    0.255    0.274
##     violent_2012       0.302    0.048    6.258    0.000    0.302    0.330
##   complaints_2012 ~                                                      
##     complants_2011     0.314    0.052    6.030    0.000    0.314    0.321
##     violent_2011       0.257    0.051    5.073    0.000    0.257    0.270
## 
## Covariances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   violent_2011 ~~                                                       
##     complants_2011    0.392    0.049    8.043    0.000    0.392    0.483
##  .violent_2012 ~~                                                       
##    .complants_2012    0.050    0.013    3.766    0.000    0.050    0.208
##  .violent_2013 ~~                                                       
##    .complants_2013    0.008    0.014    0.548    0.583    0.008    0.030
##  .violent_2014 ~~                                                       
##    .complants_2014    0.041    0.015    2.749    0.006    0.041    0.150
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .violent_2014      0.137    0.010   13.077    0.000    0.137    0.169
##    .violent_2013      0.137    0.010   13.077    0.000    0.137    0.166
##    .violent_2012      0.103    0.008   13.077    0.000    0.103    0.131
##    .complants_2014    0.556    0.043   13.077    0.000    0.556    0.802
##    .complants_2013    0.480    0.037   13.077    0.000    0.480    0.729
##    .complants_2012    0.562    0.043   13.077    0.000    0.562    0.741
##     violent_2011      0.833    0.064   13.077    0.000    0.833    1.000
##     complants_2011    0.790    0.060   13.077    0.000    0.790    1.000


Question 4 Pick your preferred model (i.e., constraining autoregressive and cross-lagged paramters to equality or not). Now, let’s add two time-constant control variables to the cross-lagged panel model: population_density and FAC_disadv. Interpret the estimated coefficients.

Show me how
# specify the model
clpm_model_covariates <- '
  violent_2014 ~ a * violent_2013 + b * complaints_2013
  violent_2013 ~ a * violent_2012 + b * complaints_2012
  violent_2012 ~ a * violent_2011 + b * complaints_2011
  
  complaints_2014 ~ c * complaints_2013 + d * violent_2013
  complaints_2013 ~ c * complaints_2012 + d * violent_2012
  complaints_2012 ~ c * complaints_2011 + d * violent_2011
  
  violent_2011 ~~ complaints_2011
  violent_2012 ~~ complaints_2012
  violent_2013 ~~ complaints_2013
  violent_2014 ~~ complaints_2014
  
  complaints_2011 ~ population_density + FAC_disadv
  violent_2011 ~ population_density + FAC_disadv
'

# fit the CLPM
clpm_fit_cov <- sem(clpm_model_covariates, estimator = "ML", data = chicago_wide)

# summary results
summary(clpm_fit_cov, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-19 ended normally after 29 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        28
##   Number of equality constraints                     8
## 
##   Number of observations                           342
## 
## Model Test User Model:
##                                                       
##   Test statistic                               283.231
##   Degrees of freedom                                32
##   P-value (Chi-square)                           0.000
## 
## Model Test Baseline Model:
## 
##   Test statistic                              2637.815
##   Degrees of freedom                                44
##   P-value                                        0.000
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.903
##   Tucker-Lewis Index (TLI)                       0.867
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)              -2341.161
##   Loglikelihood unrestricted model (H1)      -2199.545
##                                                       
##   Akaike (AIC)                                4722.322
##   Bayesian (BIC)                              4799.018
##   Sample-size adjusted Bayesian (SABIC)       4735.573
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.152
##   90 Percent confidence interval - lower         0.136
##   90 Percent confidence interval - upper         0.168
##   P-value H_0: RMSEA <= 0.050                    0.000
##   P-value H_0: RMSEA >= 0.080                    1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.068
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## Regressions:
##                     Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   violent_2014 ~                                                         
##     vilnt_2013 (a)     0.887    0.014   64.357    0.000    0.887    0.889
##     cmpln_2013 (b)     0.054    0.015    3.719    0.000    0.054    0.049
##   violent_2013 ~                                                         
##     vilnt_2012 (a)     0.887    0.014   64.357    0.000    0.887    0.882
##     cmpln_2012 (b)     0.054    0.015    3.719    0.000    0.054    0.052
##   violent_2012 ~                                                         
##     vilnt_2011 (a)     0.887    0.014   64.357    0.000    0.887    0.905
##     cmpln_2011 (b)     0.054    0.015    3.719    0.000    0.054    0.054
##   complaints_2014 ~                                                      
##     cmpln_2013 (c)     0.260    0.030    8.637    0.000    0.260    0.248
##     vilnt_2013 (d)     0.286    0.028   10.036    0.000    0.286    0.304
##   complaints_2013 ~                                                      
##     cmpln_2012 (c)     0.260    0.030    8.637    0.000    0.260    0.277
##     vilnt_2012 (d)     0.286    0.028   10.036    0.000    0.286    0.317
##   complaints_2012 ~                                                      
##     cmpln_2011 (c)     0.260    0.030    8.637    0.000    0.260    0.268
##     vilnt_2011 (d)     0.286    0.028   10.036    0.000    0.286    0.303
##   complaints_2011 ~                                                      
##     ppltn_dnst        -0.202    0.075   -2.708    0.007   -0.202   -0.141
##     FAC_disadv         0.206    0.042    4.956    0.000    0.206    0.257
##   violent_2011 ~                                                         
##     ppltn_dnst         0.117    0.076    1.536    0.124    0.117    0.079
##     FAC_disadv         0.244    0.042    5.750    0.000    0.244    0.296
## 
## Covariances:
##                      Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##  .complaints_2011 ~~                                                      
##    .violent_2011        0.340    0.044    7.734    0.000    0.340    0.460
##  .violent_2012 ~~                                                         
##    .complants_2012      0.051    0.013    3.835    0.000    0.051    0.212
##  .violent_2013 ~~                                                         
##    .complants_2013      0.008    0.014    0.576    0.565    0.008    0.031
##  .violent_2014 ~~                                                         
##    .complants_2014      0.041    0.015    2.719    0.007    0.041    0.149
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .violent_2014      0.137    0.010   13.077    0.000    0.137    0.171
##    .violent_2013      0.141    0.011   13.077    0.000    0.141    0.175
##    .violent_2012      0.104    0.008   13.077    0.000    0.104    0.130
##    .complants_2014    0.557    0.043   13.077    0.000    0.557    0.782
##    .complants_2013    0.480    0.037   13.077    0.000    0.480    0.738
##    .complants_2012    0.563    0.043   13.077    0.000    0.563    0.759
##    .complants_2011    0.726    0.056   13.077    0.000    0.726    0.919
##    .violent_2011      0.752    0.058   13.077    0.000    0.752    0.903


Question 5 Now, let’s add contemporaneous as paths as well as cross-lags.

Show me how
# specify the model
clpm_model_covariates_contemporaneous <- '
  violent_2014 ~ a * violent_2013 + b * complaints_2013 + e*complaints_2014
  violent_2013 ~ a * violent_2012 + b * complaints_2012 + e*complaints_2013
  violent_2012 ~ a * violent_2011 + b * complaints_2011 + e*complaints_2012
  
  complaints_2014 ~ c * complaints_2013 + d * violent_2013 + f*violent_2014
  complaints_2013 ~ c * complaints_2012 + d * violent_2012 + f*violent_2013
  complaints_2012 ~ c * complaints_2011 + d * violent_2011 + f*violent_2012
  
  violent_2011 ~~ complaints_2011
  violent_2012 ~~ complaints_2012
  violent_2013 ~~ complaints_2013
  violent_2014 ~~ complaints_2014
  
  complaints_2011 ~ population_density + FAC_disadv
  violent_2011 ~ population_density + FAC_disadv
'

# fit the CLPM
clpm_fit_cov_cont <- sem(clpm_model_covariates_contemporaneous, estimator = "ML", data = chicago_wide)

# summary results
summary(clpm_fit_cov_cont, fit.measures = TRUE, standardized = TRUE)
## lavaan 0.6-19 ended normally after 33 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        34
##   Number of equality constraints                    12
## 
##   Number of observations                           342
## 
## Model Test User Model:
##                                                       
##   Test statistic                               283.231
##   Degrees of freedom                                30
##   P-value (Chi-square)                           0.000
## 
## Model Test Baseline Model:
## 
##   Test statistic                              2637.815
##   Degrees of freedom                                44
##   P-value                                        0.000
## 
## User Model versus Baseline Model:
## 
##   Comparative Fit Index (CFI)                    0.902
##   Tucker-Lewis Index (TLI)                       0.857
## 
## Loglikelihood and Information Criteria:
## 
##   Loglikelihood user model (H0)              -2341.161
##   Loglikelihood unrestricted model (H1)      -2199.545
##                                                       
##   Akaike (AIC)                                4726.322
##   Bayesian (BIC)                              4810.687
##   Sample-size adjusted Bayesian (SABIC)       4740.898
## 
## Root Mean Square Error of Approximation:
## 
##   RMSEA                                          0.157
##   90 Percent confidence interval - lower         0.141
##   90 Percent confidence interval - upper         0.174
##   P-value H_0: RMSEA <= 0.050                    0.000
##   P-value H_0: RMSEA >= 0.080                    1.000
## 
## Standardized Root Mean Square Residual:
## 
##   SRMR                                           0.068
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Expected
##   Information saturated (h1) model          Structured
## 
## Regressions:
##                     Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   violent_2014 ~                                                         
##     vilnt_2013 (a)     0.874    0.013   65.912    0.000    0.874    0.876
##     cmpln_2013 (b)     0.042    0.014    3.015    0.003    0.042    0.038
##     cmpln_2014 (e)     0.044    0.004   10.773    0.000    0.044    0.042
##   violent_2013 ~                                                         
##     vilnt_2012 (a)     0.874    0.013   65.912    0.000    0.874    0.870
##     cmpln_2012 (b)     0.042    0.014    3.015    0.003    0.042    0.041
##     cmpln_2013 (e)     0.044    0.004   10.773    0.000    0.044    0.040
##   violent_2012 ~                                                         
##     vilnt_2011 (a)     0.874    0.013   65.912    0.000    0.874    0.893
##     cmpln_2011 (b)     0.042    0.014    3.015    0.003    0.042    0.042
##     cmpln_2012 (e)     0.044    0.004   10.773    0.000    0.044    0.043
##   complaints_2014 ~                                                      
##     cmpln_2013 (c)     0.244    0.030    8.125    0.000    0.244    0.233
##     vilnt_2013 (d)     0.038    0.016    2.324    0.020    0.038    0.040
##     vilnt_2014 (f)     0.279    0.013   20.703    0.000    0.279    0.297
##   complaints_2013 ~                                                      
##     cmpln_2012 (c)     0.244    0.030    8.125    0.000    0.244    0.261
##     vilnt_2012 (d)     0.038    0.016    2.324    0.020    0.038    0.042
##     vilnt_2013 (f)     0.279    0.013   20.703    0.000    0.279    0.311
##   complaints_2012 ~                                                      
##     cmpln_2011 (c)     0.244    0.030    8.125    0.000    0.244    0.252
##     vilnt_2011 (d)     0.038    0.016    2.324    0.020    0.038    0.040
##     vilnt_2012 (f)     0.279    0.013   20.703    0.000    0.279    0.290
##   complaints_2011 ~                                                      
##     ppltn_dnst        -0.202    0.075   -2.708    0.007   -0.202   -0.141
##     FAC_disadv         0.206    0.042    4.956    0.000    0.206    0.257
##   violent_2011 ~                                                         
##     ppltn_dnst         0.117    0.076    1.536    0.124    0.117    0.079
##     FAC_disadv         0.244    0.042    5.750    0.000    0.244    0.296
## 
## Covariances:
##                      Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##  .complaints_2011 ~~                                                      
##    .violent_2011        0.340    0.044    7.734    0.000    0.340    0.460
##  .violent_2012 ~~                                                         
##    .complants_2012     -0.002    0.012   -0.173    0.863   -0.002   -0.009
##  .violent_2013 ~~                                                         
##    .complants_2013     -0.052    0.014   -3.795    0.000   -0.052   -0.200
##  .violent_2014 ~~                                                         
##    .complants_2014     -0.021    0.014   -1.545    0.122   -0.021   -0.079
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .violent_2014      0.135    0.010   13.070    0.000    0.135    0.168
##    .violent_2013      0.141    0.011   13.092    0.000    0.141    0.175
##    .violent_2012      0.101    0.008   13.078    0.000    0.101    0.126
##    .complants_2014    0.545    0.042   13.077    0.000    0.545    0.764
##    .complants_2013    0.486    0.037   13.085    0.000    0.486    0.748
##    .complants_2012    0.543    0.042   13.080    0.000    0.543    0.731
##    .complants_2011    0.726    0.056   13.077    0.000    0.726    0.919
##    .violent_2011      0.752    0.058   13.077    0.000    0.752    0.903


Question 6 As we discussed, the traditional cross-lagged panel model does not properly handle unobserved heterogeneity. Let’s fit Allison et al.’s dynamic panel model with fixed effects. We can use the dpm() function from the dpm package.

This function requires the dataset to be in a long format. Coding is simple, so we can use all 25 years of data! We just need to tell R that this is a panel dataset using the panel_data() function.

# load the dpm package
library(dpm)

# treat the dataset as a panel dataset
chicago.panel <- chicago %>%
  mutate(wave = year - 1990) %>%
  panel_data(id = NC_NUM,
             wave = wave)

The dpm() function is very simple. With a long dataset defined by a panel_data() function, we can simply:

# template to fit a dpm() model
my_dpm <- dpm(dependent_variable ~ pre(lag(independent_variable)) + z | w + v,         # time-varying covariate z | time-constant covariates w and v
              data = my_data, error.inv = T, information = "observed", missing = "ML",
              y.free = F, x.free = F  # constraining autoregressive and cross-lagged panel models to equality
              )

The DPM approach does not permit modelling reciprocal relationships. So, let’s start modelling the effects of complaints about police misuse of force on violent crime while accounting for reverse causality.

Show me how
# fit a DPM with FEs
dpm_violent <- dpm(violent ~ pre(lag(complaints)),
                data = chicago.panel, error.inv = T, information = "observed", missing = "ML")

# print results
summary(dpm_violent)
## MODEL INFO:
## Dependent variable: violent 
## Total observations: 342 
## Complete observations: 342 
## Time periods: 2 - 26 
## 
## MODEL FIT:
## 𝛘²(669) = 2430.269
## RMSEA = 0.088, 90% CI [0.084, 0.092]
## p(RMSEA < .05) = 0
## SRMR = 0.045 
## 
## |                        |  Est. |  S.E. | z val. |     p |
## |:-----------------------|------:|------:|-------:|------:|
## | complaints (t - 1)     | 0.020 | 0.005 |  3.922 | 0.000 |
## | violent (t - 1)        | 0.539 | 0.010 | 52.503 | 0.000 |
## 
## Model converged after 402 iterations


Question 7 Now, let’s add two time-constant control variables to the cross-lagged panel model: population_density and FAC_disadv.

Show me how
# fit a DPM with FEs
dpm_violent_cov <- dpm(violent ~ pre(lag(complaints)) | FAC_disadv + population_density,
                data = chicago.panel, error.inv = T, information = "observed", missing = "ML")

# print results
summary(dpm_violent_cov)
## MODEL INFO:
## Dependent variable: violent 
## Total observations: 342 
## Complete observations: 342 
## Time periods: 2 - 26 
## 
## MODEL FIT:
## 𝛘²(717) = 2558.631
## RMSEA = 0.087, 90% CI [0.083, 0.09]
## p(RMSEA < .05) = 0
## SRMR = 0.047 
## 
## |                        |  Est. |  S.E. | z val. |     p |
## |:-----------------------|------:|------:|-------:|------:|
## | complaints (t - 1)     | 0.021 | 0.005 |  4.050 | 0.000 |
## | FAC_disadv             | 0.129 | 0.017 |  7.662 | 0.000 |
## | population_density     | 0.089 | 0.030 |  3.001 | 0.003 |
## | violent (t - 1)        | 0.539 | 0.010 | 52.492 | 0.000 |
## 
## Model converged after 509 iterations


Question 8 Let’s now fit Hamaker et al.’s Random Intercepts Cross-Lagged Panel Model. Unfortunately, the RI-CLPM is not fully implemented in any packages—so we need to rely on lavaan and manually code the model.

Show me how
RICLPM <- '
  # Create between components (random intercepts)
  RI_complaints =~ 1*complaints_2011 + 1*complaints_2012 + 1*complaints_2013 + 1*complaints_2014
  RI_violent =~ 1*violent_2011 + 1*violent_2012 + 1*violent_2013 + 1*violent_2014
  
  # Create within-person centered variables
  wcomplaints_2011 =~ 1*complaints_2011
  wcomplaints_2012 =~ 1*complaints_2012
  wcomplaints_2013 =~ 1*complaints_2013 
  wcomplaints_2014 =~ 1*complaints_2014
  wviolent_2011 =~ 1*violent_2011
  wviolent_2012 =~ 1*violent_2012
  wviolent_2013 =~ 1*violent_2013
  wviolent_2014 =~ 1*violent_2014

  # Estimate lagged effects between within-person centered variables
  wcomplaints_2012 ~ wcomplaints_2011 + wviolent_2011
  wviolent_2012 ~ wcomplaints_2011 + wviolent_2011
  wcomplaints_2013 ~ wcomplaints_2012 + wviolent_2012
  wviolent_2013 ~ wcomplaints_2012 + wviolent_2012
  wcomplaints_2014 ~ wcomplaints_2013 + wviolent_2013
  wviolent_2014 ~ wcomplaints_2013 + wviolent_2013

  # Estimate covariance between within-person centered variables at first wave
  wcomplaints_2011 ~~ wviolent_2011 # Covariance
  
  # Estimate covariances between residuals of within-person centered variables 
  wcomplaints_2012 ~~ wviolent_2012
  wcomplaints_2013 ~~ wviolent_2013
  wcomplaints_2014 ~~ wviolent_2014
  
  # Estimate variance and covariance of random intercepts
  RI_complaints ~~ RI_complaints
  RI_violent ~~ RI_violent
  RI_complaints ~~ RI_violent

  # Estimate (residual) variance of within-person centered variables
  wcomplaints_2011 ~~ wcomplaints_2011 # Variances
  wviolent_2011 ~~ wviolent_2011 
  wcomplaints_2012 ~~ wcomplaints_2012 # Residual variances
  wviolent_2012 ~~ wviolent_2012 
  wcomplaints_2013 ~~ wcomplaints_2013 
  wviolent_2013 ~~ wviolent_2013 
  wcomplaints_2014 ~~ wcomplaints_2014 
  wviolent_2014 ~~ wviolent_2014 
'

RICLPM_nocovs <- lavaan(RICLPM, 
  data = chicago_wide, 
  missing = 'ML', 
  meanstructure = T, 
  int.ov.free = T)

summary(RICLPM_nocovs, standardized = T)
## lavaan 0.6-19 ended normally after 63 iterations
## 
##   Estimator                                         ML
##   Optimization method                           NLMINB
##   Number of model parameters                        35
## 
##   Number of observations                           342
##   Number of missing patterns                         1
## 
## Model Test User Model:
##                                                       
##   Test statistic                                21.526
##   Degrees of freedom                                 9
##   P-value (Chi-square)                           0.011
## 
## Parameter Estimates:
## 
##   Standard errors                             Standard
##   Information                                 Observed
##   Observed information based on                Hessian
## 
## Latent Variables:
##                       Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   RI_complaints =~                                                         
##     complants_2011       1.000                               0.515    0.597
##     complants_2012       1.000                               0.515    0.602
##     complants_2013       1.000                               0.515    0.613
##     complants_2014       1.000                               0.515    0.609
##   RI_violent =~                                                            
##     violent_2011         1.000                               0.862    0.953
##     violent_2012         1.000                               0.862    0.955
##     violent_2013         1.000                               0.862    0.950
##     violent_2014         1.000                               0.862    0.955
##   wcomplaints_2011 =~                                                      
##     complants_2011       1.000                               0.692    0.802
##   wcomplaints_2012 =~                                                      
##     complants_2012       1.000                               0.683    0.798
##   wcomplaints_2013 =~                                                      
##     complants_2013       1.000                               0.663    0.790
##   wcomplaints_2014 =~                                                      
##     complants_2014       1.000                               0.670    0.793
##   wviolent_2011 =~                                                         
##     violent_2011         1.000                               0.273    0.302
##   wviolent_2012 =~                                                         
##     violent_2012         1.000                               0.267    0.296
##   wviolent_2013 =~                                                         
##     violent_2013         1.000                               0.285    0.314
##   wviolent_2014 =~                                                         
##     violent_2014         1.000                               0.268    0.297
## 
## Regressions:
##                      Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   wcomplaints_2012 ~                                                      
##     wcomplnts_2011      0.102    0.069    1.476    0.140    0.104    0.104
##     wviolent_2011      -0.447    0.289   -1.550    0.121   -0.179   -0.179
##   wviolent_2012 ~                                                         
##     wcomplnts_2011      0.050    0.027    1.849    0.064    0.129    0.129
##     wviolent_2011       0.194    0.157    1.233    0.218    0.198    0.198
##   wcomplaints_2013 ~                                                      
##     wcomplnts_2012      0.103    0.068    1.517    0.129    0.106    0.106
##     wviolent_2012       0.524    0.213    2.459    0.014    0.211    0.211
##   wviolent_2013 ~                                                         
##     wcomplnts_2012     -0.077    0.034   -2.277    0.023   -0.185   -0.185
##     wviolent_2012       0.090    0.120    0.753    0.451    0.085    0.085
##   wcomplaints_2014 ~                                                      
##     wcomplnts_2013      0.018    0.075    0.237    0.812    0.018    0.018
##     wviolent_2013      -0.155    0.205   -0.754    0.451   -0.066   -0.066
##   wviolent_2014 ~                                                         
##     wcomplnts_2013      0.058    0.036    1.617    0.106    0.144    0.144
##     wviolent_2013       0.011    0.171    0.066    0.947    0.012    0.012
## 
## Covariances:
##                       Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##   wcomplaints_2011 ~~                                                      
##     wviolent_2011        0.003    0.015    0.223    0.824    0.018    0.018
##  .wcomplaints_2012 ~~                                                      
##    .wviolent_2012        0.009    0.018    0.500    0.617    0.053    0.053
##  .wcomplaints_2013 ~~                                                      
##    .wviolent_2013        0.019    0.015    1.264    0.206    0.106    0.106
##  .wcomplaints_2014 ~~                                                      
##    .wviolent_2014        0.004    0.015    0.238    0.812    0.021    0.021
##   RI_complaints ~~                                                         
##     RI_violent           0.347    0.035    9.788    0.000    0.781    0.781
## 
## Intercepts:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##    .complants_2011    1.137    0.047   24.377    0.000    1.137    1.318
##    .complants_2012    0.945    0.046   20.426    0.000    0.945    1.105
##    .complants_2013    0.826    0.045   18.188    0.000    0.826    0.984
##    .complants_2014    0.717    0.046   15.675    0.000    0.717    0.848
##    .violent_2011      3.408    0.049   69.683    0.000    3.408    3.768
##    .violent_2012      3.386    0.049   69.378    0.000    3.386    3.752
##    .violent_2013      3.257    0.049   66.327    0.000    3.257    3.587
##    .violent_2014      3.070    0.049   62.876    0.000    3.070    3.400
## 
## Variances:
##                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
##     RI_complaints     0.265    0.033    8.080    0.000    1.000    1.000
##     RI_violent        0.743    0.059   12.701    0.000    1.000    1.000
##     wcomplnts_2011    0.479    0.045   10.746    0.000    1.000    1.000
##     wviolent_2011     0.074    0.014    5.143    0.000    1.000    1.000
##    .wcomplnts_2012    0.447    0.048    9.366    0.000    0.958    0.958
##    .wviolent_2012     0.067    0.012    5.624    0.000    0.943    0.943
##    .wcomplnts_2013    0.415    0.039   10.583    0.000    0.943    0.943
##    .wviolent_2013     0.078    0.015    5.058    0.000    0.959    0.959
##    .wcomplnts_2014    0.447    0.043   10.425    0.000    0.996    0.996
##    .wviolent_2014     0.070    0.015    4.602    0.000    0.979    0.979
##    .complants_2011    0.000                               0.000    0.000
##    .complants_2012    0.000                               0.000    0.000
##    .complants_2013    0.000                               0.000    0.000
##    .complants_2014    0.000                               0.000    0.000
##    .violent_2011      0.000                               0.000    0.000
##    .violent_2012      0.000                               0.000    0.000
##    .violent_2013      0.000                               0.000    0.000
##    .violent_2014      0.000                               0.000    0.000


Question 7 Repeat the procedures above to model the effects of violent crime on complaints about police misuse of force accounting for reverse causality.