library(tidyverse)library(DT) # for interactive html tables on websitelibrary(flextable) # best for exporting to word or PDF files.knitr::opts_chunk$set(warning =FALSE, message =FALSE)set_flextable_defaults(theme_fun = theme_vanilla, padding =2,line_spacing =1,big.mark =",", )options(DT.options =list())FitFlextableToPage <-function(ft, pgwidth =6){ ft_out <- ft %>%autofit() ft_out <-width(ft_out, width =dim(ft_out)$widths*pgwidth /(flextable_dim(ft_out)$widths))return(ft_out)}
Code
# all pins for 2022 in incorporated AND unincorporated areasptax_pins <-read_csv("../Output/Dont_Upload/0_joined_PIN_data_2022.csv") %>%mutate(class =as.numeric(class)) %>%# Allows for joining laterselect(-c(propclass_1dig:av.y))# Workaround for identifying more project IDs. # Used Appeal ID to create unique identifier to group PINs.bor <-read_csv("../Output/borappeals.csv") %>%mutate(project_appellant =paste(project_id, sep ="-", appellant))# modelsummary::datasummary_skim(bor)# Cleaned PIN-Project list after cleaning the commercial valuation dataset found online. # Another temporary work-around until we (maybe) have full keypin list:proj_xwalk <-read_csv("../Output/all_keypins.csv") # all commercial valuation properties but made with not-quite-clean data from commercial valuation dataset on Cook County Data Portal (which was made from combining the Methodology worksheets) # Values are also only the FIRST PASS assessments and do not include appeals or changes in values# Join project IDs to PINs:ptax_pins <- ptax_pins %>%left_join(proj_xwalk)nicknames <- readxl::read_excel("../Necessary_Files/muni_shortnames.xlsx") # create tc_muninames from helper file:#source("../scripts/helper_tc_muninames_2022.R")#tc_muninames <- tc_muninames %>% select(-year)# add muni names by joining tax code info:# ptax_pins <- ptax_pins %>% # mutate(tax_code_num = as.character(tax_code_num))# %>%# left_join(tc_muninames)# original class_dict variables already in 0_joined data# but I do want the new-ish variables I created to be brought in:class_dict <-read_csv("../Necessary_Files/class_dict_expanded.csv") %>%select(class_code, comparable_props, Alea_cat, incent_prop)# "Frankfort", "Homer Glen", "Oak Brook", "East Dundee", "University Park", "Bensenville", "Hinsdale", "Roselle", "Deer Park", "Deerfield"cross_county_lines <-c("030440000", "030585000", "030890000", "030320000", "031280000","030080000", "030560000", "031120000", "030280000", "030340000","030150000","030050000", "030180000","030500000", "031210000")ptax_pins <- ptax_pins %>%left_join(class_dict, by =c("class"="class_code")) %>%mutate(clean_name =ifelse(is.na(clean_name), "Unincorporated", clean_name)) %>%filter(!agency_num %in% cross_county_lines)# BOR data source shortfall: We only have the data if they appeal!bor_pins <- bor %>%group_by(pin) %>%arrange(desc(tax_year)) %>%summarize(pin =first(pin), # grabs first occurrence of unique PINclass_bor =list(unique(class)),appellant =first(appellant),project_id =first(project_id), timesappealed =n() ) %>%mutate(proj_appellant =paste(project_id, "-", appellant))ptax_pins <- ptax_pins %>%left_join(bor_pins, by ="pin")# now do it the other way and compareptax_pins <- ptax_pins %>%mutate( both_ids = project_id,both_ids =ifelse(is.na(both_ids), keypin, both_ids),both_ids =ifelse(is.na(both_ids) &between(class, 300, 899), pin, both_ids))eq2022 <-2.9237#example of eq factor proliferationincentive_majorclasses <-c("6", "7A", "7B", "8A", "8B")commercial_classes <-c(401:435, 490, 491, 492, 496:499,500:535,590, 591, 592, 597:599, 700:799,800:835, 891, 892, 897, 899) industrial_classes <-c(480:489,493, 550:589, 593,600:699,850:890, 893 )ptax_pins <- ptax_pins %>%mutate(class_1dig =str_sub(class, 1,1),class_group =case_when( (class_1dig ==5& class %in% commercial_classes) ~"5A", (class_1dig ==5& class %in% industrial_classes) ~"5B", class_1dig ==7& class <742~"7A", class_1dig ==7& class >=742~"7B", (class_1dig ==8& class %in% commercial_classes ) ~"8A", (class_1dig ==8& class %in% industrial_classes ) ~"8B",TRUE~as.character(class_1dig))) %>%mutate(# taxing district revenue = taxable eav * tax rate so rearrange the formula:taxed_eav = final_tax_to_dist / tax_code_rate*100,total_value_eav = (final_tax_to_dist + final_tax_to_tif)/ tax_code_rate *100+ all_exemptions + abatements,exempt_eav_inTIF =ifelse(in_tif ==1, all_exemptions, 0),exempt_eav = all_exemptions + abatements,taxed_av = taxed_eav / eq2022, # current value that taxing agencies can tax for their levies## taxable AV = equalized assessed value net TIF increments, gross exemptions. ## Used for calculating untaxable value further below# taxable_av = (final_tax_to_dist / tax_code_rate *100 + all_exemptions + abatements)/ eq2022, # taxable_eav_fromincents = ifelse(class >=600 & class < 900, taxable_av * eq2022, 0),## untaxable value = exempt EAV from abatements and exemptions + TIF incrementuntaxable_value_eav = all_exemptions + abatements +## TIF increment EAV above frozen EAV, which becomes TIF revenue (final_tax_to_tif / tax_code_rate*100) +## difference between 25% and reduced level of assessment for incentive class properties. Excludes TIF increment when calculating the difference! ifelse(between(class, 600, 899), (taxed_av/loa*0.25- taxed_av)*eq2022, 0),untaxable_incent_eav =ifelse(between(class, 600, 899), (taxed_av/loa*0.25- taxed_av)*eq2022, 0),# manually adjust untaxable value of class 239 propertiesuntaxable_value_eav =ifelse(class ==239, equalized_av-taxed_eav, untaxable_value_eav), untaxable_value_av = untaxable_value_eav / eq2022,untaxable_value_fmv = untaxable_value_av / loa,exempt_fmv = exempt_eav / eq2022 / loa, fmv_inTIF =ifelse(in_tif==1, av/loa, 0),fmv_tif_increment =ifelse(final_tax_to_tif >0, ((final_tax_to_tif / (tax_code_rate/100)) / eq2022 ) / loa, 0),fmv_incents_inTIF =ifelse(between(class, 600, 899) & in_tif ==1, fmv, 0),fmv_incents_tif_increment =ifelse(between(class, 600, 899) & final_tax_to_tif >0 , ((final_tax_to_tif / (tax_code_rate/100)) / eq2022 ) / loa, 0),naive_rev_forgone = untaxable_incent_eav * tax_code_rate/100) %>%select(tax_code, class, pin, fmv, untaxable_value_fmv, fmv_inTIF, fmv_tif_increment, fmv, total_billed, final_tax_to_dist, final_tax_to_tif, tax_code_rate, eav, equalized_av, av, everything())
Total Value should equal Current Taxable Value + non-Taxable Value where non-Taxable Value = Value in TIF Increment + Reduced Value from Policy Choices where Reduced Value = Tax Exempt Value from Homeowners exemptions or abatements + Reduced Taxable Value from lower levels of assessments due to incentive classifications:
\[\mbox{Total Value = Taxed Value + Untaxable Value}\]
where
\[\mbox{Untaxable Value = TIF Increment + Exemptions + Abatements
+ Reduced Taxable Value from Lower Incentive Class Assessment Ratios}\]
where
\[\mbox{Reduced Taxable Value from Incentive Classification Levels of Assessments}\]\[\mbox{which then equals } {0.25 \ast EAV - \approx0.10 \ast EAV}\]
Cook County Total Value
\[
\mbox{AV = Fair Market Value * Level of Assessment}
\]
Taxed Value refers to what taxing agencies did tax to pay for their levies. We use the portion of the tax bill that does NOT go to TIFs to calculate the portion of the composite levy paid by each PIN and then sum up from there.
\[
\mbox{Final Tax to District} = \mbox{Portion of Levy Paid by PIN} = {\mbox{Tax Code Rate}}*{\mbox{Taxable Value of PIN}}
\]
\[\mbox{Equalized Assessed Value} = {\frac{\mbox{final tax to dist + final tax to TIF}}{\mbox{tax code rate}} + \mbox{Exemptions + Abatements}}\]
Table 8.1: FMV of PINs in Cook County Taxed FMV represents the property value that was actually taxed by local taxing jurisdictions(equal to the amount levied) but converted to FMV. We use the the portion of an individuals tax bill that does NOT go to a TIF to calculate the composite levy for taxing jursidictions.
Code
table_cook %>%select(cty_fmv_comandind, #cty_fmv, cty_pct_fmv_both_incent, cty_pct_fmv_incentinTIF, cty_pct_PC_both_incent, cty_PC_comandind, cty_PC_incent_inTIF, cty_pct_PC_both_incent_inTIF, cty_pct_fmv_incents_tif_increment) %>%mutate(across(contains("pct_"), scales::percent, accuracy = .01)) %>%flextable() %>%align(align ="right") %>%set_header_labels(cty_fmv_comandind ='Com. & Ind. FMV',# cty_fmv = 'Total FMV in Cook',cty_pct_fmv_both_incent ='% of Com. & Ind. FMV w/ Incent.',cty_pct_fmv_incentinTIF ='% of Com. & Ind. FMV w/ Incent. in TIF',cty_pct_fmv_incents_tif_increment ='% of Com. & Ind. FMV in TIF Increment',cty_PC_comandind ='PIN Count',cty_PC_incent_inTIF ="Incent. PINs in TIF",cty_pct_PC_both_incent ='% of Com. & Ind. PINs w/ Incent.',cty_pct_PC_both_incent_inTIF ='% of Incent. PINs in TIF' ) %>%FitFlextableToPage()
Com. & Ind. FMV
% of Com. & Ind. FMV w/ Incent.
% of Com. & Ind. FMV w/ Incent. in TIF
% of Com. & Ind. PINs w/ Incent.
PIN Count
Incent. PINs in TIF
% of Incent. PINs in TIF
% of Com. & Ind. FMV in TIF Increment
112,959,756,091
3.25%
41.45%
4.50%
95,299
1,909
44.47%
26.58%
Table 8.2: Commercial and Industrial PINs in Cook County 3.2% of industrial and commercial PINs (aka “revenue producing PINs”) FMV has an incentive classification (4.55% when using PIN counts). Of the PINs that have incentive classification, 41.5% of the FMV is located within a TIF (43.9% when using PIN counts).
Table 8.3: Commercial PINs in Cook County 4.1% of commercial PINs FMV has an incentive classification (1.2% when using PIN counts). Of the commercial PINs that have incentive classification, 55.9% of the FMV is located within a TIF (40.5% when using PIN counts).
Table 8.4: Industrial PINs in Cook County 36.7% of industrial PINs FMV has an incentive classification (13.7% when using PIN counts). Of the Industrial PINs that have incentive classification, 35.7% of the FMV is located within a TIF (44% when using PIN counts).
Table 8.6: Untaxable AV in Cook County. Taxed AV represents the property value that was actually taxed by local taxing jurisdictions.
Code
table_cook %>%select(cty_fmv, cty_fmv_inTIF, cty_fmv_tif_increment, cty_fmv_incentive, cty_fmv_incent_inTIF, cty_fmv_incents_tif_increment) %>%flextable() %>%set_header_labels(cty_fmv ='Total FMV', cty_fmv_inTIF ='FMV in TIFs',cty_fmv_tif_increment ='TIF Increment FMV' ,cty_fmv_incentive ="FMV with Incent.Class.", cty_fmv_incent_inTIF ='FMV with Incent. Class. in TIFs')%>%FitFlextableToPage()
Total FMV
FMV in TIFs
TIF Increment FMV
FMV with Incent.Class.
FMV with Incent. Class. in TIFs
cty_fmv_incents_tif_increment
596,863,352,086
111,309,224,161
45,606,137,923
12,633,962,903
5,236,537,107
3,357,780,319
Table 8.7: FMV of properties with incentive classifications and TIF increment. Value in TIFs, value within the TIF that can be taxed by local taxing jurisdictions, value of properties that have reduced levels of assessments from incentive classifications, and the value that is both in a TIF and has a reduced LOA.
Taxed value is the amount of value that was actually taxed in order to pay for taxing agencies levies. It includes frozen EAV within an area + taxable EAV for residential properties net exemptions and abatements. It also includes the equalized assessed value of incentive properties at their current, lower assessment ratios. final_tax_to_dist is used to calculate the amount that was collected by local government agencies and then divided by the tax rate to calculate the amount of value that was taxed, or the taxable equalized assessed value (TEAV).
The Taxed Value, when converted to the Fair Market Value (FMV) represents the amount of value that was taxed out of the full FMV available in Cook County.
Untaxable EAV includes homeowner exemptions for 200 level properties, abatements for other property class types, EAV in the TIF increment, and EAV that has been reduced due to incentive classifications.
The Fair Market Value (FMV) is also called the Market Value for
Assessment Purposes and can be calculated from the av /
loa, or the Assessed Value divided by the Level of
Assessment. However, the values used for the level of assessment are an
approximation for incentive properties since we do not have the PIN
level assessment ratios.
Code
table_cook %>%ggplot() +geom_line(aes(x=year, y=fmv_group_growth, group = landuse_change, color = landuse_change)) +facet_wrap(~incent_change) +scale_x_continuous(#limits = c(2011, 2022), breaks =c(2011, 2018, 2022)) +labs(title="Growth from 2011 to 2022", subtitle ="Change in Incentive Use by Land Use Change", caption ="Indexed to 2011 FMV", x ="", y ="FMV Growth from 2011")
Code
library(tidyverse)options(scipen =999)# Trends in Incentivized FMV as a percent of the base over time## Data prepmuni_MC <-read_csv("../Output/ptaxsim_muni_class_summaries_2006-2022.csv") %>%select(year, clean_name, class, av = muni_c_av)class_dict <-read_csv("../Necessary_Files/class_dict_expanded.csv") %>%select(class = class_code, class_1dig, assess_ratio, incent_prop, Alea_cat, major_class_code)muni_MC <- muni_MC %>%left_join(class_dict, by =c("class")) %>%filter(class !=0) # drop exempt property types with 0 taxable value#class_8_munis <- read_csv("./Necessary_Files/datarequests_Class8Munis.csv")class_8_munis <-read_csv("../Output/datarequests_Class8Munis.csv")# changed from as.list to as.characterclass_8_munis <-as.character(class_8_munis$clean_name)# class 8 munis - at the year-class levelclass_8_df <-# left_join(muni_MC, class_dict, by = "class") %>% muni_MC %>%filter(clean_name %in% class_8_munis) %>%filter(av !=0) %>%mutate(FMV = av/assess_ratio) %>%group_by(year) %>%mutate(year_tb_tot =sum(FMV)) %>%# tax base for all class 8 munis together, per yearungroup() %>%filter(Alea_cat %in%c("Industrial", "Commercial")) %>%## drops all non-industrial and non-commercial classes to calculate the rest of the totalsgroup_by(year) %>%mutate(year_ind_comm_FMV =sum(FMV)) %>%# total commercial and industrial FMV for all class 8 munis together, per yearungroup() %>%group_by(year, clean_name) %>%mutate(muni_year_ind_comm_FMV =sum(FMV)) %>%# calculates total FMV in each munis each yearungroup() %>%group_by(year, Alea_cat) %>%mutate(cat_year_FMV =sum(FMV)) %>%# calculates FMV within each commercial vs industrial category for each yearungroup() %>%group_by(year, clean_name, class_1dig) %>%# total fmv in class 5, 6, 7, and 8 per munimutate(year_muni_class_FMV =sum(FMV))## Added this for cook level totals:class_8_df_outofCook <- muni_MC %>%# filter(clean_name %in% class_8_munis) %>% ## keep all munis, use for cook county totals.filter(av !=0) %>%mutate(FMV = av/assess_ratio) %>%group_by(year) %>%mutate(year_tb_tot =sum(FMV)) %>%# tax base for all class 8 munis together, per yearungroup() %>%filter(Alea_cat %in%c("Industrial", "Commercial")) %>%## drops all non-industrial and non-commercial classes to calculate the rest of the totalsgroup_by(year) %>%mutate(year_ind_comm_FMV =sum(FMV)) %>%# total commercial and industrial FMV for all class 8 munis together, per yearungroup() %>%group_by(year, clean_name) %>%mutate(muni_year_ind_comm_FMV =sum(FMV)) %>%# calculates total FMV in each munis each yearungroup() %>%group_by(year, Alea_cat) %>%mutate(cat_year_FMV =sum(FMV)) %>%# calculates FMV within each commercial vs industrial category for each yearungroup() %>%group_by(year, clean_name, class_1dig) %>%# total fmv in class 5, 6, 7, and 8 per munimutate(year_muni_class_FMV =sum(FMV))## Class 8 Townships Graph -------------------## Alea Version: ggplot() +geom_line(data = class_8_df %>%group_by(year) %>%summarize(ind_comm_perc =mean(year_ind_comm_FMV/year_tb_tot)), aes(x = year, y = ind_comm_perc, color ="Commercial+Industrial"), lwd =1) +# industrial fmvgeom_line(data = class_8_df %>%filter(Alea_cat =="Industrial") %>%group_by(year) %>%# needed na.rm=TRUE, otherwise it didn't work. perc_industrial was not being calculated without it.summarize(perc_industrial =sum(FMV/year_tb_tot, na.rm=TRUE)), ## added this partaes(x = year, y = perc_industrial, color ="Industrial"), lwd =1) +# commercial fmvgeom_line(data = class_8_df %>%filter(Alea_cat =="Commercial") %>%group_by(year) %>%summarize(perc_commercial =sum(FMV/year_tb_tot, na.rm=TRUE)), ## added this partaes(x = year, y = perc_commercial, color ="Commercial"), lwd =1) +geom_line(data = class_8_df %>%filter(incent_prop =="Incentive") %>%group_by(year) %>%summarise(incent_perc =sum(FMV)/year_tb_tot),aes(x = year, y = incent_perc, color ="Incentive Classes"), lwd =1 ) +geom_line(data = class_8_df %>%# threw error here, missing x and y in aes()filter(class_1dig ==8) %>%group_by(year) %>%summarize(perc_8 =sum(FMV/year_tb_tot)), ## added this partaes(x = year, y = perc_8, color ="Class 8"), lwd =1) +# was missing a + sign heretheme_classic() +scale_x_continuous(name ="", breaks =seq(2006, 2022, by =3), limits =c(2006, 2022), expand =c(0,0)) +scale_y_continuous(name ="Percent of FMV", labels = scales::percent_format(), limits =c(0, 0.20),breaks =seq(0, 0.5, by =0.05), expand =c(0,0)) +scale_color_manual(name ="", values =c("Commercial+Industrial"="black", "Industrial"="gray70", "Commercial"="gray50", "Incentive Classes"="orange", "Class 8"="red" )) +theme(legend.position ="bottom") +labs(title ="Property in the Class 8 Townships") +guides(color =guide_legend(nrow=2, byrow =TRUE))
Code
## Percentage out of Cook County ---------------------## Alea Version for Cook Level: ggplot() +# Commercial + Industrial FMV in cookgeom_line(data = class_8_df_outofCook %>%group_by(year) %>%#didn't group by year before?summarize(ind_comm_perc =mean(year_ind_comm_FMV/year_tb_tot)), aes(x = year, y = ind_comm_perc, color ="Commercial+Industrial"), lwd =1) +# incentive class properties in cookgeom_line(data = class_8_df_outofCook %>%filter(incent_prop =="Incentive") %>%group_by(year) %>%summarise(incent_perc =sum(FMV/year_tb_tot)),aes(x = year, y = incent_perc, color ="Incentive Classes"), lwd =1 ) +# FMV with class 8 property class in cook countygeom_line(data = class_8_df_outofCook %>%# threw error here, missing x and y in aes()filter(class_1dig ==8) %>%group_by(year) %>%summarize(perc_8 =sum(FMV/year_tb_tot)), ## added this partaes(x = year, y = perc_8, color ="Class 8"), lwd =1) +# was missing a + sign here# industrial fmv in cook countygeom_line(data = class_8_df_outofCook %>%# threw error here, missing x and y in aes()filter(Alea_cat =="Industrial") %>%group_by(year) %>%# needed na.rm=TRUE, otherwise it didn't work. perc_industrial was not being calculated without it.summarize(perc_industrial =sum(FMV/year_tb_tot, na.rm=TRUE)), ## added this partaes(x = year, y = perc_industrial, color ="Industrial"), lwd =1) +# commercial fmv in cook countygeom_line(data = class_8_df_outofCook %>%# threw error here, missing x and y in aes()filter(Alea_cat =="Commercial") %>%group_by(year) %>%summarize(perc_commercial =sum(FMV/year_tb_tot, na.rm=TRUE)), ## added this partaes(x = year, y = perc_commercial, color ="Commercial"), lwd =1) +# make it pretty:theme_classic() +scale_x_continuous(name ="", breaks =seq(2006, 2022, by =3), limits =c(2006, 2022), expand =c(0,0)) +scale_y_continuous(name ="Percent of County FMV", labels = scales::percent_format(), limits =c(0, 0.20), breaks =seq(0, 0.5, by =0.05), expand =c(0,0)) +scale_color_manual(name ="", values =c("Commercial+Industrial"="black", "Industrial"="gray80", "Commercial"="gray40", "Incentive Classes"="orange", "Class 8"="red")) +theme(legend.position ="bottom") +labs(title="Cook County Commercial & Industrial FMV") +guides(color =guide_legend(nrow=2, byrow =TRUE))
Code
## Newest Addition for April 30th Presentation --------------------ggplot() +# incentive class properties in cookgeom_line(data = class_8_df_outofCook %>%filter(incent_prop =="Incentive") %>%group_by(year) %>%summarise(incent_perc =sum(FMV/year_ind_comm_FMV)),aes(x = year, y = incent_perc, color ="Incentive Classes"), lwd =1 ) +# FMV with class 8 property class in cook countygeom_line(data = class_8_df_outofCook %>%filter(class_1dig ==8) %>%group_by(year) %>%summarize(perc_8 =sum(FMV/year_ind_comm_FMV)), aes(x = year, y = perc_8, color ="Class 8"), lwd =1) +# make it pretty:theme_classic() +scale_x_continuous(name ="", breaks =seq(2006, 2022, by =3), limits =c(2006, 2022), expand =c(0,0)) +scale_y_continuous(name ="Percent of Com+Ind FMV", labels = scales::percent_format(), limits =c(0, 0.25), breaks =seq(0, 0.5, by =0.05), expand =c(0,0)) +scale_color_manual(name ="", values =c("Industrial"="gray80", "Commercial"="gray40", "Incentive Classes"="orange", "Class 8"="red")) +theme(legend.position ="bottom") +labs(title="Cook County", subtitle ="Share of Commercial & Industrial FMV with Incentive Classification") +guides(color =guide_legend(nrow=2, byrow =TRUE))
Code
## Newest Addition for April 30th Presentation --------------------ggplot() +# incentive class properties in cookgeom_line(data = class_8_df_outofCook %>%filter(incent_prop =="Incentive") %>%group_by(year) %>%summarise(incent_perc =sum(FMV/year_ind_comm_FMV)),aes(x = year, y = incent_perc, color ="Incentive Classes"), lwd =1 ) +# # # FMV with class 8 property class in cook county# geom_line(data = class_8_df_outofCook %>% # filter(class_1dig == 8) %>% # group_by(year) %>%# summarize(perc_8 = sum(FMV/year_ind_comm_FMV)), # aes(x = year, y = perc_8, color = "Class 8"), lwd = 1) + # make it pretty:theme_classic() +scale_x_continuous(name ="", breaks =seq(2006, 2022, by =3), limits =c(2006, 2022), expand =c(0,0)) +scale_y_continuous(name ="Percent of Com+Ind FMV", labels = scales::percent_format(), limits =c(0, 0.25), breaks =seq(0, 0.5, by =0.05), expand =c(0,0)) +scale_color_manual(name ="", values =c("Industrial"="gray80", "Commercial"="gray40", "Incentive Classes"="orange")) +theme(legend.position ="bottom") +labs(title="Cook County", subtitle ="Share of Commercial & Industrial FMV with Incentive Classification") +guides(color =guide_legend(nrow=2, byrow =TRUE))
Code
ggplot() +geom_line(data = class_8_df %>%filter(incent_prop =="Incentive") %>%group_by(year) %>%summarise(incent_perc =sum(FMV/year_ind_comm_FMV)),aes(x = year, y = incent_perc, color ="All Incentive Classes"), lwd =1 ) +geom_line(data = class_8_df %>%filter(class_1dig ==8) %>%group_by(year) %>%summarize(perc_8 =sum(FMV/year_ind_comm_FMV)), aes(x = year, y = perc_8, color ="Class 8"), lwd =1) +# make it pretty:theme_classic() +scale_x_continuous(name ="", breaks =seq(2006, 2022, by =3), limits =c(2006, 2022), expand =c(0,0)) +scale_y_continuous(name ="Percent of Com&Ind FMV", labels = scales::percent_format(), # limits = c(0, 0.25), breaks =seq(0, 0.5, by =0.05), expand =c(0,0)) +scale_color_manual(name ="", values =c("Commercial+Industrial"="black", "Industrial"="gray80", "Commercial"="gray40", "All Incentive Classes"="orange", "Class 8"="red")) +theme(legend.position ="bottom") +labs(title="Class 8 Townships", subtitle ="Share of Commercial & Industrial FMV with Incentive Classification") +guides(color =guide_legend(nrow=2, byrow =TRUE))
Municipality Level Stats
Ignore stats for these Municipalities. Simple rounding errors may cause bizarre results for rate changes & other calculations. These municipalities are dropped from summary tables in this website but are included in exported files.
Frankfort has 1 PIN in Cook County
East Dundee has 2
Homer Glen has 3
University Park has 4
Oak Brook, Deer Park, Deerfield, & Bensenville each have less than 75 PINs in Cook County, IL
Table 9.5: Municipalities with the largest share of Commercial and Industrial property with incentive classification. Uses tax year 2022 values obtained from PTAXSIM, and levels of assessment from CCAO’s Github. There are 27 municipalities that do not use incentives and have a majority of their taxable EAV within Cook County.
$15 Billion EAV is tax exempt due to homeowners exemptions. All incentive properties combined only have $4 billion EAV that is tax exempt (due to the decreased level of assessment which results in less AV, and therefore, EAV)
Estimates for Revenue Shifted to Non-Incentive Class Properties
Uses old current tax rate and multiplies it by the new taxbase.
Code
ptax_pins %>%filter(!clean_name %in%c("Frankfort", "Homer Glen", "Oak Brook", "East Dundee","University Park", "Bensenville", "Hinsdale", "Roselle","Deer Park", "Deerfield")) %>%filter(!agency_num %in% cross_county_lines &!is.na(clean_name) & clean_name!="Unincorporated" ) %>%summarize(# for homestead exemptionsmostnaive_forgone_tax_amt_exe =sum(tax_amt_exe), # more accurate but still uses current tax rate instead of recalculated tax rate:forgonerev_from_exemptions =sum(ifelse(class >=200& class <300, (((av*eq2022) - (taxed_av*eq2022))) * tax_code_rate/100, 0), na.rm=TRUE),# amount of EAV from taxing an additional 15% of the AV if incentive properties didn't exist# using current tax rate for each property at the tax code levelforgonerev_from_comind_incents =sum(ifelse(class >=600& class <900, (((taxed_av*eq2022)*0.25- (taxed_av*eq2022))) * tax_code_rate/100, 0), na.rm=TRUE),forgonerev_commerc_incents =sum(ifelse(class >=600& class <900& class %in% commercial_classes, (((taxed_av*eq2022)*0.25- (taxed_av*eq2022))) * tax_code_rate/100, 0), na.rm=TRUE),forgonerev_indust_incents =sum(ifelse(class >=600& class <900& class %in% industrial_classes, (((taxed_av*eq2022)*0.25- (taxed_av*eq2022))) * tax_code_rate/100, 0), na.rm=TRUE),# forgonerev_noTIFs = rate_current/100 * ,# TIF increment above the frozen EAVforgonerev_TIFs =sum(fmv_tif_increment * loa * eq2022*tax_code_rate/100, na.rm=TRUE),# if incentive properties had no tax value (i.e. owners left, or fully tax exempt)# also equal to the current amount collected from incentive propertiesforgonerev_vacant =sum(ifelse(class >=600& class <900, taxed_av*eq2022 * tax_code_rate/100, 0), na.rm =TRUE) )
Change in Composite Property Tax Rate Due to Incentives and other Policy Scenarios
Code
muni_ratechange <- ptax_pins %>%ungroup() |># left_join(muni_rate) %>%filter(!clean_name %in%c("Frankfort", "Homer Glen", "Oak Brook", "East Dundee", "University Park", "Bensenville", "Hinsdale", "Roselle", "Deer Park", "Deerfield")) %>%filter(!agency_num %in% cross_county_lines) %>%group_by(clean_name) %>%summarize(classgroup_PC =n(),# projects = n_distinct(both_ids), # mostly for industrial and commercial propertiespins_withincents =sum(ifelse(class >=600& class <900, 1,0)),fmv_incentive =sum(ifelse(class >=600& class <900, fmv, 0), na.rm =TRUE),#fmv_taxed = sum(taxed_fmv, na.rm=TRUE),fmv_incents_inTIFs =sum(ifelse(class >=600& class <900& final_tax_to_tif >0, fmv, 0), na.rm =TRUE),fmv_inTIF =sum(fmv_inTIF, na.rm=TRUE),eav_tif_increment =sum(final_tax_to_tif/tax_code_rate, na.rm=TRUE),fmv_tif_increment =sum(fmv_tif_increment, na.rm=TRUE),fmv_untaxable_value =sum(untaxable_value_fmv , na.rm=TRUE),fmv_exemptions =sum(all_exemptions/eq2022/loa, na.rm=TRUE),fmv_abatements =sum(exe_abate/eq2022/loa, na.rm=TRUE),zero_bill =sum(zero_bill, na.rm=TRUE),fmv_residential =sum(ifelse(class %in%c(200:399), fmv, 0), na.rm =TRUE),fmv_C2 =sum(ifelse(class %in%c(200:299), fmv, 0), na.rm =TRUE),fmv_industrial =sum(ifelse(class %in% industrial_classes, fmv, 0), na.rm =TRUE),fmv_commercial =sum(ifelse(class %in% commercial_classes, fmv, 0), na.rm =TRUE),current_rate_avg =mean(tax_code_rate),avg_C2_bill_noexe =mean(ifelse(between(class,200,299) & all_exemptions ==0, (final_tax_to_dist + final_tax_to_tif), NA), na.rm=TRUE),avg_C2_bill_withexe =mean(ifelse(between(class,200,299) & all_exemptions >0, (final_tax_to_dist + final_tax_to_tif), NA), na.rm=TRUE),av_taxed =sum(taxed_av, na.rm =TRUE),untaxable_value_av =sum(untaxable_value_av, na.rm=TRUE),av =sum(av),eav_taxed =sum(taxed_av*eq2022, na.rm=TRUE), eav_untaxable =sum(untaxable_value_eav, na.rm=TRUE),eav_max =sum(fmv*loa*eq2022, na.rm=TRUE),fmv =sum(fmv, na.rm=TRUE),pins_in_class =n(),all_exemptions =sum(all_exemptions), # in EAVabatements =sum(exe_abate), # in EAVeav_incents_inTIFs =sum(ifelse(class >=600& class <=900& in_tif ==1, eav, 0), na.rm =TRUE),# loa = mean((loa*classgroup_PC ) / sum(classgroup_PC), na.rm=TRUE),final_tax_to_dist =sum(final_tax_to_dist),final_tax_to_tif =sum(final_tax_to_tif),eav =sum(eav),new_TEAV_noIncents =sum(ifelse(class >=600& class <900, (taxed_av*eq2022/loa)*0.25, taxed_av*eq2022), na.rm=TRUE),new_TEAV_noC6 =sum(ifelse( class >=600& class <700, (taxed_av*eq2022/loa)*0.25 , taxed_av*eq2022)),new_TEAV_noC7 =sum(ifelse(class >=700& class <800, (taxed_av*eq2022/loa)*0.25, taxed_av*eq2022)),new_TEAV_noC8 =sum(ifelse(class >=800& class <900, (taxed_av*eq2022/loa)*0.25, taxed_av*eq2022)),new_TEAV_vacant_noIncents =sum(ifelse(class >=600& class <900,0, taxed_av*eq2022), na.rm=TRUE)) |>mutate(new_TEAV_noExemps = eav_taxed + all_exemptions, # does not include abatementsnew_TEAV_noAbates = eav_taxed + abatements, # include only abatements, not other exemption types# amount of EAV from taxing an additional 15% of the AV if incentive properties didn't existforgone_EAV_incent =#class_group %in% incentive_majorclasses,#incent_prop == "Incentive", new_TEAV_noIncents - eav_taxed,# TIF increment above the frozen EAV# forgone_TIF_EAV = fmv_tif_increment * loa * eq2022 ) %>%#cbind(table_cook) %>%mutate(# Absolute maximum TEAV: No Exemptions, no abatements, no TIFS, no Incentive properties# Commercial and industrial assessed at 25%TEAV_max = eav_taxed + all_exemptions + abatements + eav_tif_increment + forgone_EAV_incent,# no exemptions or incentive classifications:TEAV_neither = eav_taxed + all_exemptions + forgone_EAV_incent,rate_noExe = final_tax_to_dist / new_TEAV_noExemps *100,rate_noAbate = final_tax_to_dist / new_TEAV_noAbates *100,rate_noInc = final_tax_to_dist / new_TEAV_noIncents *100,rate_neither = final_tax_to_dist / TEAV_neither *100, rate_noTIFs = final_tax_to_dist / (eav_taxed + eav_tif_increment) *100,rate_vacant = final_tax_to_dist / new_TEAV_vacant_noIncents*100,rate_lowest = final_tax_to_dist / TEAV_max *100,# rate_noC6 = levy / new_TEAV_noC6 * 100,# rate_noC7 = levy / TEAV_noC7 * 100,# rate_noC8 = levy / TEAV_noC8 * 100,rate_current = final_tax_to_dist / eav_taxed *100,change_noInc = rate_current - rate_noInc,change_neither = rate_current - rate_neither,change_noTIF = rate_current - rate_noTIFs,change_noExe = rate_current - rate_noExe,change_vacant = rate_current - rate_vacant,change_lowest = rate_current - rate_lowest ) %>%mutate(across(contains("rate_"), round, digits =2))
Tables - Difference in Composite Tax Rates
Code
muni_ratechange_sliced <- muni_ratechange %>%select(clean_name, rate_current, rate_noInc, change_noInc) %>%arrange(desc(change_noInc) ) %>%mutate(across(c(rate_current, rate_noInc, change_noInc), round, digits=2)) %>%mutate(change_noInc =abs(round(change_noInc, digits =2)) ) %>%slice(c(1:5, 58:62, 115:119)) muni_ratechange_sliced %>%flextable() %>%border_remove() %>%hline_top() %>%hline(i =c(5,10)) %>%set_header_labels(clean_name ="Municipality", rate_current ="Current Comp.\nTax Rate", rate_noInc ="Tax Rate if No\nIncent. Class.",change_noInc ="Rate Change") %>%bold(i =8) %>%add_footer("There are 26 municipalities that do not use incentives and have a majority of their taxable EAV within Cook County.", top =FALSE) %>%set_table_properties( layout ="autofit")
Municipality
Current Comp. Tax Rate
Tax Rate if No Incent. Class.
Rate Change
Mc Cook
13.61
8.95
4.66
Bedford Park
14.25
9.72
4.54
Matteson
18.50
14.08
4.42
Ford Heights
27.12
22.91
4.20
North Lake
12.19
8.00
4.19
Niles
8.05
7.79
0.26
Robbins
16.32
16.08
0.24
Chicago Ridge
13.39
13.17
0.22
Midlothian
16.00
15.79
0.21
Glenview
7.43
7.24
0.19
Stickney
13.13
13.13
0.00
Western Springs
8.76
8.76
0.00
Wilmette
7.35
7.35
0.00
Winnetka
7.46
7.46
0.00
Worth
14.12
14.12
0.00
Table 10.1: Composite Tax Rate Change from hypothetical scenario of taxing incentive property at 25% of their FMV instead of 10% of their FMV. There are 26 municipalities that do not use incentives and have a majority of their taxable EAV within Cook County.
The file comm_ind_inmunis_timeseries_2006to2022.csvcomm_ind_PINs_2011to2022_timeseries.csv contains all PINs that had an incentive property class for at least 1 year. It includes all observations for a property during the years that it existed, even if it is not an incentive class property in that year.
Table 11.2: Number of PINs that became each major class type each year.
Explore PINs that became Class 8 or Other Incentive in South Triad
Code
comm_ind_pins %>%filter(class8_change =="Becomes Class 8") %>%left_join(bor, by =c("pin", "year"="tax_year")) %>%filter(!is.na(appellant)) %>%arrange(pin, desc(year)) %>%select(year, appellant, project_id, class.x, everything())# example of PIN that was class 8 and then became un-incentivized in 2017# comm_ind_pins %>% filter(pin == "16271000330000")comm_ind_pins %>%filter(class8_change =="Becomes Class 8"& Triad =="South") %>%arrange(pin) %>%select(year, class, everything())