data-raw/01_analyzed_data_plac.md

Analyzed data

Benny Salo 2018-06-18

Setup

library(dplyr)

Load data

Import data set 'FinPrisonMales'. This version of the data includes only males. Data is not publicly available.

rm(list = ls())
devtools::wd()
FinPrisonMales <- readRDS("not_public/FinPrisonMales.rds")

Variables

Name levels of the key variables clearly

levels(FinPrisonMales$openPrison)
## [1] "closed_prison" "open_prison"
levels(FinPrisonMales$openPrison) <- 
  c("Closed_prison", "Open_prison")

levels(FinPrisonMales$supervisedParole)
## [1] "no supervision"    "supervised parole"
levels(FinPrisonMales$supervisedParole) <-
  c("No_parole_supervision", "Parole_was_supervised")

levels(FinPrisonMales$conditionalReleaseGranted) 
## [1] "cr_not_granted" "cr_granted"
levels(FinPrisonMales$conditionalReleaseGranted) <- 
  c("Not_granted", "Granted")

levels(FinPrisonMales$conditionalReleaseOutcome) 
## [1] "No conditional release"        "Successful conditional relase"
## [3] "Cancelled conditional release"
levels(FinPrisonMales$conditionalReleaseOutcome) <- 
  c("No_conditional_release", "Successful_conditional_relase", "Cancelled_conditional_release")

Create new variable indicating both placement in open prison and in addition successful conditional release. This will be used for calculating 'overarching propensity score'.

FinPrisonMales <- FinPrisonMales %>% 
  mutate(open_and_cr = 
           ifelse(openPrison == "Open_prison" & 
                  conditionalReleaseOutcome == "Successful_conditional_relase",
                  "yes", "no"))

Exclude irrelevant variables with missing values. Matchit does not allow missing values and they will not be needed anyway.

index_no_missing <- apply(FinPrisonMales, MARGIN = 2, FUN = anyNA) == FALSE

FinPrisonMales   <- FinPrisonMales[index_no_missing]

The package MatchIt uses dichotomous integer variables for outcomes when calculating propensity scores. Add these.

FinPrisonMales <-
  FinPrisonMales %>% 
  # Numeric versions of the factors have integers 1 and 2.
  # Subtracting 1 puts them on a logical 0, 1 scale.
  mutate(open01      = as.numeric(openPrison) - 1,
         cond01      = as.numeric(conditionalReleaseGranted) - 1,
         reoffence01 = 
           ifelse(reoffenceThisTerm == "new_prison_sentence",
                  1, 0),
         open_and_cr01 = 
           ifelse(open_and_cr == "yes", 1, 0))
  # The following will probably be deleted.
  # We also want reversed codings with closed and no CR coded as 1
  # We achieve this by subtracting 2. (Results in -1, 0)
  # and taking the absolute value (results in 1, 0)
         # open10 = abs(as.numeric(openPrison) - 2),
         # cond10 = abs(as.numeric(conditionalReleaseGranted) - 2))

Define sets of predictors

The vector all_predictors will be used to write the formula for propensity scores.

offence_variables <- 
  stringr::str_subset(names(FinPrisonMales), "^o_")

static_preds <- 
   c("ageFirstSentence_mr", "ageFirst_missing", "ageAtRelease", 
     "ps_escapeHistory", "ps_prisonTerms_mr", "ps_comServiceTerms_mr", 
     "ps_remandTerms_mr", "ps_defaultTerms_mr", "ps_info_missing", 
     offence_variables)


rita_factors <- 
   c("economy_problems", "alcohol_problems", "resistance_change", 
     "drug_related_probl", "aggressiveness", "employment_probl") 


all_predictors <- c(static_preds, rita_factors)

devtools::use_data(all_predictors, overwrite = TRUE)
devtools::use_data(static_preds, overwrite = TRUE)
devtools::use_data(rita_factors, overwrite = TRUE)

Exclusion and inclusion

Exclude individuals who committed a crime during the sentence. This is the simplest way to handle the issue that we do not know when the crime was committed, when it was uncovered, or how it affected placement decisions.

These are 93 individuals

table(FinPrisonMales$crimeDuringSentence)
## 
## No records of crime     Record of crime 
##                1403                  93
analyzed_data_plac <-
  FinPrisonMales %>% 
  filter(crimeDuringSentence == "No records of crime")

rm(FinPrisonMales)

This is the distribution of individuals over status of placement at release and conditional release:

knitr::kable(
  table(analyzed_data_plac$openPrison,
        analyzed_data_plac$conditionalReleaseOutcome)
  )

| | No_conditional_release| Successful_conditional_relase| Cancelled_conditional_release| |----------------|-------------------------:|--------------------------------:|--------------------------------:| | Closed_prison | 668| 38| 48| | Open_prison | 411| 220| 18|

We exclude individuals with suspended conditional release. This is the easiest way to handle the confounding that individuals granted conditional release from open prison may have been placed in closed prison if the conditional release was revoked.

analyzed_data_plac <-
  analyzed_data_plac %>% 
  filter(conditionalReleaseOutcome != "Cancelled_conditional_release")

