# default_exp cityfinance

This colab and more can be found at https://github.com/BNIA/VitalSigns.

Whats Inside?:

https://bniajfi.org/indicators/Housing%20And%20Community%20Development/homtax

https://bniajfi.org/indicators/Housing%20And%20Community%20Development/histax

Indicators Used

  • ✔️ 46 - histax - (MdProp, BCDF) Number of Historic Tax Credits per 1,000 Residential Units

The number of residential properties that received the Historic Tax Credit per 1,000 residential properties within an area. The credit is granted on the increased assessment directly resulting from qualified improvements. The duration of the credit is for 10 years, and is applicable to properties located in designated areas of significant historical value.

  • ✔️ 47 - homtax - (MdProp, BCDF) Number of Homestead Tax Credits per 1,000 Residential Units

The number of residential properties that received the homestead tax credit per 1,000 residential properties within an area. The Homestead Credit limits the increase in taxable assessments each year to a fixed percentage. Every county and municipality in Maryland is required to limit taxable assessment increases to 10% or less each year, with the Baltimore City rate capped at 4%.

Datasets Used

  • ✔️ housing.TaxCredits_201X (46-homtax, 47-owntax) From BidBaltimore
year = "20"

Import Modules

! pip install -U -q PyDrive ! pip install geopy ! pip install geopandas ! pip install geoplot ! pip install dataplay ! pip install matplotlib ! pip install psycopg2-binary! apt-get install build-dep python-psycopg2 ! apt-get install libpq-dev ! apt-get install libspatialindex-dev!pip install rtree !pip install dexplotfrom dataplay.geoms import workWithGeometryData%%capture # These imports will handle everything import os import sys import csv import matplotlib.pyplot as plt import numpy as np import pandas as pd import geopandas as gpd from geopandas import GeoDataFrame import psycopg2 import pyproj from pyproj import Proj, transform # conda install -c conda-forge proj4 from shapely.geometry import Point from shapely import wkb from shapely.wkt import loads # https://pypi.org/project/geopy/ from geopy.geocoders import Nominatim # In case file is KML, enable support import fiona fiona.drvsupport.supported_drivers['kml'] = 'rw' fiona.drvsupport.supported_drivers['KML'] = 'rw'from IPython.display import clear_output clear_output(wait=True)import ipywidgets as widgets from ipywidgets import interact, interact_manual

Configure Enviornment

# This will just beautify the output pd.set_option('display.expand_frame_repr', False) pd.set_option('display.precision', 2) from IPython.core.interactiveshell import InteractiveShell InteractiveShell.ast_node_interactivity = "all" # pd.set_option('display.expand_frame_repr', False) # pd.set_option('display.precision', 2) # pd.reset_option('max_colwidth') pd.set_option('max_colwidth', 20) # pd.reset_option('max_colwidth')totalres = pd.read_csv("37-totalres-19.csv") # totalres.set_index('CSA2010', inplace=True) totalres.tail(1)

HomesteadTax_FY20 - BidBaltimore - NEW

lsoriginal = gpd.read_file("HomesteadTax_FY20"+year+"_CSACity.shp");original.rename(columns={ 'CSA':'CSA2010', 'BaltCity':'InBaltimore'}, inplace=True) df = original[ original['CSA2010'].notnull() | original['InBaltimore'].notnull() ]print('After filtering records where a CSA or Baltimore geo-code match Exists') print( 'All rows Before Filter: ', original.shape[0] ) # rows, columns print( '# w BCity.isnull: ', df.InBaltimore.isnull().sum() ); bmorow = df[ df.CSA2010.isnull() ].shape[0] print( '# w CSA2010.isnull: ', bmorow ); csarow = df[ df.CSA2010.notnull() ].shape[0] print( '# w CSA2010.notnull: ', csarow ); print( '# rows After Filter: ', df.shape[0],'==',csarow,'+',bmorow,'==', csarow + bmorow); # add baltimore city df.CSA2010 = df.CSA2010.fillna('Baltimore City')homesteadTax = df.copy() homesteadTax.head(1)

HistoricTax_FY20xx - BidBaltimore - NEW

