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.
#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")
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
| 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)
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")
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")
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()
| Time Served | Number of Inmates (Observations) | % of Inmates in Dataset |
|---|---|---|
|
3735 | 38.53 % |
|
2506 | 25.85 % |
|
1596 | 16.46 % |
|
383 | 3.95 % |
|
138 | 1.42 % |
| NA | 1336 | 13.78 % |
#creating an exact time served variable
me_analysis <- me_analysis %>%
mutate(exact_time_served = RELEASEYR - ADMITYR)
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()
| Offense Categorization | Avg. Sent. Length | % of Prison Pop. |
|---|---|---|
|
14.8 | 3.08 % |
|
5.2 | 1.72 % |
|
3.5 | 9.2 % |
|
2.9 | 6.56 % |
|
1.5 | 16.93 % |
|
2.0 | 1.33 % |
|
1.7 | 12.13 % |
|
1.1 | 9.93 % |
|
1.3 | 2.49 % |
|
1.9 | 2.24 % |
|
1.4 | 22.33 % |
|
1.2 | 10.14 % |
|
3.9 | 0.79 % |
| NA | 0.5 | 1.11 % |
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()
| 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 % |
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()
| 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)
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")
| 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 % |
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()
| Offense Categorization | Avg. Sentence Length w/ Good Time Credits | Avg. Sentence Length | % of Prison Pop. | Sentence Reduction % |
|---|---|---|---|---|
|
12.4 | 14.8 | 3.08 % | 16 % |
|
2.9 | 3.5 | 9.2 % | 17 % |
|
3.6 | 5.2 | 1.72 % | 31 % |
|
2.0 | 2.9 | 6.56 % | 31 % |
|
1.1 | 1.5 | 16.93 % | 27 % |
|
1.6 | 2.0 | 1.33 % | 20 % |
|
1.2 | 1.7 | 12.13 % | 29 % |
|
0.8 | 1.1 | 9.93 % | 27 % |
|
0.9 | 1.3 | 2.49 % | 31 % |
|
1.3 | 1.9 | 2.24 % | 32 % |
|
1.0 | 1.4 | 22.33 % | 29 % |
|
0.8 | 1.2 | 10.14 % | 33 % |
|
2.7 | 3.9 | 0.79 % | 31 % |
| NA | 0.4 | 0.5 | 1.11 % | 20 % |
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
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()
| Offense Categorization | Avg. Sent. Length w/ Parole | Avg. Sent. Length | % of Prison Pop. | Incarceration Savings Per Prisoner | Average Sentence Reduction % |
|---|---|---|---|---|---|
|
3.3 | 14.8 | 3.08 % | 2480.60 | 78 % |
|
1.7 | 5.2 | 1.72 % | 754.97 | 67 % |
|
1.1 | 3.5 | 9.2 % | 517.69 | 69 % |
|
0.9 | 2.9 | 6.56 % | 431.41 | 69 % |
|
0.4 | 1.5 | 16.93 % | 237.27 | 73 % |
|
0.5 | 2.0 | 1.33 % | 323.56 | 75 % |
|
0.4 | 1.7 | 12.13 % | 280.42 | 76 % |
|
0.1 | 1.1 | 9.93 % | 215.70 | 91 % |
|
0.2 | 1.3 | 2.49 % | 237.27 | 85 % |
|
0.5 | 1.9 | 2.24 % | 301.99 | 74 % |
|
0.3 | 1.4 | 22.33 % | 237.27 | 79 % |
|
0.1 | 1.2 | 10.14 % | 237.27 | 92 % |
|
0.5 | 3.9 | 0.79 % | 733.40 | 87 % |
| NA | -0.1 | 0.5 | 1.11 % | 129.42 | 120 % |
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()
| Offense Categorization | Avg. Sent. Length w/ Parole | Avg. Sent. Length | % of Prison Pop. | Incarceration Savings Per Prisoner | Average Sentence Reduction % |
|---|---|---|---|---|---|
|
6.7 | 14.8 | 3.08 % | 1747.21 | 55 % |
|
3.6 | 5.2 | 1.72 % | 345.13 | 31 % |
|
2.5 | 3.5 | 9.2 % | 215.70 | 29 % |
|
2.1 | 2.9 | 6.56 % | 172.56 | 28 % |
|
1.3 | 1.5 | 16.93 % | 43.14 | 13 % |
|
1.8 | 2.0 | 1.33 % | 43.14 | 10 % |
|
1.4 | 1.7 | 12.13 % | 64.71 | 18 % |
|
1.1 | 1.1 | 9.93 % | 0.00 | 0 % |
|
1.2 | 1.3 | 2.49 % | 21.57 | 8 % |
|
1.5 | 1.9 | 2.24 % | 86.28 | 21 % |
|
1.3 | 1.4 | 22.33 % | 21.57 | 7 % |
|
1.2 | 1.2 | 10.14 % | 0.00 | 0 % |
|
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()
| 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 |
|---|---|---|---|---|---|---|---|---|---|---|
|
3.08 % | 14.8 | 12.4 | 3.3 | 6.7 | 16 % | 78 % | 55 % | 2480.60 | 1747.21 |
|
9.2 % | 3.5 | 2.9 | 1.1 | 2.5 | 17 % | 69 % | 29 % | 517.69 | 215.70 |
|
1.72 % | 5.2 | 3.6 | 1.7 | 3.6 | 31 % | 67 % | 31 % | 754.97 | 345.13 |
|
6.56 % | 2.9 | 2.0 | 0.9 | 2.1 | 31 % | 69 % | 28 % | 431.41 | 172.56 |
|
16.93 % | 1.5 | 1.1 | 0.4 | 1.3 | 27 % | 73 % | 13 % | 237.27 | 43.14 |
|
1.33 % | 2.0 | 1.6 | 0.5 | 1.8 | 20 % | 75 % | 10 % | 323.56 | 43.14 |
|
12.13 % | 1.7 | 1.2 | 0.4 | 1.4 | 29 % | 76 % | 18 % | 280.42 | 64.71 |
|
9.93 % | 1.1 | 0.8 | 0.1 | 1.1 | 27 % | 91 % | 0 % | 215.70 | 0.00 |
|
2.49 % | 1.3 | 0.9 | 0.2 | 1.2 | 31 % | 85 % | 8 % | 237.27 | 21.57 |
|
2.24 % | 1.9 | 1.3 | 0.5 | 1.5 | 32 % | 74 % | 21 % | 301.99 | 86.28 |
|
22.33 % | 1.4 | 1.0 | 0.3 | 1.3 | 29 % | 79 % | 7 % | 237.27 | 21.57 |
|
10.14 % | 1.2 | 0.8 | 0.1 | 1.2 | 33 % | 92 % | 0 % | 237.27 | 0.00 |
|
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 |
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)
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)")
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)")
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)")