ABSTRACT: A mindset shift in the 1970s to more “tough-on-crime” politics led to harsher sentencing policies across the United States. As a result, in 1976, Maine became the first state out of 16 to abolish parole, which is the conditional release of an inmate before they complete their prison sentence. In the last 5 years, some states began to doubt their decisions on the effectiveness of abolishing parole. In 2021, a bill to reestablish parole in Maine was introduced and as a result of this bill a 13 member commission to study restoring parole in Maine was created. This project is inspired by the ongoing conversation about parole in Maine, and the fact that inmates in Maine have very few opportunities for early release and rehabilitation. In this work I conduct a data analysis to model the potential impact of reinstating parole in Maine. There is a particular focus on changes in inmate sentence lengths as well as the economic impact if Maine were to implement the parole systems of Wyoming and Vermont.

Data Setup

#Installing and loading necessary packages

# install.packages("skimr", "haven", "tidyverse", "dplyr", "psych", "DT", "foreign", "gridExtra", "knitr", "kableExtra")
#library(haven)
library(tidyverse)
library(dplyr)
library(psych)
library(DT)
library(foreign)
library(skimr)
library(gridExtra)
library(kableExtra)
library(tinytex)

#update.packages(ask = FALSE, checkBuilt = TRUE)
#tinytex::tlmgr_update()

#loading dataset
load("C:/Users/smangane/OneDrive - bates.edu/Bates Parole Thesis/BatesParoleThesis/DS0001/38492-0001-Data.rda") 

#filtering for Maine
 ME_term_records <- da38492.0001 %>%
  filter(STATE == "(23) Maine") 

Basic Summary Statistics/EDA - (ME Term Records)

The skim() function in R gives us a broad overview of our data frame. The table is organized by factor and numeric variables. It shows the amount of missing, and unique (or distinct) values as well as the most common values for each factored variable. For our numeric variables, we can see missing values as well as the mean, median, and distribution of values.

#skimming the data set and renaming columns
skim(ME_term_records) %>%  
  kbl(caption = "Dataset Overview", 
      col.names = c("Variable Type", "Variable (Column Name)", "Missing Rows", "Completion Rate", "Ordered?", "Unique Rows", "Most Common Values", "Mean", "Standard Deviation", "Minimum", "25th Quartile", "Median", "75th Quartile", "Maximum", "Histogram")) %>%
  kable_minimal() %>% 
  scroll_box(width = "100%", height = "500px")#creating table