# Remove the excluded level for conditional release.
levels(analyzed_data_plac$conditionalReleaseOutcome) <- 
  c("No_conditional_release", "Successful_conditional_release", NA)

Further we separate those with their parole supervised and those without supervision.

knitr::kable(
  table(
    analyzed_data_plac$conditionalReleaseOutcome,
    analyzed_data_plac$openPrison,
    analyzed_data_plac$supervisedParole),
    col.names = c("Conditional release", "Placement", "Supervision", "Freq")
  )

| Conditional release | Placement | Supervision | Freq| |:---------------------------------|:---------------|:------------------------|-----:| | No_conditional_release | Closed_prison | No_parole_supervision | 241| | Successful_conditional_release | Closed_prison | No_parole_supervision | 9| | No_conditional_release | Open_prison | No_parole_supervision | 148| | Successful_conditional_release | Open_prison | No_parole_supervision | 50| | No_conditional_release | Closed_prison | Parole_was_supervised | 427| | Successful_conditional_release | Closed_prison | Parole_was_supervised | 29| | No_conditional_release | Open_prison | Parole_was_supervised | 263| | Successful_conditional_release | Open_prison | Parole_was_supervised | 170|

The smallest groups (individuals placed in closed prison but granted conditional release, [9 not supervised, 29 supervised]) will not be examined further. That leaves us with the possibility to make the following comparisons:

  1. the effect of open prison among those not granted conditional release
    1. when parole was not supervised (closed [241] vs. open prison [148])
    2. when parole was supervised (closed [427] vs. open [263])
  2. the effect of conditional release among those placed in open prison at the end of their sentence
    1. when parole was not supervised (no release[148] vs. successful release [50])
    2. when parole was supervised (no [263] vs. successful [170])

Create subsets

We create a subset for each of the four (2 x 2) comparisons above.

  1. Effect of open prison (when conditional release is not granted).

    • when parole is NOT supervised

    r op_cr0_ps0<- analyzed_data_plac %>% filter(conditionalReleaseOutcome == "No_conditional_release" & supervisedParole == "No_parole_supervision")

    • when parole IS supervised

    r op_cr0_ps1 <- analyzed_data_plac %>% filter(conditionalReleaseOutcome == "No_conditional_release" & supervisedParole == "Parole_was_supervised")

  2. Effect of conditional release (for individuals placed in open prison)

    • when parole is NOT supervised

    r cr_op1_ps0 <- analyzed_data_plac %>% filter(openPrison == "Open_prison" & supervisedParole == "No_parole_supervision")

    • when parole IS supervised

    r cr_op1_ps1 <- analyzed_data_plac %>% filter(openPrison == "Open_prison" & supervisedParole == "Parole_was_supervised")

Assertions. Make sure the subsets have the expected number of observations.

stopifnot(nrow(op_cr0_ps0) == (241 + 148))
stopifnot(nrow(op_cr0_ps1) == (427 + 263))
stopifnot(nrow(cr_op1_ps0) == (148 + 50))
stopifnot(nrow(cr_op1_ps1) == (263 + 170))

Make a list for each subset that also contains the name of the effect variable and a description of inclusion criteria.

op_cr0_ps0 <- list(effect_variable = "openPrison",
                   inclusion_criteria = 
                     "No conditional release, parole NOT supervised",
                   data = op_cr0_ps0)

op_cr0_ps1 <- list(effect_variable = "openPrison",
                   inclusion_criteria = 
                     "No conditional release, parole WAS supervised",
                   data = op_cr0_ps1)

cr_op1_ps0  <- list(effect_variable = "conditionalReleaseOutcome",
                   inclusion_criteria = 
                     "Released from open prison, parole NOT supervised",
                   data = cr_op1_ps0)

cr_op1_ps1  <- list(effect_variable = "conditionalReleaseOutcome",
                   inclusion_criteria = 
                     "Released from open prison, parole WAS supervised",
                   data = cr_op1_ps1)

Assertions. Check that the script above has produced a list with three elements with correct names and of correct classes.

check_list_elements <- function(x) {
  assertthat::assert_that(
    class(cr_op1_ps1$effect_variable) == "character",
    class(cr_op1_ps1$inclusion_criteria) == "character",
    class(cr_op1_ps1$data) == "data.frame",
    msg = " The list does not contain the expected elements."
  )
}

check_list_elements(op_cr0_ps0)
## [1] TRUE
check_list_elements(op_cr0_ps1)
## [1] TRUE
check_list_elements(cr_op1_ps0)
## [1] TRUE
check_list_elements(cr_op1_ps1)
## [1] TRUE

Save subset list for later use.

devtools::wd()
saveRDS(op_cr0_ps0, "not_public/op_cr0_ps0.rds")
saveRDS(op_cr0_ps1, "not_public/op_cr0_ps1.rds")
saveRDS(cr_op1_ps0, "not_public/cr_op1_ps0.rds")
saveRDS(cr_op1_ps1, "not_public/cr_op1_ps1.rds")
saveRDS(analyzed_data_plac, "not_public/analyzed_data_plac.rds")


bennysalo/placement-and-recidivism documentation built on May 21, 2019, 9:47 a.m.