This data analysis is part of my senior thesis, presented to the Department of Mathematics at Bates College, in partial fulfillment of the requirements for the Degree of Bachelor of Arts. Presented below is my 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)
#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 dataframe. The first and second dataframes that they print are the
factor and numeric variables in our dataframe. It shows the amount of
missing, and unique (or distinct) values as well as the highest values
for each factored variable. Based on this, I order some of the factored
variables. 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(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 observations of prisoners in the
ME_term_records. Here I create a histogram of the
distribution of admittance in Maine, to get an estimate of reoffenders
in Maine. About 41% of all inmates 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. Although it can happen more than once, 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")
These are the percentages of the distributions of time served. More than 50% of the data set are serving 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)
This is the average sentence length for each offense and their percentage of the data set population.
#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 % |
I calculate what percentage of inmates were released before, within, or after your 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), only 0.86% aren’t released earlier or at the release date they’re supposed to (maximum sentence length). Thus it seems like prison sentence length are pretty certain 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 % |
Below I 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 ht einmates 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.
#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 dataset have a projected release year before or in 2020. 78.65% of inmates in this dataset have a projected release year after 2020 and the projected release year for 16.57% of inmates in the dataset are 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") %>%
kbl(caption = "Percentages of Projected Release Years") %>%
kable_minimal()
| Latest Projected Release Year | Number of Inmates (Observations) | Percent |
|---|---|---|
| 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 you 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 (keep in mind 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 our 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 our 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) and special good time earned (only in Wyoming, but won’t consider for below) to be eligible. LWOP or life sentences aren’t eligible for parole.
Based on Wyoming’s parole model when we compare the time served with and without parole (given they’re released on the parole eligibility date), there sentence lengths are dramatically reduced, compared to the time served with good time credits. 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 If those with the longest sentences no longer pose a threat to public safety and are released on parole, they can save Maine the most.
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 after a year. They also wrote their good time bill in 2020 and it’s effective 01/01/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 ad 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 grant releases from the previous years to predict how many people would be released on parole and the savings for Maine after 2015 (we have total expenditure data for 2016 and above). I use the grant 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)
Probation Grant Rates in Maine
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, then Maine will have an 25% average increase in their total budget.
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)")
Parole Grant Rates in Wyoming
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.
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)")
Parole Grant Rates in Vermont
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.
#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('Incarceration Savings (Net)', 'Incarceration Costs (Reduced)', 'Parole 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)")