Dataset Overview
Variable Type Variable (Column Name) Missing Rows Completion Rate Ordered? Unique Rows Most Common Values Mean Standard Deviation Minimum 25th Quartile Median 75th Quartile Maximum Histogram
factor ABT_INMATE_ID 0 1.0000000 FALSE 9694 A23: 7, A23: 6, A23: 6, A23: 5 NA NA NA NA NA NA NA NA
factor SEX 0 1.0000000 FALSE 2 (1): 11093, (2): 1516 NA NA NA NA NA NA NA NA
factor ADMTYPE 69 0.9945277 FALSE 3 (1): 12077, (2): 397, (3): 66 NA NA NA NA NA NA NA NA
factor OFFGENERAL 135 0.9892934 FALSE 5 (1): 4825, (2): 3610, (3): 2668, (4): 1280 NA NA NA NA NA NA NA NA
factor EDUCATION 0 1.0000000 FALSE 1 (9): 12609 NA NA NA NA NA NA NA NA
factor SENTLGTH 164 0.9869934 FALSE 7 (2): 4320, (0): 3098, (1): 2999, (3): 1231 NA NA NA NA NA NA NA NA
factor OFFDETAIL 135 0.9892934 FALSE 13 (12: 2668, (05: 2197, (07: 1664, (08: 1345 NA NA NA NA NA NA NA NA
factor RACE 243 0.9807281 FALSE 3 (1): 10619, (2): 1154, (4): 593, (3): 0 NA NA NA NA NA NA NA NA
factor AGEADMIT 0 1.0000000 FALSE 5 (2): 5297, (3): 3147, (1): 1964, (4): 1602 NA NA NA NA NA NA NA NA
factor AGERELEASE 1726 0.8631136 FALSE 5 (2): 4590, (3): 2982, (4): 1536, (1): 1113 NA NA NA NA NA NA NA NA
factor TIMESRVD 1726 0.8631136 FALSE 5 (0): 4914, (1): 3332, (2): 2077, (3): 417 NA NA NA NA NA NA NA NA
factor RELTYPE 2670 0.7882465 FALSE 3 (1): 5043, (2): 4770, (3): 126 NA NA NA NA NA NA NA NA
factor STATE 0 1.0000000 FALSE 1 (23: 12609, (01: 0, (02: 0, (04: 0 NA NA NA NA NA NA NA NA
numeric ADMITYR 0 1.0000000 NA NA NA 2014.650 4.165646 1970 2013 2015 2018 2020 ▁▁▁▁▇
numeric RELEASEYR 1726 0.8631136 NA NA NA 2016.167 2.538238 2012 2014 2016 2018 2020 ▆▇▃▇▇
numeric MAND_PRISREL_YEAR 12609 0.0000000 NA NA NA NaN NA NA NA NA NA NA
numeric PROJ_PRISREL_YEAR 12609 0.0000000 NA NA NA NaN NA NA NA NA NA NA
numeric PARELIG_YEAR 12609 0.0000000 NA NA NA NaN NA NA NA NA NA NA
#factoring the ages and offenses renaming columns 
ME_term_records <- ME_term_records  %>% 
    mutate_at(vars(AGEADMIT, AGERELEASE),
              factor,
              levels = c("(1) 18-24 years", "(2) 25-34 years",  "(3) 35-44 years",  "(4) 45-54 years", "(5) 55+ years"),
              ordered = TRUE) %>% 
  mutate_at(vars(OFFGENERAL),
            factor,
            levels = c("(1) Violent", "(2) Property",   "(3) Drugs",    "(4) Public order", "(5) Other/unspecified"),
            ordered = TRUE)

Frequency of Admittance in Maine (1991-2020) - looking at reoffenders

To see each individual case, I grouped the data frame by ID number, since a person could be released more than once and as a result have more than one record (only available in DS0001). There are 9,694 distinct prisoners in the ME_term_records data set. Below I create a histogram of the frequency of admittance in Maine, to get an estimate of re-offenders in Maine. About 41% of all inmates in this data set are repeat offenders.

#creating a variable that states inmates as repeat offenders or not
me_analysis <- ME_term_records %>%
  count(ABT_INMATE_ID, sort = TRUE) %>%
  mutate(Repeat_Offender = case_when(
    n > 1 ~ "Yes",
    TRUE ~ "No"
  )) %>% 
  full_join(ME_term_records, by = "ABT_INMATE_ID") %>% 
  rename("In_Datasetx" = "n")

#creating a histogram
 me_analysis %>%
  ggplot(aes(In_Datasetx)) + 
  geom_bar() +
     labs(title = "Frequency of Admittance in Maine (1991-2020)", x ="Number of Times an Inmate was Admitted", y = "Frquency of Inmates Admitted")

Frequency of Parole Violator Admissions in Maine

Below, I create a histogram of the distribution of parole violator admittance (those who were admitted because they violated parole) in Maine. Of those 9,694 observations, 238 have been admitted because they violated their parole. Considering that Maine no longer has parole, the percentage of parole violator admissions is extremely low. Most inmates have returned to prison only once for violating parole.

#code for percentages of distribution of admissions type
# me_analysis %>% 
#   distinct(ABT_INMATE_ID, .keep_all = TRUE) %>% 
#   count(ADMTYPE) %>% 
#   mutate(Percent = paste((n/9694)*100,seperate = "%"))

#creating graph
 me_analysis %>%
   filter(ADMTYPE == "(2) Parole return/revocation") %>%
   count(ABT_INMATE_ID, sort = TRUE) %>%
   ggplot(aes(n)) + 
  geom_bar() +
     labs(title = "Frequency of Parole Violator Admissions in Maine (1991-2020)", x ="Number of Times an Inmate was Admitted for Violating Parole", y = "Frquency of Inmates Admitted")

Distribution of Time Served in Maine

Below is a table of the distributions of time served in this data set and the percentage of inmates in that category. More than 50% of the data set (over the course of 29 years) has served less than 2 years in prison.

#Create table of percentages of time served    
me_analysis %>%
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  count(TIMESRVD) %>% 
  mutate(Percent = paste(round((n/9694)*100,digits = 2),seperate = "%"))  %>% 
  rename("Time Served" = "TIMESRVD",
         "Number of Inmates (Observations)" = "n",
         "% of Inmates in Dataset" = "Percent") %>% 
  kbl(caption = "Percentages of Time Served") %>%
  kable_minimal()
Percentages of Time Served
Time Served Number of Inmates (Observations) % of Inmates in Dataset
  1. < 1 year
3735 38.53 %
  1. 1-1.9 years
2506 25.85 %
  1. 2-4.9 years
1596 16.46 %
  1. 5-9.9 years
383 3.95 %
  1. >=10 years
138 1.42 %
NA 1336 13.78 %
#creating an exact time served  variable
me_analysis <- me_analysis %>%
  mutate(exact_time_served = RELEASEYR - ADMITYR) 

Average Sentence Length By Crime

Below is a table of the average sentence length for each offense and their percentage of the data set population. Most inmates (61.53%) in this data set were convicted of a drug, aggravated/simple assault, burglary, or public order offense, all of which have an average sentence length of fewer than 2 years as well.

#table of percentages of dataset population by offense
ro <- me_analysis %>% 
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  count(OFFDETAIL) %>% 
  mutate(Perc_of_prisonpop = paste(round((n/9694)*100,digits = 2),seperate = "%")) %>%
  select("OFFDETAIL", "Perc_of_prisonpop")

#combing dataframe above with table of average sentence lengths 
avg_senlgth <- me_analysis %>%
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  group_by(OFFDETAIL) %>%
  summarize(Avg_sentlgth = mean(exact_time_served, na.rm = TRUE)) %>% 
  full_join(ro, by = "OFFDETAIL") %>% 
  mutate(Avg_sentlgth = round(Avg_sentlgth, digits = 1))  %>% 
  rename("Offense Categorization" = "OFFDETAIL",
         "Avg. Sent. Length" = "Avg_sentlgth",
         "% of Prison Pop." = "Perc_of_prisonpop")

#creating table
avg_senlgth %>% 
  kbl(caption = "Average Sentence Length for Each Offense") %>%
  kable_minimal()
Average Sentence Length for Each Offense
Offense Categorization Avg. Sent. Length % of Prison Pop.
  1. Murder (including non-negligent manslaughter)
14.8 3.08 %
  1. Negligent manslaughter
5.2 1.72 %
  1. Rape/sexual assault
3.5 9.2 %
  1. Robbery
2.9 6.56 %
  1. Aggravated or simple assault
1.5 16.93 %
  1. Other violent offenses
2.0 1.33 %
  1. Burglary
1.7 12.13 %
  1. Larceny
1.1 9.93 %
  1. Fraud
1.3 2.49 %
  1. Other property offenses
1.9 2.24 %
  1. Drugs (includes possession, distribution, trafficking, other)
1.4 22.33 %
  1. Public order
1.2 10.14 %
  1. Other/unspecified
3.9 0.79 %
NA 0.5 1.11 %

Initial Analysis

How Certain Are Prison’s Sentence Length in Maine?

To evaluate determinacy in Maine, I calculate what percentage of inmates were released before, within, or after their mandatory prison release year (determined by the maximum sentence length). Despite not knowing the release year of about 15% of inmates (due to missing release years or maximum sentence lengths, see section 2.2), only 0.86% aren’t released earlier or at the release date they’re supposed to. Thus it seems like prison sentence lengths are fixed in Maine.

#creating 4 variables: earliest and latest mand. prison release, released early variables (in character and numeric form)
me_analysis <- me_analysis %>% 
  mutate(Earliest_MAND_PRISREL_YEAR = case_when( #max sent.length + admit yr
     SENTLGTH == "(0) < 1 year" ~ ADMITYR,
     SENTLGTH == "(1) 1-1.9 years" ~ ADMITYR + 1, 
     SENTLGTH == "(2) 2-4.9 years" ~ ADMITYR + 2, 
     SENTLGTH == "(3) 5-9.9 years" ~ ADMITYR + 5, 
     SENTLGTH == "(4) 10-24.9 years" ~ ADMITYR + 10,
    SENTLGTH == "(5) >=25 years" ~ ADMITYR + 25,
   ), Latest_MAND_PRISREL_YEAR = case_when(
     SENTLGTH == "(0) < 1 year" ~ ADMITYR + 1,
     SENTLGTH == "(1) 1-1.9 years" ~ ADMITYR + 2, 
     SENTLGTH == "(2) 2-4.9 years" ~ ADMITYR + 5,
     SENTLGTH == "(3) 5-9.9 years" ~ ADMITYR + 10, 
     SENTLGTH == "(4) 10-24.9 years" ~ ADMITYR + 25,
    SENTLGTH == "(5) >=25 years" ~ NA_real_,
   )
   ) %>% 
  mutate(Released_early_dbl = case_when(
    RELEASEYR < Earliest_MAND_PRISREL_YEAR ~ paste(Earliest_MAND_PRISREL_YEAR - RELEASEYR, " year(s) earlier"),
    RELEASEYR == Earliest_MAND_PRISREL_YEAR ~ "0",
    RELEASEYR > Earliest_MAND_PRISREL_YEAR & RELEASEYR < Latest_MAND_PRISREL_YEAR ~ paste(Latest_MAND_PRISREL_YEAR - RELEASEYR, " year(s) within mand prison release"),
    RELEASEYR > Earliest_MAND_PRISREL_YEAR & RELEASEYR == Latest_MAND_PRISREL_YEAR ~ "0",
    RELEASEYR > Earliest_MAND_PRISREL_YEAR & RELEASEYR > Latest_MAND_PRISREL_YEAR ~ paste(RELEASEYR - Latest_MAND_PRISREL_YEAR, " years later")
  )) %>%
    mutate(Release_early_chr = case_when(
      RELEASEYR < Earliest_MAND_PRISREL_YEAR ~ "Yes",
      RELEASEYR == Earliest_MAND_PRISREL_YEAR ~ "Same Time",
      RELEASEYR > Earliest_MAND_PRISREL_YEAR & RELEASEYR < Latest_MAND_PRISREL_YEAR ~ "Same Time",
    RELEASEYR > Earliest_MAND_PRISREL_YEAR & RELEASEYR == Latest_MAND_PRISREL_YEAR ~ "Same Time",
    RELEASEYR > Earliest_MAND_PRISREL_YEAR & RELEASEYR > Latest_MAND_PRISREL_YEAR ~ "No"))
      

#table to see when people are released
me_analysis %>%
  count(Release_early_chr) %>% 
  mutate(Percent = paste(round((n/12609)*100, digits = 2),seperate = "%")) %>% 
  rename("Released Before Mandatory Release Year" = "Release_early_chr",
         "Number of Inmates (Observations)" = "n",
         "% of Inmates in Dataset" = "Percent") %>% 
  kbl(caption = "Percentages of When Inmates Are Released") %>%
  kable_minimal()
Percentages of When Inmates Are Released
Released Before Mandatory Release Year Number of Inmates (Observations) % of Inmates in Dataset
No 108 0.86 %
Same Time 8270 65.59 %
Yes 2349 18.63 %
NA 1882 14.93 %

Truth in Sentencing?

I also calculate the percentage of inmates serving at least 85% of their sentence. This isn’t possible for prisoners who serve less than 1 year and more than 25 years, since the units are in years and I can’t determine what their maximum sentence length is. Nonetheless, for the inmates, we can calculate it for, a majority of inmates in Maine serve at least 85% of their prison sentence lengths, which lines up with truth-in-sentencing laws passed and ‘fixedness’ we see in the table above.

#creating variable which determines the 85% mark of a prisoner's sentence
me_analysis <- me_analysis %>% 
  mutate(etisyear = case_when(
     SENTLGTH == "(1) 1-1.9 years" ~ 1 * .85, 
     SENTLGTH == "(2) 2-4.9 years" ~ 2 * .85, 
     SENTLGTH == "(3) 5-9.9 years" ~ 5 * .85, 
     SENTLGTH == "(4) 10-24.9 years" ~ 10 * .85,
    SENTLGTH == "(5) >=25 years" ~ 25 * .85,
   ),ltisyear = case_when(
    SENTLGTH == "(0) < 1 year" ~ 1 *.85,
     SENTLGTH == "(1) 1-1.9 years" ~ 2 * .85, 
     SENTLGTH == "(2) 2-4.9 years" ~ 5 * .85, 
     SENTLGTH == "(3) 5-9.9 years" ~ 10 * .85, 
     SENTLGTH == "(4) 10-24.9 years" ~ 25 * .85
   ), servedperc = case_when( #variables above compared to their exact time served
     SENTLGTH == "(0) < 1 year" ~ "Served less than a year",
     SENTLGTH == "(5) >=25 years" ~ "Served more than 25 years",
     exact_time_served >= etisyear & exact_time_served <= ltisyear ~ "85% or more",
     exact_time_served >= ltisyear ~ "85% or more",
     exact_time_served < etisyear ~ "Less than 85%"
   ))

#creating table of percentages of inmates of above
me_analysis %>% 
  count(servedperc) %>% 
  mutate(Percent = paste(round((n/12609)*100, digits = 2),seperate = "%")) %>% 
  rename("Percentage Served" = "servedperc",
         "Number of Inmates (Observations)" = "n",
         "% of Inmates in Dataset" = "Percent") %>% 
  kbl(caption = "Percentages of Sentence Served") %>% 
  kable_minimal()
Percentages of Sentence Served
Percentage Served Number of Inmates (Observations) % of Inmates in Dataset
85% or more 5413 42.93 %
Less than 85% 2283 18.11 %
Served less than a year 3098 24.57 %
Served more than 25 years 269 2.13 %
NA 1546 12.26 %
#for those serving less than 85%, shows what perc they're actually serving
# me_analysis %>%
#   filter(servedperc == "Less than 85%") %>% 
#   mutate(servedpercent =  case_when(
#      SENTLGTH == "(1) 1-1.9 years" ~ exact_time_served/1, 
#      SENTLGTH == "(2) 2-4.9 years" ~ exact_time_served/2, 
#      SENTLGTH == "(3) 5-9.9 years" ~ exact_time_served/5, 
#      SENTLGTH == "(4) 10-24.9 years" ~ exact_time_served/10,
#     SENTLGTH == "(5) >=25 years" ~ exact_time_served/25,
#    )) %>% 
#   count(servedpercent) 

Missing Values

Some of the NA categories may be due missing RELEASEYR values. As we can see in the graph below, this may be due to the fact that most inmates are still in custody and haven’t been released yet.

#created a minimum sentence length, and then the earliest projected release yr and the latest projected release yr

me_analysis3 <- me_analysis %>%
  filter(is.na(RELEASEYR)) %>%
  mutate(exact_maxsentlgth = case_when(
           SENTLGTH == "(0) < 1 year" ~ 1,
           SENTLGTH == "(1) 1-1.9 years" ~ 1.9,
           SENTLGTH == "(2) 2-4.9 years" ~ 4.9,
           SENTLGTH == "(3) 5-9.9 years" ~ 9.9,
           SENTLGTH == "(4) 10-24.9 years" ~ 24.9),
         min_sentlgth = case_when(
           SENTLGTH == "(1) 1-1.9 years" ~ 1, #365 * 1
           SENTLGTH == "(2) 2-4.9 years" ~ 2, #365 * 2
           SENTLGTH == "(3) 5-9.9 years" ~ 5, #365 * 5
           SENTLGTH == "(4) 10-24.9 years" ~ 10, #365 * 10
           SENTLGTH == "(5) >=25 years" ~ 25,  #365*25, murder to be exact
         ),
         min_sentlgth = case_when(
           SENTLGTH == "(6) Life, LWOP, Life plus additional years, Death" ~ "NA - Life",
           TRUE ~ as.character(min_sentlgth)
         ),
         eproj_releaseyr = case_when(
           min_sentlgth == "NA - Life" ~ NA_real_,
           TRUE ~ ADMITYR + as.numeric(min_sentlgth)
         ),
         lproj_releaseyr = case_when(
           min_sentlgth == "NA - Life" ~ NA_real_,
           TRUE ~ floor(ADMITYR + as.numeric(exact_maxsentlgth))
         )) %>% 
  select("ADMITYR", "SENTLGTH", "eproj_releaseyr", "lproj_releaseyr") 

me_analysis3 %>%
  ggplot(aes(x = lproj_releaseyr)) +
  geom_bar() +
  geom_vline(xintercept = 2020, color = "blue") + labs(title = "Distribution of Projected Release Years", subtitle = "(For inmates with a `RELEASEYR` of `NA`)", x ="Projected Release Year", y = "Count / Frequency")

Only 4.78% of inmates in the data set have a projected release year before or in 2020. 78.65% of inmates in this data set have a projected release year after 2020 and the projected release year for 16.57% of inmates in the data set is unknown

me_analysis3 %>%
  count(lproj_releaseyr) %>% 
  mutate(Percent = paste(round((n/1726)*100,digits = 2),seperate = "%")) %>% 
  rename("Latest Projected Release Year" = "lproj_releaseyr",
         "Number of Inmates (Observations)" = "n",
         "% of Total" = "Percent") %>% 
  kbl(caption = "Percentages of Projected Release Years") %>% 
  kable_minimal() %>% 
  scroll_box(width = "100%", height = "500px")
Percentages of Projected Release Years
Latest Projected Release Year Number of Inmates (Observations) % of Total
1991 1 0.06 %
1992 1 0.06 %
1998 1 0.06 %
2001 1 0.06 %
2003 1 0.06 %
2005 1 0.06 %
2007 2 0.12 %
2008 2 0.12 %
2009 1 0.06 %
2012 2 0.12 %
2013 3 0.17 %
2014 2 0.12 %
2016 5 0.29 %
2017 7 0.41 %
2018 7 0.41 %
2019 6 0.35 %
2020 40 2.32 %
2021 250 14.48 %
2022 117 6.78 %
2023 260 15.06 %
2024 235 13.62 %
2025 28 1.62 %
2026 60 3.48 %
2027 74 4.29 %
2028 59 3.42 %
2029 61 3.53 %
2030 1 0.06 %
2031 1 0.06 %
2032 3 0.17 %
2033 9 0.52 %
2034 12 0.7 %
2035 14 0.81 %
2036 15 0.87 %
2037 19 1.1 %
2038 14 0.81 %
2039 25 1.45 %
2040 13 0.75 %
2041 27 1.56 %
2042 34 1.97 %
2043 19 1.1 %
2044 7 0.41 %
NA 286 16.57 %

What’s the maximum percentage of a sentence that can be reduced through good time credits?

Prisoners can be released at their maximum sentence lengths or earlier due to “good time” credit deductions (earned through good conduct and program participation). Prisoners convicted of murder, and any crime listed under sexual assaults (not limited to these two!) are eligible for only five days of credit per month for good conduct and program participation. Besides that prisoners can earn up to 4 days for good conduct and an extra 5 days per month for participating in programs (that they’re assigned to!). Here, I calculate the maximum percent of a sentence that can be reduced if prisoners earn all their good time credits as well as the averages of their sentence lengths (excluding good time credits) for each crime.

Note that there can be way more observations because we had to use the NCRP’s broad categories which we don’t know the criteria for (inmates convicted of other crimes are only limited to 5 days of good time credit, but they don’t fit in the dataset’s categories). However, for prisoners convicted of sexual assault or murder (about 10.9% of the data set), the release date with all good time credits earned is about ~83.5% of the maximum sentence given by a judge. For all other prisoners (89.1% of the data set), the release date with all good time credits earned is about ~70% of the maximum sentence given by a judge

#create dataframe for murder/rape offenses and calculate their good time credits and time served (subtracting those credits)

#Formula: (12 \* time served) \* (5 days per month) = good time credits available (in days)

df1 <- me_analysis %>%
  filter(OFFDETAIL == "(01) Murder (including non-negligent manslaughter)" | OFFDETAIL == "(03) Rape/sexual assault") %>%
  mutate(Good_time_credits = (12 * exact_time_served) * 5,
         gtc_exact_time_served = (( (365 * exact_time_served) - Good_time_credits ) / (365)))
         
#create dataframe that calculates average sent length minus good time credits by offense
avg_senlgthv <- df1 %>%
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  group_by(OFFDETAIL) %>%
  summarize(avg_sentlgth_w_gtc = round(mean(gtc_exact_time_served, na.rm = TRUE), digits = 1)) 


#create dataframe for all other offenses and calculate their good time credits and time served (subtracting those credits)

#Formula: (12 * time served) * (9 days per month) = good time credits available (in days)

df2 <- me_analysis %>%
  filter(OFFDETAIL != "(01) Murder (including non-negligent manslaughter)" & OFFDETAIL != "(03) Rape/sexual assault" | is.na(OFFDETAIL)) %>%
  mutate(Good_time_credits = (12 * exact_time_served) * 9, 
         gtc_exact_time_served = (( (365 * exact_time_served) - Good_time_credits ) / (365)))  

#create dataframe that calculates average sent length minus good time credits by offense
avg_senlgthnv <- df2 %>%
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  group_by(OFFDETAIL) %>%
  summarize(avg_sentlgth_w_gtc = round(mean(gtc_exact_time_served, na.rm = TRUE), digits = 1)) 


#combine the two dataframes above and calculate thier sentence reductions
gtc_table <- bind_rows(avg_senlgthv, avg_senlgthnv) %>% 
  full_join(avg_senlgth, by = c("OFFDETAIL" = "Offense Categorization")) %>% 
  mutate(perc_reduction = paste(round(((`Avg. Sent. Length` - avg_sentlgth_w_gtc)/`Avg. Sent. Length`), digits = 2) * 100, seperate = "%")) %>% 
  rename("Offense Categorization" = "OFFDETAIL",
         "Avg. Sentence Length w/ Good Time Credits" = "avg_sentlgth_w_gtc",
         "Avg. Sentence Length" = "Avg. Sent. Length",
         "Sentence Reduction %" = "perc_reduction")
 
#creating table
kbl(gtc_table, caption = "Sentence Length Comparison with Good Time Credits") %>%
  kable_minimal()
Sentence Length Comparison with Good Time Credits
Offense Categorization Avg. Sentence Length w/ Good Time Credits Avg. Sentence Length % of Prison Pop. Sentence Reduction %
  1. Murder (including non-negligent manslaughter)
12.4 14.8 3.08 % 16 %
  1. Rape/sexual assault
2.9 3.5 9.2 % 17 %
  1. Negligent manslaughter
3.6 5.2 1.72 % 31 %
  1. Robbery
2.0 2.9 6.56 % 31 %
  1. Aggravated or simple assault
1.1 1.5 16.93 % 27 %
  1. Other violent offenses
1.6 2.0 1.33 % 20 %
  1. Burglary
1.2 1.7 12.13 % 29 %
  1. Larceny
0.8 1.1 9.93 % 27 %
  1. Fraud
0.9 1.3 2.49 % 31 %
  1. Other property offenses
1.3 1.9 2.24 % 32 %
  1. Drugs (includes possession, distribution, trafficking, other)
1.0 1.4 22.33 % 29 %
  1. Public order
0.8 1.2 10.14 % 33 %
  1. Other/unspecified
2.7 3.9 0.79 % 31 %
NA 0.4 0.5 1.11 % 20 %

Wyoming and Vermont Parole Eligibility:

In Wyoming and Vermont, an inmate must have served his or her minimum term, less any good time (15 days a month in Wyoming) to be eligible for parole. LWOP or life sentences aren’t eligible for parole

Wyoming

Based on Wyoming’s parole model when we com- pare the time served with and without parole (given they’re released on the parole eligibility date), their sentence lengths are dramatically reduced, compared to the time served with good time credits (see Table 9). Although Wyoming’s good time credits are very generous, they don’t have a huge impact because it’s based on the time served until parole, which is much shorter. Compared to good time credits, being released on parole can serve as a better incentive for prisoners with the longest sentences and has the highest incarceration savings

me_analysis1 <- me_analysis %>% 
  filter(SENTLGTH != "(6) Life, LWOP, Life plus additional years, Death" | is.na(SENTLGTH)) %>% #filter out LWOP sentences
  mutate(PARELIG_YEAR = case_when( #parole eligibility year (minimum sentence defined based on smallest value in range of time served)
           TIMESRVD == "(0) < 1 year" ~ ADMITYR, #minimum term = 0.5
           TIMESRVD == "(1) 1-1.9 years" ~ floor(1 + ADMITYR), #365 * 1
           TIMESRVD == "(2) 2-4.9 years" ~ floor(2 + ADMITYR), #365 * 2
           TIMESRVD == "(3) 5-9.9 years" ~ floor(5 + ADMITYR), #365 * 5
           TIMESRVD == "(4) >=10 years" ~ floor(10 + ADMITYR)  #365*10
           ),
         time_until_parole_wy = case_when( #sentence length until parole eligibility year 
           PARELIG_YEAR == ADMITYR ~ 0.5,
           TRUE ~ PARELIG_YEAR - ADMITYR),
         Good_time_credits_wy = (12 * time_until_parole_wy) * 15,
         gtc_exact_time_served_wy = (( (365 * time_until_parole_wy) - Good_time_credits_wy ) / (365)), #time served w/ good time credits
         PARELIG_YEAR = PARELIG_YEAR - (Good_time_credits_wy/365)) #adjusting for any good time credit they earned 

#find the avg. time until parole for each offense and combine with avg. sentence length df for comparison
 avg_time_until_parole_wy <- me_analysis1 %>%
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  group_by(OFFDETAIL) %>%
  mutate(time_until_parole_gtc = PARELIG_YEAR - ADMITYR) %>%  #sentence leng. until parole w/ gtc
  summarize(avg_time_until_parole = round(mean(time_until_parole_gtc, na.rm = TRUE), digits = 1)) %>% 
  full_join(avg_senlgth, by = c("OFFDETAIL" = "Offense Categorization")) 


wyparole_table <- avg_time_until_parole_wy %>%  
  mutate(incarceration_savings_pp = round((`Avg. Sent. Length` - avg_time_until_parole) * (78732.15/365), digits = 2), #calculated the savings if inmates were released on parole eligibility year (avg. cost of incarceration per prisoner per day * sentence length not served)
         avg_perc_reduction = paste(round(((`Avg. Sent. Length` - avg_time_until_parole)/`Avg. Sent. Length`), digits = 2) * 100, seperate = "%")) %>% #calculated the avg. sent. reduction perc. for each offense
  rename("Offense Categorization" = "OFFDETAIL",
         "Avg. Sent. Length w/ Parole" = "avg_time_until_parole",
         "Average Sentence Reduction %" = "avg_perc_reduction",
         "Incarceration Savings Per Prisoner" = "incarceration_savings_pp")
 
#creating table
kbl(wyparole_table, caption = "Sentence Length Comparison with Parole in Wyoming") %>%
  kable_minimal()
Sentence Length Comparison with Parole in Wyoming
Offense Categorization Avg. Sent. Length w/ Parole Avg. Sent. Length % of Prison Pop. Incarceration Savings Per Prisoner Average Sentence Reduction %
  1. Murder (including non-negligent manslaughter)
3.3 14.8 3.08 % 2480.60 78 %
  1. Negligent manslaughter
1.7 5.2 1.72 % 754.97 67 %
  1. Rape/sexual assault
1.1 3.5 9.2 % 517.69 69 %
  1. Robbery
0.9 2.9 6.56 % 431.41 69 %
  1. Aggravated or simple assault
0.4 1.5 16.93 % 237.27 73 %
  1. Other violent offenses
0.5 2.0 1.33 % 323.56 75 %
  1. Burglary
0.4 1.7 12.13 % 280.42 76 %
  1. Larceny
0.1 1.1 9.93 % 215.70 91 %
  1. Fraud
0.2 1.3 2.49 % 237.27 85 %
  1. Other property offenses
0.5 1.9 2.24 % 301.99 74 %
  1. Drugs (includes possession, distribution, trafficking, other)
0.3 1.4 22.33 % 237.27 79 %
  1. Public order
0.1 1.2 10.14 % 237.27 92 %
  1. Other/unspecified
0.5 3.9 0.79 % 733.40 87 %
NA -0.1 0.5 1.11 % 129.42 120 %

Vermont

In Vermont, if an inmate doesn’t have a minimum sentence, then they’re eligible for parole after a year. They also wrote their good time bill in 2020 and it’s effective January 1st, 2021. Since this data is up until 2020, good time wasn’t taken into consideration for the parole eligibility date calculation.

As a result of the slightly different parole criteria (being eligible for parole after a year), sentence reductions aren’t as drastic for those with shorter sentences, which encompasses most of the prisoners in Maine from 1991-2020.

#same comments as Wyoming, but for vermont (excluding good time credits)
me_analysis2 <- me_analysis %>% 
  filter(SENTLGTH != "(6) Life, LWOP, Life plus additional years, Death" | is.na(SENTLGTH)) %>%
  mutate(PARELIG_YEAR_VT = case_when(
           TIMESRVD == "(1) 1-1.9 years" | TIMESRVD == "(0) < 1 year" ~ floor(1 + ADMITYR), #365 * 1
           TIMESRVD == "(2) 2-4.9 years" ~ floor(2 + ADMITYR), #365 * 2
           TIMESRVD == "(3) 5-9.9 years" ~ floor(5 + ADMITYR), #365 * 5
           TIMESRVD == "(4) >=10 years" ~ floor(10 + ADMITYR)  #365*10
           ),
         time_until_parole_vt = case_when(
           PARELIG_YEAR_VT == ADMITYR ~ 0.2,
           TRUE ~ PARELIG_YEAR_VT - ADMITYR))
         # sent_reduction_perc_vt = case_when(
         #    PARELIG_YEAR_VT == ADMITYR ~ 1.0, #0% reduction
         #    ADMITYR == RELEASEYR ~ 2.0, #INF! 
         #    RELEASEYR == PARELIG_YEAR_VT ~ 3.0, #100% reduction
         #    TRUE ~  round(((exact_time_served - time_until_parole_vt)/exact_time_served), digits = 2) * 100)) 

 avg_time_until_parole_vt <- me_analysis2 %>%
  distinct(ABT_INMATE_ID, .keep_all = TRUE) %>%
  group_by(OFFDETAIL) %>%  
  summarize(avg_time_until_parole = round(mean(time_until_parole_vt, na.rm = TRUE), digits = 1)) %>% 
  full_join(avg_senlgth, by = c("OFFDETAIL" = "Offense Categorization")) 


 
vtparole_table <- avg_time_until_parole_vt %>% 
  # group_by(OFFDETAIL) %>% 
  # summarise(avg_perc_reduction = round(mean(sent_reduction_perc_vt, na.rm = TRUE), digits = 2)) %>% 
  # full_join(avg_time_until_parole_vt, by = "OFFDETAIL") %>% 
  mutate(incarceration_savings_pp = round((`Avg. Sent. Length` - avg_time_until_parole) * (78732.15/365), digits = 2),
         avg_perc_reduction = paste(round(((`Avg. Sent. Length` - avg_time_until_parole)/`Avg. Sent. Length`), digits = 2) * 100, seperate = "%")) %>% #calculated the avg. sent. reduction perc. for each offense
  rename("Offense Categorization" = "OFFDETAIL",
         "Avg. Sent. Length w/ Parole" = "avg_time_until_parole",
         "Average Sentence Reduction %" = "avg_perc_reduction",
         "Incarceration Savings Per Prisoner" = "incarceration_savings_pp")
 
 

#creating table
kbl(vtparole_table, caption = "Sentence Length Comparison with Parole in Vermont") %>%
  kable_minimal()
Sentence Length Comparison with Parole in Vermont
Offense Categorization Avg. Sent. Length w/ Parole Avg. Sent. Length % of Prison Pop. Incarceration Savings Per Prisoner Average Sentence Reduction %
  1. Murder (including non-negligent manslaughter)
6.7 14.8 3.08 % 1747.21 55 %
  1. Negligent manslaughter
3.6 5.2 1.72 % 345.13 31 %
  1. Rape/sexual assault
2.5 3.5 9.2 % 215.70 29 %
  1. Robbery
2.1 2.9 6.56 % 172.56 28 %
  1. Aggravated or simple assault
1.3 1.5 16.93 % 43.14 13 %
  1. Other violent offenses
1.8 2.0 1.33 % 43.14 10 %
  1. Burglary
1.4 1.7 12.13 % 64.71 18 %
  1. Larceny
1.1 1.1 9.93 % 0.00 0 %
  1. Fraud
1.2 1.3 2.49 % 21.57 8 %
  1. Other property offenses
1.5 1.9 2.24 % 86.28 21 %
  1. Drugs (includes possession, distribution, trafficking, other)
1.3 1.4 22.33 % 21.57 7 %
  1. Public order
1.2 1.2 10.14 % 0.00 0 %
  1. Other/unspecified
2.0 3.9 0.79 % 409.84 49 %
NA 1.0 0.5 1.11 % -107.85 -100 %

If you don’t want to keep scrolling up and down, below is a joint table of the sentence lengths and their reductions with Maine’s good time credit system, and Wyoming’s and Vermont’s parole system.

#creating joint table of the 3 tables above for thesis poster

gtc_table %>% 
  select(1,2,5) %>% 
  rename("(ME) Avg. Sent. Length w/ Good Time Credits" = "Avg. Sentence Length w/ Good Time Credits",
         "(ME) Sent. Reduction % w/ Good Time Credits" = "Sentence Reduction %") %>% 
  full_join(wyparole_table, by = "Offense Categorization") %>%
  # select(1,2,3,6) %>% 
   rename("(WY) Avg. Sent. Reduction %" = "Average Sentence Reduction %",
         "(WY) Avg. Sent. Length w/ Parole" = "Avg. Sent. Length w/ Parole",
         "(WY) Incarceration Savings Per Prisoner" = "Incarceration Savings Per Prisoner") %>% 
  full_join(vtparole_table, by = "Offense Categorization") %>% 
  select(1:9,12:13) %>%
  rename("(VT) Avg. Sent. Reduction %" = "Average Sentence Reduction %",
         "(VT) Avg. Sent. Length w/ Parole" = "Avg. Sent. Length w/ Parole",
         "(VT) Incarceration Savings Per Prisoner" = "Incarceration Savings Per Prisoner",
         "Avg. Sent. Length" = "Avg. Sent. Length.x",
         "% of Prison Pop." = "% of Prison Pop..x") %>% 
  select(1,6,5,2,4,9,3,8,11,7,10) %>% 
  kbl(caption = "Sentence Length Comparisons") %>% 
  kable_minimal()
Sentence Length Comparisons
Offense Categorization % of Prison Pop. Avg. Sent. Length (ME) Avg. Sent. Length w/ Good Time Credits (WY) Avg. Sent. Length w/ Parole (VT) Avg. Sent. Length w/ Parole (ME) Sent. Reduction % w/ Good Time Credits (WY) Avg. Sent. Reduction % (VT) Avg. Sent. Reduction % (WY) Incarceration Savings Per Prisoner (VT) Incarceration Savings Per Prisoner
  1. Murder (including non-negligent manslaughter)
3.08 % 14.8 12.4 3.3 6.7 16 % 78 % 55 % 2480.60 1747.21
  1. Rape/sexual assault
9.2 % 3.5 2.9 1.1 2.5 17 % 69 % 29 % 517.69 215.70
  1. Negligent manslaughter
1.72 % 5.2 3.6 1.7 3.6 31 % 67 % 31 % 754.97 345.13
  1. Robbery
6.56 % 2.9 2.0 0.9 2.1 31 % 69 % 28 % 431.41 172.56
  1. Aggravated or simple assault
16.93 % 1.5 1.1 0.4 1.3 27 % 73 % 13 % 237.27 43.14
  1. Other violent offenses
1.33 % 2.0 1.6 0.5 1.8 20 % 75 % 10 % 323.56 43.14
  1. Burglary
12.13 % 1.7 1.2 0.4 1.4 29 % 76 % 18 % 280.42 64.71
  1. Larceny
9.93 % 1.1 0.8 0.1 1.1 27 % 91 % 0 % 215.70 0.00
  1. Fraud
2.49 % 1.3 0.9 0.2 1.2 31 % 85 % 8 % 237.27 21.57
  1. Other property offenses
2.24 % 1.9 1.3 0.5 1.5 32 % 74 % 21 % 301.99 86.28
  1. Drugs (includes possession, distribution, trafficking, other)
22.33 % 1.4 1.0 0.3 1.3 29 % 79 % 7 % 237.27 21.57
  1. Public order
10.14 % 1.2 0.8 0.1 1.2 33 % 92 % 0 % 237.27 0.00
  1. Other/unspecified
0.79 % 3.9 2.7 0.5 2.0 31 % 87 % 49 % 733.40 409.84
NA 1.11 % 0.5 0.4 -0.1 1.0 20 % 120 % -100 % 129.42 -107.85

Parole Release Predictions

Since we don’t have access to LSI Risk scores, we can’t predict who would be released on parole. Instead, I use the percentages of releases to parole from the previous years to predict how many people would be released on parole and the savings for Maine after 2015 (we only have total expenditure data for 2016 and above). I use the percentages of releases to probation in Maine (since parole release data before they abolished it is unavailable), and releases to parole in Wyoming and Vermont, all of which are then compared to each other. Presented below is the formula I use to calculate net savings in Maine and the summary statistics used for the formula:

Net incarceration savings \(=\) (projected parole non-returnees \(\times\) cost per prisoner in Maine) \(-\) (projected parole releases \(\times\) cost of parole per prisoner)

Model 1: Based on Maine Probation Releases

  • Average Cost of Parole: $229.1
  • Average Probation Grant Rate: 50.87%
  • Average Parole Success Rate: 87.38%

If Maine implements parole and inmates are released to parole at the same rate they’re released to probation in Maine, then Maine will have a 25% average increase in their total budget and can save at least $40 million.

parolerelease_me <- me_analysis %>% 
  filter(SENTLGTH != "(6) Life, LWOP, Life plus additional years, Death" | is.na(SENTLGTH)) %>%  #filter out LWOP
  filter(RELEASEYR >= 2016) %>% #2016 and above 
  count(RELEASEYR) %>% #to get the amount of prisoners per release yr after 2016
  mutate(parole_entries_me = case_when( #projected parole entries based on probation grant each yr
    RELEASEYR == 2016 ~ floor(n * .52728),
    RELEASEYR == 2017 ~ floor(n * .514),
    RELEASEYR == 2018 ~ floor(n * .5063),
    RELEASEYR == 2019 ~ floor(n * .5003),
    RELEASEYR == 2020 ~ floor(n * .4956)
  ), 
  parole_costs = parole_entries_me *250, #total parole costs each yr (parolees * cost of parole per prisoner)
  parole_nonreturnees_me = case_when( #projected parole nonreturnees based on probation success each yr
    RELEASEYR == 2016 ~ floor(parole_entries_me * .857),
    RELEASEYR == 2017 ~ floor(parole_entries_me * .822),
    RELEASEYR == 2018 ~ floor(parole_entries_me * .89),
    RELEASEYR == 2019 ~ floor(parole_entries_me * .897),
    RELEASEYR == 2020 ~ floor(parole_entries_me * .903)
  ), 
  reduced_incarceration_costs = case_when( #total reduced incarceration costs each yr (parole nonreturnees * cost of incarcaration per prisoner)
    RELEASEYR == 2016 ~ floor(parole_nonreturnees_me * 83874.5),
    RELEASEYR == 2017 ~ floor(parole_nonreturnees_me * 78732.15),
    RELEASEYR == 2018 ~ floor(parole_nonreturnees_me * 79306.1),
    RELEASEYR == 2019 ~ floor(parole_nonreturnees_me * 85417.9),
    RELEASEYR == 2020 ~ floor(parole_nonreturnees_me * 106548)
  ),
  net_incarceration_savings = reduced_incarceration_costs - parole_costs, #benefit - costs = net benefit
  Maine_prison_budget_proj = case_when( #maine's projected budget if they implement parole
    RELEASEYR == 2016 ~ floor(185865999 + net_incarceration_savings),
    RELEASEYR == 2017 ~ floor(186596104 + net_incarceration_savings),
    RELEASEYR == 2018 ~ floor(193824055 + net_incarceration_savings),
    RELEASEYR == 2019 ~ floor(194411181 + net_incarceration_savings),
    RELEASEYR == 2020 ~ floor(202761410 + net_incarceration_savings)
  ),
  Maine_prison_budget_perc = case_when( #maine's projected budget percent change if they implement parole
    RELEASEYR == 2016 ~ floor(((Maine_prison_budget_proj - 185865999)/185865999) * 100),
    RELEASEYR == 2017 ~ floor(((Maine_prison_budget_proj - 186596104)/186596104) * 100),
    RELEASEYR == 2018 ~ floor(((Maine_prison_budget_proj - 193824055)/193824055) * 100),
    RELEASEYR == 2019 ~ floor(((Maine_prison_budget_proj - 194411181)/194411181) * 100),
    RELEASEYR == 2020 ~ floor(((Maine_prison_budget_proj - 202761410)/202761410) * 100)
    ))
  
parolerelease_me_tidy <- parolerelease_me %>% #from wide to tidy format for graphing purposes
  pivot_longer(cols = n:Maine_prison_budget_proj, names_to = "Statistic", values_to = "Value")

parolerelease_me_tidy %>% 
  filter(Statistic == "net_incarceration_savings" | Statistic == "reduced_incarceration_costs"| Statistic == "parole_costs") %>% 
  ggplot(aes(x = RELEASEYR, y = Value, fill = Statistic)) +
   geom_col(position = position_dodge()) + ylim(0, 55500000) + #goes past 4e+07 
  geom_text(aes(label = Value), vjust = -0.5, size = 2, position = position_dodge(0.9)) +
  scale_fill_discrete(labels=c('Incarceration Savings (Net)', 'Parole Costs', 'Incarceration Costs (Reduced)')) +
  labs(title = "Net Incarceration Savings (2016-2020)", subtitle = "(If Parolees are Released Based on Probation Grant Rates in Maine)", x ="Release Year", y = "Costs (in Dollars)")

Model 2: Based on Wyoming Parole Releases

  • Average Cost of Parole: $1,918.45 (excludes 2019)
  • Average Probation Grant Rate: 67.02%
  • Average Parole Success Rate: 54.18%

If Maine implements parole and inmates are released to parole at the same rate they’re released to parole in Wyoming, then Maine will have a 19.5% increase in their total budget and can save at least $35 million.

parolerelease_wy <- me_analysis %>% 
  filter(SENTLGTH != "(6) Life, LWOP, Life plus additional years, Death" | is.na(SENTLGTH)) %>%  #filter out LWOP
  filter(RELEASEYR >= 2016) %>% #2016 and above 
  count(RELEASEYR) %>% #to get the amount of prisoners per release yr after 2016
  mutate(parole_entries_wy = case_when( #projected parole entries based on parole grant each yr
    RELEASEYR == 2016 ~ floor(n * .6637),
    RELEASEYR == 2017 ~ floor(n * .6801),
    RELEASEYR == 2018 ~ floor(n * .6582),
    RELEASEYR == 2019 ~ floor(n * .6712),
    RELEASEYR == 2020 ~ floor(n * .6773)
  ), 
  parole_costs = case_when( #total parole costs each yr (parolees * cost of parole per prisoner), excludes 2019
    RELEASEYR == 2016 ~ floor(parole_entries_wy * 2179.87),
    RELEASEYR == 2017 ~ floor(parole_entries_wy * 1906.66),
    RELEASEYR == 2018 ~ floor(parole_entries_wy * 1766.26),
    RELEASEYR == 2020 ~ floor(parole_entries_wy * 1821)
  ), 
  parole_nonreturnees_wy = case_when( #projected parole nonreturnees based on parole success each yr
    RELEASEYR == 2016 ~ floor(parole_entries_wy * .603),
    RELEASEYR == 2017 ~ floor(parole_entries_wy * .574),
    RELEASEYR == 2018 ~ floor(parole_entries_wy * .603),
    RELEASEYR == 2019 ~ floor(parole_entries_wy * .488),
    RELEASEYR == 2020 ~ floor(parole_entries_wy * .441)
  ), 
  reduced_incarceration_costs = case_when( #total reduced incarceration costs each yr (parole nonreturnees * cost of incarcaration per prisoner)
    RELEASEYR == 2016 ~ floor(parole_nonreturnees_wy * 83874.5),
    RELEASEYR == 2017 ~ floor(parole_nonreturnees_wy * 78732.15),
    RELEASEYR == 2018 ~ floor(parole_nonreturnees_wy * 79306.1),
    RELEASEYR == 2019 ~ floor(parole_nonreturnees_wy * 85417.9),
    RELEASEYR == 2020 ~ floor(parole_nonreturnees_wy * 106548)
  ), 
  net_incarceration_savings = reduced_incarceration_costs - parole_costs, #benefit - costs = net benefit
  Maine_prison_budget_proj = case_when( #maine's projected budget if they implement parole
    RELEASEYR == 2016 ~ floor(185865999 + net_incarceration_savings),
    RELEASEYR == 2017 ~ floor(186596104 + net_incarceration_savings),
    RELEASEYR == 2018 ~ floor(193824055 + net_incarceration_savings),
    RELEASEYR == 2019 ~ floor(194411181 + net_incarceration_savings),
    RELEASEYR == 2020 ~ floor(202761410 + net_incarceration_savings)
  ),
  Maine_prison_budget_perc = case_when( #maine's projected budget percent change if they implement parole
    RELEASEYR == 2016 ~ floor(((Maine_prison_budget_proj - 185865999)/185865999) * 100),
    RELEASEYR == 2017 ~ floor(((Maine_prison_budget_proj - 186596104)/186596104) * 100),
    RELEASEYR == 2018 ~ floor(((Maine_prison_budget_proj - 193824055)/193824055) * 100),
    RELEASEYR == 2019 ~ floor(((Maine_prison_budget_proj - 194411181)/194411181) * 100),
    RELEASEYR == 2020 ~ floor(((Maine_prison_budget_proj - 202761410)/202761410) * 100)
    ))

parolerelease_wy_tidy <- parolerelease_wy %>% #from wide to tidy format for graphing purposes
  pivot_longer(cols = n:Maine_prison_budget_proj, names_to = "Statistic", values_to = "Value")

parolerelease_wy_tidy %>%
  filter(Statistic == "net_incarceration_savings" | Statistic == "reduced_incarceration_costs"| Statistic == "parole_costs") %>% 
  ggplot(aes(x = RELEASEYR, y = Value, fill = Statistic)) +
   geom_col(position = position_dodge()) + ylim(0, 55500000) + #goes past 4e+07 
  geom_text(aes(label = Value), vjust = -0.5, size = 2, position = position_dodge(0.9)) +
  scale_fill_discrete(labels=c('Net Incarceration Savings','Parole Costs', 'Reduced Incarceration Costs')) +
  labs(title = "Net Incarceration Savings (2016-2020)", subtitle = "(If Parolees are Released Based on Parole Grant Rates in Wyoming)", x ="Release Year", y = "Costs (in Dollars)")

Model 3: Based on Vermont Parole Releases

  • Average Cost of Parole: $401.2
  • Average Probation Grant Rate: 24.62%
  • Average Parole Success Rate: 56.9% (excludes 2019 and 2020)

If Maine implements parole and inmates are released to parole at the same rate they’re released to parole in Vermont, then Maine will have a 7% increase in their total budget and can save at least $10 million.

#recidivism rate: (2016) 43.8% (2017) 42.9% (2018) 42.6%

parolerelease_vt <- me_analysis %>% 
  filter(SENTLGTH != "(6) Life, LWOP, Life plus additional years, Death" | is.na(SENTLGTH)) %>%
  #filter out LWOP
  filter(RELEASEYR >= 2016) %>% #2016 and above 
  count(RELEASEYR) %>% #to get the amount of prisoners per release yr after 2016
  mutate(parole_entries_vt = case_when( #projected parole entries based on parole grant each yr
    RELEASEYR == 2016 ~ floor(n * .3462),
    RELEASEYR == 2017 ~ floor(n * .2228),
    RELEASEYR == 2018 ~ floor(n * .1616),
    RELEASEYR == 2019 ~ floor(n * .1619),
    RELEASEYR == 2020 ~ floor(n * .3384)
  ),  
  parole_nonreturnees_vt = case_when( #projected parole nonreturnees based on parole success each yr, don't have recidivism rates after 2018
    RELEASEYR == 2016 ~ floor(parole_entries_vt * .562),
    RELEASEYR == 2017 ~ floor(parole_entries_vt * .571),
    RELEASEYR == 2018 ~ floor(parole_entries_vt * .574)
  ),
  reduced_incarceration_costs = case_when( #total reduced incarceration costs each yr (parole nonreturnees * cost of incarcaration per prisoner)
    RELEASEYR == 2016 ~ floor(parole_nonreturnees_vt * 83874.5),
    RELEASEYR == 2017 ~ floor(parole_nonreturnees_vt * 78732.15),
    RELEASEYR == 2018 ~ floor(parole_nonreturnees_vt * 79306.1),
    RELEASEYR == 2019 ~ floor(parole_nonreturnees_vt * 85417.9),
    RELEASEYR == 2020 ~ floor(parole_nonreturnees_vt * 106548)
  ), 
  parole_costs = case_when( #total parole costs each yr (parolees * cost of parole per prisoner)
    RELEASEYR == 2016 ~ floor(parole_entries_vt * 327.134),
    RELEASEYR == 2017 ~ floor(parole_entries_vt * 419.861),
    RELEASEYR == 2018 ~ floor(parole_entries_vt * 390.898),
    RELEASEYR == 2019 ~ floor(parole_entries_vt * 437.468),
    RELEASEYR == 2020 ~ floor(parole_entries_vt * 430.615)
  ), 
  net_incarceration_savings = reduced_incarceration_costs - parole_costs, #benefit - costs = net benefit 
  Maine_prison_budget_proj = case_when( #maine's projected budget if they implement parole
    RELEASEYR == 2016 ~ floor(185865999 + net_incarceration_savings),
    RELEASEYR == 2017 ~ floor(186596104 + net_incarceration_savings),
    RELEASEYR == 2018 ~ floor(193824055 + net_incarceration_savings),
    RELEASEYR == 2019 ~ floor(194411181 + net_incarceration_savings),
    RELEASEYR == 2020 ~ floor(202761410 + net_incarceration_savings)
  ),
  Maine_prison_budget_perc = case_when( #maine's projected budget percent change if they implement parole
    RELEASEYR == 2016 ~ floor(((Maine_prison_budget_proj - 185865999)/185865999) * 100),
    RELEASEYR == 2017 ~ floor(((Maine_prison_budget_proj - 186596104)/186596104) * 100),
    RELEASEYR == 2018 ~ floor(((Maine_prison_budget_proj - 193824055)/193824055) * 100),
    RELEASEYR == 2019 ~ floor(((Maine_prison_budget_proj - 194411181)/194411181) * 100),
    RELEASEYR == 2020 ~ floor(((Maine_prison_budget_proj - 202761410)/202761410) * 100)
    ))

parolerelease_vt_tidy <- parolerelease_vt %>% #from wide to tidy format for graphing purposes
  pivot_longer(cols = n:Maine_prison_budget_proj, names_to = "Statistic", values_to = "Value")

parolerelease_vt_tidy %>%
  filter(Statistic == "net_incarceration_savings" | Statistic == "reduced_incarceration_costs"| Statistic == "parole_costs") %>% 
  ggplot(aes(x = RELEASEYR, y = Value, fill = Statistic)) +
   geom_col(position = position_dodge()) + ylim(0, 55500000) +  
  geom_text(aes(label = Value), vjust = -0.5, size = 2, position = position_dodge(0.9)) +
  scale_fill_discrete(labels=c('Net Incarceration Savings','Parole Costs', 'Reduced Incarceration Costs')) +
  labs(title = "Net Incarceration Savings (2016-2020)", subtitle = "(If Parolees are Released Based on Parole Grant Rates in Vermont)", x ="Release Year", y = "Costs (in Dollars)")