lsoriginal = gpd.read_file("HistoricTax_FY20"+year+"_CSACity.shp");original.rename(columns={ 'CSA':'CSA2010', 'BaltCity':'InBaltimore'}, inplace=True) df = original[ original['CSA2010'].notnull() | original['InBaltimore'].notnull() ]print('After filtering records where a CSA or Baltimore geo-code match Exists') print( 'All rows Before Filter: ', original.shape[0] ) # rows, columns print( '# w BCity.isnull: ', df.InBaltimore.isnull().sum() ); bmorow = df[ df.CSA2010.isnull() ].shape[0] print( '# w CSA2010.isnull: ', bmorow ); csarow = df[ df.CSA2010.notnull() ].shape[0] print( '# w CSA2010.notnull: ', csarow ); print( '# rows After Filter: ', df.shape[0],'==',csarow,'+',bmorow,'==', csarow + bmorow); # add baltimore city df.CSA2010 = df.CSA2010.fillna('Baltimore City')historicTax = df.copy() historicTax.head(1)

HistoricTax 46 - (MdProp, TaxSale)

https://bniajfi.org/indicators/Housing%20And%20Community%20Development/histax

Above:2016Query. Beloew:2017Query

with numerator AS ( select (sum( case when csa_present then 1 else NULL end)::numeric) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.historictax_fy2018', 'gid', 'the_geom') a left join housing.historictax_fy2018 b on a.gid = b.gid group by csa ), denominator AS ( select (sum( case when (address != $$NULL$$) AND (desclu = $$Apartments$$ OR desclu = $$Residential$$ OR desclu = $$Residential Commercial$$ OR desclu = $$Residential Condominium$$) then 1 else NULL end)::numeric ) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.mdprop_2017v2', 'gid', 'the_geom') a left join housing.mdprop_2017v2 b on a.gid = b.gid group by csa, the_pop ), tbl AS ( select denominator.csa,(numerator.result / denominator.result)*(1000::numeric) as result from numerator left join denominator on numerator.csa = denominator.csa )

select * from tbl where 1 = 1 ORDER BY csa ASC;

t = """ with numerator AS ( select (sum( case when csa_present then 1 else NULL end)::numeric) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.historictax_fy2017', 'gid', 'the_geom') a left join housing.historictax_fy2017 b on a.gid = b.gid group by csa ), denominator AS ( select (sum( case when (address != $$NULL$$) AND (desclu = $$Apartments$$ OR desclu = $$Residential$$ OR desclu = $$Residential Commercial$$ OR desclu = $$Residential Condominium$$) then 1 else NULL end)::numeric ) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.mdprop_2017', 'gid', 'the_geom') a left join housing.mdprop_2017 b on a.gid = b.gid group by csa, the_pop ), tbl AS ( select denominator.csa,(numerator.result / denominator.result)*(1000::numeric) as result from numerator left join denominator on numerator.csa = denominator.csa ) update vital_signs.data set histax = result from tbl where data.csa = tbl.csa and data_year = '2016'; """historicTax.columnstotalres = pd.read_csv("37-totalres-"+year+".csv"def histax(df, totalres, year): histax = df.copy() # Aggregate Numeric Values by Sum histax['histaxCount'] = 1 histax = histax.groupby('CSA2010').sum(numeric_only=True) # Make sure ALL csas and BaltimoreCity are included. among other things histax = totalres[ ['CSA2010','totalres'+year] ].merge( histax, left_on='CSA2010', right_on='CSA2010', how='outer' ) # Update the baltimore CSA. histax.at[55,'histaxCount'] = histax['histaxCount'].sum() # Create the Indicator histax['46-histax'+year] = histax['histaxCount'] * 1000 / totalres['totalres'+year] histax = histax[['CSA2010', 'histaxCount', '46-histax'+year, 'totalres'+year ]] compareYears = gpd.read_file("https://services1.arcgis.com/mVFRs7NF4iFitgbY/ArcGIS/rest/services/Histax/FeatureServer/0/query?where=1%3D1&outFields=*&returnGeometry=true&f=pgeojson"); prevYear = 'histax'+ str( int(year) - 1 ) if prevYear in compareYears.columns: histax = histax.merge( compareYears[['CSA2010', prevYear]], left_on='CSA2010', right_on='CSA2010', how='outer' ) histax['change'] = histax['46-histax'+year] - histax[ prevYear ] histax['percentChange'] = histax['change'] / histax[ prevYear ] * 1000 histax['change'] = histax['change'].apply(lambda x: "{:.2f}".format(x) ) histax = histax[['CSA2010', 'histaxCount', 'totalres19', 'histax18', '40-histax19', 'percentChange', 'change']] return histaxhistax = histax( historicTax, totalres, year) histax.head(60) histax.to_csv('46-histax'+year+'.csv', index=False)

HomesteadTax 47 - (MdProp, TaxSale)

t = """ with numerator AS ( select (sum( case when csa_present then 1 else NULL end)::numeric) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.homesteadtax_fy2017', 'gid', 'the_geom') a left join housing.homesteadtax_fy2017 b on a.gid = b.gid group by csa ), denominator AS ( select (sum( case when (address != $$NULL$$) AND (desclu = $$Apartments$$ OR desclu = $$Residential$$ OR desclu = $$Residential Commercial$$ OR desclu = $$Residential Condominium$$) then 1 else NULL end)::numeric ) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.mdprop_2017', 'gid', 'the_geom') a left join housing.mdprop_2017 b on a.gid = b.gid group by csa, the_pop ), tbl AS ( select denominator.csa,(numerator.result / denominator.result)*(1000::numeric) as result from numerator left join denominator on numerator.csa = denominator.csa ) update vital_signs.data set homtax = result from tbl where data.csa = tbl.csa and data_year = '2016'; Above:2016Query. Beloew:2017Query with numerator AS ( select (sum( case when csa_present then 1 else NULL end)::numeric) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.homesteadtax_fy2018', 'gid', 'the_geom') a left join housing.homesteadtax_fy2018 b on a.gid = b.gid group by csa ), denominator AS ( select (sum( case when (address != $$NULL$$) AND (desclu = $$Apartments$$ OR desclu = $$Residential$$ OR desclu = $$Residential Commercial$$ OR desclu = $$Residential Condominium$$) then 1 else NULL end)::numeric ) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.mdprop_2017v2', 'gid', 'the_geom') a left join housing.mdprop_2017v2 b on a.gid = b.gid group by csa, the_pop ), tbl AS ( select denominator.csa,(numerator.result / denominator.result)*(1000::numeric) as result from numerator left join denominator on numerator.csa = denominator.csa ) select * from tbl where 1 = 1 ORDER BY csa ASC; """totalres = pd.read_csv("37-totalres-"+year+".csv")totalres.columns#export def homtax(df, totalres, year): homtax = df.copy() # Aggregate Numeric Values by Sum homtax['homtaxCount'] = 1 homtax = homtax.groupby('CSA2010').sum(numeric_only=True) # Make sure ALL csas and BaltimoreCity are included. among other things homtax = totalres[ ['CSA2010','totalres'+year] ].merge( homtax, left_on='CSA2010', right_on='CSA2010', how='outer' ) # Update the baltimore CSA. homtax.at[55,'homtaxCount'] = homtax['homtaxCount'].sum() # Create the Indicator homtax['47-homtax'+year] = homtax['homtaxCount'] * 1000 / totalres['totalres'+year] homtax = homtax[['CSA2010', 'homtaxCount', '47-homtax'+year, 'totalres'+year ]] compareYears = gpd.read_file("https://services1.arcgis.com/mVFRs7NF4iFitgbY/ArcGIS/rest/services/Histax/FeatureServer/0/query?where=1%3D1&outFields=*&returnGeometry=true&f=pgeojson"); prevYear = 'histax'+ str( int(year) - 1 ) if prevYear in compareYears.columns: homtax = homtax.merge( compareYears[['CSA2010', prevYear]], left_on='CSA2010', right_on='CSA2010', how='outer' ) homtax['change'] = homtax['47-homtax'+year] - homtax[ prevYear ] homtax['percentChange'] = homtax['change'] / homtax[ prevYear ] * 1000 homtax['change'] = homtax['change'].apply(lambda x: "{:.2f}".format(x) ) homtax = homtax[['CSA2010', 'homtaxCount', 'totalres19', 'homtax18', '47-homtax19', 'percentChange', 'change']] return homtaxhomtax = homtax( homesteadTax, totalres, year) homtax.head(60) homtax.to_csv('47-homtax'+year+'.csv', index=False)

owntax 48

Seema did it most recently

select (sum( case when csa_present then 1 else 0 end)::numeric) as result, csa from vital_signs.match_csas_and_bc_by_geom('housing.homeownertax_2016', 'gid', 'the_geom') a left join housing.homeownertax_2016 b on a.gid = b.gid group by csa order by csa

WE ARE NOT USING THE QUERY OR THE DATA FROM THE QUERY

DATA WAS PROVIDED IN AN ALREADY AGGREGATED FORM

STARTING FROM 2016; WE Used to get it raw.

We do not get it raw for data confidentiality reasons (you would know how much people earn.)

we don't have 2020 so i know it's 19. but just something to keep in our notes, that for dept of finance data the fiscal year is +1 on what we call it for VS

SEARCH

CONNECT WITH US

DONATE

Help us keep this resource free and available to the public. Donate now!

Donate to BNIA-JFI

CONTACT US

Baltimore Neighborhood Indicators Alliance
The Jacob France Institute
1420 N. Charles Street, Baltimore, MD 21201
410-837-4377 | bnia-jfi@ubalt.edu