# AUTOGENERATED! DO NOT EDIT! File to edit: notebooks/04_Create_Acs_Indicators.ipynb (unless otherwise specified).

__all__ = ['getColName', 'getColByName', 'addKey', 'nullIfEqual', 'sumInts', 'createAcsIndicator',
           'age5', 'age18', 'age24', 'age64', 'age65', 'racdiv', 'hisp', 'paa', 'pwhite', 'pasi',
           'p2more', 'ppac', 'bahigher', 'hsdipl', 'lesshs', 'carpool', 'drvalone', 'pubtran', 'walked',
           'othercom', 'trav14', 'trav29', 'trav44', 'trav45', 'novhcl', 'hhs', 'fam', 'femhhs', 'sclemp',
           'hhpov', 'hhchpov', 'mhhi', 'hh25inc', 'hh40inc', 'hh60inc', 'hh75inc', 'hhm75inc', 'unempr',
           'empl', 'nilf', 'unempl', 'elheat', 'heatgas', 'affordr', 'affordm', 'nohhint']


#Cell
#@title Run This Cell: Misc Function Declarations

# These functions right here are used in the calculations below.
# Finds a column matchings a substring
def getColName  (df, col): return df.columns[df.columns.str.contains(pat = col)][0]
def getColByName (df, col): return df[getColName(df, col)]

# Pulls a column from one dataset into a new dataset.
# This is not a crosswalk. calls getColByName()
def addKey(df, fi, col):
    key = getColName(df, col)
    val = getColByName(df, col)
    fi[key] = val
    return fi
    
# Return 0 if two specified columns are equal.
def nullIfEqual(df, c1, c2):
    return df.apply(lambda x:
        x[getColName(df, c1)]+x[getColName(df, c2)] if x[getColName(df, c1)]+x[getColName(df, c2)] != 0 else 0, axis=1)
    
# I'm thinking this doesnt need to be a function..
def sumInts(df): return df.sum(numeric_only=True)


#Need these imports or the scripts WILL NOT work.
import geopandas as gpd
import numpy
import pandas as pd
from .acsDownload import retrieve_acs_data
from dataplay.merge import mergeDatasets
from dataplay.intaker import Intake


#cell
#@title Run This Cell: Create createIndicator()

def createAcsIndicator(state, county, tract, year, tableId,
                    mergeUrl, merge_left_col, merge_right_col, merge_how, groupBy,
                    aggMethod, method, columnsToInclude, finalFileName=False):

  # Pull the data
  df = retrieve_acs_data(state, county, tract, tableId, year)
  print('Table: ' + tableId + ', Year: ' + year + ' imported.')

  # Get the crosswalk
  if mergeUrl:
    right_ds = Intake.getData( mergeUrl )
    print( right_ds.columns )
    print('Merge file imported')
    # Merge crosswalk with the data
    df = mergeDatasets( left_ds=df, right_ds=right_ds,
                  left_col=merge_left_col, right_col=merge_right_col,
                  merge_how=merge_how, interactive=False )

    print('Both are now merged.')

  # Group and Aggregate
  if groupBy:
    df = df.groupby(groupBy)
    print('Aggregating...')
    if aggMethod == 'sum':
      df = sumInts(df)
    else:
      df = sumInts(df)
    print('Aggregated')

  # Create the indicator
  print('Creating Indicator')
  resp = method( df, columnsToInclude)
  print('Indicator Created')
  if finalFileName:
    resp.to_csv(finalFileName, quoting=csv.QUOTE_ALL)
    print('Indicator Saved')

  return resp


# Cell
#@title Run This Cell: Create age5

#Table ID - B01001
#Table Name - Sex by Age
#Indicator Output - Percent of Population Under 5 Years old

def age5( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='027E|003E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['age5_XX']  = ( df.filter(regex='027E|003E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create age18

#Table ID - B01001
#Table Name - Sex by Age
#Indicator Output - Percent of Population 5-17 Years old

def age18( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='004E|005E|006E|028E|029E|030E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                     #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['age18_XX']  = ( df.filter(regex='004E|005E|006E|028E|029E|030E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create age24

#Table ID - B01001
#Table Name - Sex by Age
#Indicator Output - Percent of Population 18-24 Years old

def age24( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='007E|008E|009E|010E|031E|032E|033E|034E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                          #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['age24_XX']  = ( df.filter(regex='007E|008E|009E|010E|031E|032E|033E|034E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create age64

#Table ID - B01001
#Table Name - Sex by Age
#Indicator Output - Percent of Population 25-64 Years old


def age64( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='011|012E|013E|014E|015E|016E|017E|018E|019E|035|036E|037E|038E|039E|040E|041E|042E|043E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                                                          #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['age64_XX']  = ( df.filter(regex='011|012E|013E|014E|015E|016E|017E|018E|019E|035|036E|037E|038E|039E|040E|041E|042E|043E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create age65

#Table ID - B01001
#Table Name - Sex by Age
#Indicator Output - Percent of Population 65 Years and over

def age65( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|020E|021E|022E|023E|024E|025E|044E|045E|046E|047E|048E|049E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                                   #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['age65_XX']  = ( df.filter(regex='020E|021E|022E|023E|024E|025E|044E|045E|046E|047E|048E|049E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create racdiv

#Table ID - B02001
#Table Name - Race
#Indicator Output: Racial Diversity Index
#NOTE: Import 'hisp' script as well, or this script WILL NOT work. This is the only script that uses TWO tables - table 2 (B03002) is called automatically to get the hispanic statistics.

def racdiv(df, columnsToInclude):
  fi = pd.DataFrame()

  #Get hisp table and Indicators
  #'hisp' script HAS to be imported for this script to work.
  #User has to re-enter the year they want the indicator for. Maybe there is a way to automate this input???
  chosen_year = str(input("Please enter your chosen year again (i.e., '17', '20'): "))
  if(int(chosen_year)) <= 19:
    fi_hisp = createAcsIndicator(state = '24', county = '510', tract = '*' , year = chosen_year, tableId = 'B03002',
                      mergeUrl = 'https://raw.githubusercontent.com/BNIA/VitalSigns/main/CSA_2010_and_2020.csv', 
                      merge_left_col = 'tract',
                      merge_right_col = 'TRACTCE',
                      merge_how = 'outer',
                      groupBy = 'CSA2010',
                      aggMethod= 'sum', 
                      method = hisp,
                      columnsToInclude = [],
                      finalFileName=False)
  else:
    fi_hisp = createAcsIndicator(state = '24', county = '510', tract = '*' , year = chosen_year, tableId = 'B03002',
                      mergeUrl = 'https://raw.githubusercontent.com/BNIA/VitalSigns/main/CSA_2010_and_2020.csv', 
                      merge_left_col = 'tract',
                      merge_right_col = 'TRACTCE',
                      merge_how = 'outer',
                      groupBy = 'CSA2020',
                      aggMethod= 'sum', 
                      method = hisp,
                      columnsToInclude = [],
                      finalFileName=False)

  #Column 012E from the Hisp table has a different name on the years prior to 2019. 
  #This  code changes the name of that column automatically for every year prior to 2019.
  if(int(chosen_year)) < 19:
    fi_hisp.rename(columns = {'B03002_012E_Total_Hispanic_or_Latino':'B03002_012E_Total:_Hispanic_or_Latino:'}, inplace = True)

  
  #Append column 12 from table B03002 to table B02001          
  df['B02001_012E_Total_Hispanic_or_Latino'] = fi_hisp['B03002_012E_Total:_Hispanic_or_Latino:']

  columns = df.filter(regex='001E|003E|004E|005E|006E|012E|tract').columns.values  #'tract' HAS to be in this list.
  columns = numpy.append(columns, columnsToInclude)                                
  
  #Get all the race percentages.
  #'tract' is added here so that "Unassigned--Jail" can be removed later.
  fi['White%'] = ( df.filter(regex='002E').sum(axis=1)) / df.filter(regex='001E').sum(axis=1) * 100
  fi['African-American%'] = ( df.filter(regex='003E').sum(axis=1)) / df.filter(regex='001E').sum(axis=1) * 100
  fi['American Indian%'] = ( df.filter(regex='004E').sum(axis=1)) / df.filter(regex='001E').sum(axis=1) * 100
  fi['Asian%'] = ( df.filter(regex='005E').sum(axis=1)) / df.filter(regex='001E').sum(axis=1) * 100
  fi['Native Hawaii/Pac Islander%'] = ( df.filter(regex='006E').sum(axis=1)) / df.filter(regex='001E').sum(axis=1) * 100
  fi['Hisp%'] = ( df.filter(regex='012E').sum(axis=1)) / df.filter(regex='001E').sum(axis=1) * 100
  fi['tract'] = df['tract'] 

  #Get the diversity index
  fi['Diversity_Index'] = (1 -(
      (fi['African-American%'] /100 )**2
      + (fi['White%'] /100 )**2
      + (fi['American Indian%'] /100 )**2
      + (fi['Asian%'] /100 )**2
      + (fi['Native Hawaii/Pac Islander%'] /100 )**2
    )*(
        ( fi['Hisp%'] /100 )**2
        +(1-( fi['Hisp%'] /100) )**2
    ) ) * 100


  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hisp

#Table ID - B03002
#Table Name - Hipanic or Latino Origin by Race
#Indicator Output: Percent of Residents - Hispanic

def hisp( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='012E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hispXX']  = ( df.filter(regex='012E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create paa

#Table ID - B03002
#Table Name - Hipanic or Latino Origin by Race
#Indicator Output: Percent of Residents - Black/African-American (Non-Hispanic)

def paa( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='004E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['paaXX']  = ( df.filter(regex='004E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi

# Cell
#@title Run This Cell: Create pwhite

#Table ID - B03002
#Table Name - Hipanic or Latino Origin by Race
#Indicator Output: Percent of Residents - White/Caucasian (Non-Hispanic)

def pwhite( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='003E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['pwhiteXX']  = ( df.filter(regex='003E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create pasi

#Table ID - B03002
#Table Name - Hipanic or Latino Origin by Race
#Indicator Output: Percent of residents - Asian (Non-Hispanic)

def pasi( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='006E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['pasiXX']  = ( df.filter(regex='006E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create p2more

#Table ID - B03002
#Table Name - Hipanic or Latino Origin by Race
#Indicator Output: Percent of Residents - Two or More Races (Non-Hispanic)

def p2more( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='009E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['p2moreXX']  = ( df.filter(regex='009E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create ppac

#Table ID - B03002
#Table Name - Hipanic or Latino Origin by Race
#Indicator Output: Percent of Residents - All Other Races (Hawaiian/ Pacific Islander, Alaskan/ Native American Other Race) (Non-Hispanic)

def ppac( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='008E|005E|007E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                      #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['ppacXX']  = ( df.filter(regex='008E|005E|007E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create bahigher

#Table ID: B06009
#Table Name: Place of Birth by Educational Attainment in the U.S.
#Indicator Output: Percent Population (25 Years and over) with a Bachelor's Degree or Above

def bahigher( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='005E|006E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['bahigherXX']  = ( df.filter(regex='005E|006E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hsdipl

#Table ID: B06009
#Table Name: Place of Birth by Educational Attainment in the U.S.
#Indicator Output: Percent Population (25 Years and over) With High School Diploma and Some College or Associates Degree

def hsdipl( df, columnsToInclude ):
  fi = pd.DataFrame()
  df.columns = df.columns.str.replace(r"[(]", "")   #Remove parenthesis from column names. - Columns will give an error when this line isnt here.
  df.columns = df.columns.str.replace(r"[)]", "")   #Remove parenthesis from column names. - Columns will give an error when this line isnt here.

  columns = df.filter(regex='003E|004E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hsdiplXX']  = ( df.filter(regex='003E|004E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create lesshs

#Table ID: B06009
#Table Name: Place of Birth by Educational Attainment in the U.S.
#Indicator Output: Percent Population (25 Years and over) With Less Than a High School Diploma or GED

def lesshs( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='002E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['lesshsXX']  = ( df.filter(regex='002').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create carpool

#Table ID: B08101
#Table Name: Means of transportation to work by age
#Indicator Output: Percent of Population that Carpool to Work

def carpool( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|049E|017E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['carpoolXX']  = ( df.filter(regex='017E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='049E').sum(axis=1))) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create drvalone

#Table ID: B08101
#Table Name: Means of transportation to work by age
#Indicator Output: Percent of Population that Drove Alone to Work

def drvalone( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|049E|009E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['drvaloneXX']  = ( df.filter(regex='009E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='049E').sum(axis=1))) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row 
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc
  
  return fi


# Cell
#@title Run This Cell: Create pubtran

#Table ID: B08101
#Table Name: Means of transportation to work by age
#Indicator Output: Percent of Population that Uses Public Transportation to Get to Work

def pubtran( df, columnsToInclude ):
  df.columns = df.columns.str.replace(r"[(]", "")   #Remove parenthesis from column names. - Columns will give an error when this line isnt here.
  df.columns = df.columns.str.replace(r"[)]", "")   #Remove parenthesis from column names. - Columns will give an error when this line isnt here.

  fi = pd.DataFrame()

  columns = df.filter(regex='001E|025E|049E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['pubtranXX']  = ( df.filter(regex='025E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='049E').sum(axis=1))) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row 
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create walked

#Table ID: B08101
#Table Name: Means of transportation to work by age
#Indicator Output: Percent of Population that Walks to Work

def walked( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|049E|033E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['walkedXX']  = ( df.filter(regex='033E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='049E').sum(axis=1))) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row 
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create othercom

#Table ID: B08101
#Table Name: Means of transportation to work by age
#Indicator Output: Percent of Population Using Other Means to Commute to Work (Taxi, Motorcycle, Bicycle, Other)

def othercom( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|049E|041E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['othercomXX']  = ( df.filter(regex='041E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='049E').sum(axis=1))) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row 
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create trav14

#Table ID - B08303
#Table Name - Travel time to work
#Indicator Output - Percent of Employed Population with Travel Time to Work of 0-14 Minutes

def trav14( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|002E|003E|004E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['trav14_XX']  = ( df.filter(regex='002E|003E|004E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create trav29

#Table ID - B08303
#Table Name - Travel time to work
#Indicator Output - Percent of Employed Population with Travel Time to Work of 15-29 Minutes

def trav29( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='005E|006E|007E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['trav29_XX']  = ( df.filter(regex='005E|006E|007E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create trav44

#Table ID - B08303
#Table Name - Travel time to work
#Indicator Output - Percent of Employed Population with Travel Time to Work of 30-44 Minutes 

def trav44( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='008E|009E|010E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['trav44_XX']  = ( df.filter(regex='008E|009E|010E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi

# Cell
#@title Run This Cell: Create trav45

#Table ID - B08303
#Table Name - Travel time to work
#Indicator Output - Percent of Employed Population with Travel Time to Work of 45 Minutes and Over

def trav45( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='011E|012E|013E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['trav45_XX']  = ( df.filter(regex='011E|012E|013E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create novhcl

#Table ID - B08201
#Table Name - Household size by vehicles available
#Indicator Output - Percent of Households with No Vehicles Available

def novhcl( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='002E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['novhclXX']  = ( df.filter(regex='002E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hhs

#Table ID - B11005
#Table Name - Household by Presence of People under 18 years by Household Type
#Indicator Output - Total Number of Households

def hhs( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)       #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hhsXX']  =  df.filter(regex='001E').sum(axis=1)

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create fam

#Table ID - B11005
#Table Name - Household by Presence of People under 18 years by Household Type
#Indicator Output - Percent of Households with Children Under 18

def fam( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='002E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['famXX']  = ( df.filter(regex='002E').sum(axis=1)
) / df.filter(regex='001E').sum(axis=1) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create femhhs

#Table ID - B11005
#Table Name - Household by Presence of People under 18 years by Household Type
#Indicator Output - Percent of Female-Headed Households with Children Under 18

def femhhs( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='007E|011E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['femhhsXX']  = ( df.filter(regex='007E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='011E').sum(axis=1))) * 100

  #Baltimore city is tract 10,000. Since it has a tract number, it was added to the CSA csv file and the code calculated its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
  
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create sclemp

#Table ID: B14005
#Table Name: Sex by School Enrollment by Educational Attainment by Employment Status for the population 16 to 19 years
#Indicator Output: Percentage of Population aged 16-19 in School and/or Employed

def sclemp( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='003E|013E|017E|027E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['sclempXX']  = ( df.filter(regex='003E|009E|013E|017E|023E|027E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hhpov

#Table ID: B17017
#Table Name: Poverty status in the past 12 months by household type by age of householder
#Indicator Output: Percent of Family Households Living Below the Poverty Line

def hhpov( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='003E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                 #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hhpovXX']  = ( df.filter(regex='003E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1) - (df.filter(regex='020E').sum(axis=1)) - (df.filter(regex='049E').sum(axis=1))  #substract non-family households from the total
) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi
  

# Cell
#@title Run This Cell: Create hhchpov

#Table ID: B17001
#Table Name: Poverty status in the past 12 months by sex by age
#Indicator Output: Percent of Children Living Below the Poverty Line

def hhchpov( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='004E|005E|006E|007E|008E|009E|018E|019E|020E|021E|022E|023E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                              #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hhchpovXX']  = ( df.filter(regex='004E|005E|006E|007E|008E|009E|018E|019E|020E|021E|022E|023E').sum(axis=1)
) / ( df.filter(regex='004E|005E|006E|007E|008E|009E|018E|019E|020E|021E|022E|023E|033E|034E|035E|036E|037E|038E|047E|048E|049E|050E|051E|052E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi

# Cell
#@title Run This Cell: Create mhhi

#Table ID: B19001
#Table Name: Household income in the past 12 months
#Indicator Output: Median Household Income

def mhhi( df, columnsToInclude = [] ):
  info = pd.DataFrame(
      [
          ['B19001_002E', 0, 10000],
          ['B19001_003E', 10000, 4999 ],
          ['B19001_004E', 15000, 4999 ],
          ['B19001_005E', 20000, 4999 ],
          ['B19001_006E', 25000, 4999 ],
          ['B19001_007E', 30000, 4999],
          ['B19001_008E', 35000, 4999 ],
          ['B19001_009E', 40000, 4999 ],
          ['B19001_010E', 45000, 4999 ],
          ['B19001_011E', 50000, 9999 ],
          ['B19001_012E', 60000, 14999],
          ['B19001_013E', 75000, 24999 ],
          ['B19001_014E', 100000, 24999 ],
          ['B19001_015E', 125000, 24999 ],
          ['B19001_016E', 150000, 49000 ],
          ['B19001_017E', 200000, 1000000000000000000000000 ],

      ],
      columns=['variable', 'lower', 'range']
  )

  # Final Dataframe
  data_table = pd.DataFrame()
  for index, row in info.iterrows():
      data_table = addKey(df, data_table, row['variable'])

  # Accumulate totals accross the columns.
  # Midpoint: Divide column index 16 (the last column) of the cumulative totals
  temp_table = data_table.cumsum(axis=1)
  temp_table['midpoint'] = (temp_table.iloc[ : , -1 :] /2) # V3
  temp_table['midpoint_index'] = False
  temp_table['midpoint_index_value'] = False # Z3
  temp_table['midpoint_index_lower'] = False # W3
  temp_table['midpoint_index_range'] = False # X3
  temp_table['midpoint_index_minus_one_cumulative_sum'] = False #Y3
  # step 3 - csa_agg3: get the midpoint index by "when midpoint > agg[1] and midpoint <= agg[2] then 2"

  # Get CSA Midpoint Index using the breakpoints in our info table.
  for index, row in temp_table.iterrows():
      # Get the index of the first column where our midpoint is greater than the columns value.
      midpoint = row['midpoint']
      midpoint_index = 0
      # For each column (except the 6 columns we just created)

      # The tracts midpoint was < than the first tracts value at column 'B19001_002E_Total_Less_than_$10,000'
      if( midpoint < int(row[0]) or row[-6] == False ):
        temp_table.loc[ index, 'midpoint_index' ] = 0
      else:
        for column in row.iloc[:-6]:
            # set midpoint index to the column with the highest value possible that is under midpoint
            if( midpoint >= int(column) ):
                if midpoint==False: print (str(column) + ' - ' + str(midpoint))
                temp_table.loc[ index, 'midpoint_index' ] = midpoint_index +1
            midpoint_index += 1

  # temp_table = temp_table.drop('Unassigned--Jail')
  for index, row in temp_table.iterrows():
    temp_table.loc[ index, 'midpoint_index_value' ] = data_table.loc[ index, data_table.columns[row['midpoint_index']] ]
    temp_table.loc[ index, 'midpoint_index_lower' ] = info.loc[ row['midpoint_index'] ]['lower']
    temp_table.loc[ index, 'midpoint_index_range' ] = info.loc[ row['midpoint_index'] ]['range']
    temp_table.loc[ index, 'midpoint_index_minus_one_cumulative_sum'] = row[ row['midpoint_index']-1 ]

  # This is our denominator, which cant be negative.
  for index, row in temp_table.iterrows():
    if row['midpoint_index_value']==False:
      temp_table.at[index, 'midpoint_index_value']=1;

  #~~~~~~~~~~~~~~~
  # Step 3)
  # Run the Calculation
  # Calculation = (midpoint_lower::numeric + (midpoint_range::numeric * ( (midpoint - midpoint_upto_agg) / nullif(midpoint_total,0)
  # Calculation = W3+X3*((V3-Y3)/Z3)

  # v3 -> 1 - midpoint of households  == sum / 2
  # w3 -> 2 - lower limit of the income range containing the midpoint of the housing total == row[lower]
  # x3 -> width of the interval containing the medium == row[range]
  # z3 -> number of hhs within the interval containing the median == row[total]
  # y3 -> 4 - cumulative frequency up to, but no==NOT including the median interval
  #~~~~~~~~~~~~~~~

  def finalCalc(x):
    return ( x['midpoint_index_lower']+ x['midpoint_index_range']*(
      ( x['midpoint']-x['midpoint_index_minus_one_cumulative_sum'])/ x['midpoint_index_value'] )
    )

  temp_table['mhhi'] = temp_table.apply(lambda x: finalCalc(x), axis=1)

  temp_table[columnsToInclude] = df[columnsToInclude]

  #Delete "Unassigned--Jail" row -> remove row where final is equal to zero
  temp_table = temp_table[temp_table.mhhi != 0]
  
  #Move Baltimore City row to the bottom of the list.
  bc = temp_table.loc['Baltimore City'] #save Baltimore City row
  temp_table = temp_table.drop(temp_table.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  temp_table.loc['Baltimore City'] = bc


  return temp_table


# Cell
#@title Run This Cell: Create hh25inc

#Table ID: B19001
#Table Name: Household income in the past 12 months
#Indicator Output: Percent of Households Earning Less than $25,000

def hh25inc( df, columnsToInclude ):
  df.columns = df.columns.str.replace(r"[$]", "")   #Remove dollar sign from column names. - Columns will give an error when this line isnt here.

  fi = pd.DataFrame()

  columns = df.filter(regex='001E|002E|003E|004E|005E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                              #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hh25incXX']  = ( df.filter(regex='002E|003E|004E|005E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hh40inc

#Table ID: B19001
#Table Name: Household income in the past 12 months
#Indicator Output: Percent of Households Earning $25,000 to $40,000

def hh40inc( df, columnsToInclude ):
  df.columns = df.columns.str.replace(r"[$]", "")   #Remove dollar sign from column names. - Columns will give an error when this line isnt here.

  fi = pd.DataFrame()

  columns = df.filter(regex='001E|006E|007E|008E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                              #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hh40incXX']  = ( df.filter(regex='006E|007E|008E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hh60inc

#Table ID: B19001
#Table Name: Household income in the past 12 months
#Indicator Output: Percent of Households Earning $40,000 to $60,000

def hh60inc( df, columnsToInclude ):
  df.columns = df.columns.str.replace(r"[$]", "")   #Remove dollar sign from column names. - Columns will give an error when this line isnt here.

  fi = pd.DataFrame()

  columns = df.filter(regex='001E|009E|010E|011E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                              #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hh60incXX']  = ( df.filter(regex='009E|010E|011E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hh75inc

#Table ID: B19001
#Table Name: Household income in the past 12 months
#Indicator Output: Percent of Households Earning $60,000 to $75,000

def hh75inc( df, columnsToInclude ):
  df.columns = df.columns.str.replace(r"[$]", "")   #Remove dollar sign from column names. - Columns will give an error when this line isnt here.

  fi = pd.DataFrame()

  columns = df.filter(regex='001E|012E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                              #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hh75incXX']  = ( df.filter(regex='012E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create hhm75inc

#Table ID: B19001
#Table Name: Household income in the past 12 months
#Indicator Output: Percent of Households Earning More than $75,000

def hhm75inc( df, columnsToInclude ):
  df.columns = df.columns.str.replace(r"[$]", "")   #Remove dollar sign from column names. - Columns will give an error when this line isnt here.

  fi = pd.DataFrame()

  columns = df.filter(regex='001E|013E|014E|015E|016E|017E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                              #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['hhm75incXX']  = ( df.filter(regex='013E|014E|015E|016E|017E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create unempr

#Table ID: B23001
#Table Name: Sex by age by employment status for the population 16 years and over
#Indicator Output: Unemployment Rate

def unempr( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='006E|013E|020E|027E|034E|041E|048E|055E|062E|069E|092E|099E|106E|113E|120E|127E|134E|141E|148E|155E|008E|015E|022E|029E|036E|043E|050E|057E|064E|071E|094E|101E|108E|115E|122E|129E|136E|143E|150E|157E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                                                                                                                                                                         #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['unemprXX']  = ( df.filter(regex='008E|015E|022E|029E|036E|043E|050E|057E|064E|071E|094E|101E|108E|115E|122E|129E|136E|143E|150E|157E').sum(axis=1)
) / ( df.filter(regex='006E|013E|020E|027E|034E|041E|048E|055E|062E|069E|092E|099E|106E|113E|120E|127E|134E|141E|148E|155E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create empl

#Table ID: B23001
#Table Name: Sex by age by employment status for the population 16 years and over
#Indicator Output: Percent Population 16-64 Employed

def empl( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='128E|135E|142E|149E|156E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                           #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['emplXX']  = ( df.filter(regex='007E|014E|021E|028E|035E|042E|049E|056E|063E|070E|093E|100E|107E|114E|121E|128E|135E|142E|149E|156E').sum(axis=1)
) / ( df.filter(regex='003E|010E|017E|024E|031E|038E|045E|052E|059E|066E|089E|096E|103E|110E|117E|124E|131E|138E|145E|152E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create nilf

#Table ID: B23001
#Table Name: Sex by age by employment status for the population 16 years and over
#Indicator Output: Percent Population 16-64 Not in Labor Force

def nilf( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='009E|016E|023E|030E|037E|044E|051E|058E|065E|072E|095E|102E|109E|116E|123E|130E|137E|144E|151E|158E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                                                                      #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['nilfXX']  = ( df.filter(regex='009E|016E|023E|030E|037E|044E|051E|058E|065E|072E|095E|102E|109E|116E|123E|130E|137E|144E|151E|158E').sum(axis=1)
) / ( df.filter(regex='003E|010E|017E|024E|031E|038E|045E|052E|059E|066E|089E|096E|103E|110E|117E|124E|131E|138E|145E|152E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create unempl

#Table ID: B23001
#Table Name: Sex by age by employment status for the population 16 years and over
#Indicator Output: Percent Population 16-64 Unemployed and Looking for Work

def unempl( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='008E|015E|022E|029E|036E|043E|050E|057E|064E|071E|094E|101E|108E|115E|122E|129E|136E|143E|150E|157E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                                                                                      #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['unemplXX']  = ( df.filter(regex='008E|015E|022E|029E|036E|043E|050E|057E|064E|071E|094E|101E|108E|115E|122E|129E|136E|143E|150E|157E').sum(axis=1)
) / ( df.filter(regex='003E|010E|017E|024E|031E|038E|045E|052E|059E|066E|089E|096E|103E|110E|117E|124E|131E|138E|145E|152E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create elheat

#Table ID: B25040
#Table Name: House heating fuel
#Indicator Output: Percent of Residences Heated by Electricity

def elheat( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='004E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['elheatXX']  = ( df.filter(regex='004E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create heatgas

#Table ID: B25040
#Table Name: House heating fuel
#Indicator Output: Percent of Residences Heated by Utility Gas

def heatgas( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='002E|001E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['heatgasXX']  = ( df.filter(regex='002E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
  
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create affordr

#Table ID: B25070
#Table Name: Gross rent as a percentage of household income in the past 12 months
#Indicator Output: Affordability Index - Rent

def affordr( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|007E|008E|009E|010E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['affordrXX']  = ( df.filter(regex='007E|008E|009E|010E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]
 
  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create affordm

#Table ID: B25091
#Table Name: Mortgage status by selected monthly owner costs as a percentage of household income in the past 12 months
#Indicator Output: Affordability Index - Mortgage

def affordm( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='002E|008E|009E|010E|011E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)            #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['affordmXX']  = ( df.filter(regex='008E|009E|010E|011E').sum(axis=1)
) / ( df.filter(regex='002E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi


# Cell
#@title Run This Cell: Create nohhint

#Table ID: B28002
#Table Name: Presence and types of internet 
#Indicator Output: Percent of Households with No Internet at Home

def nohhint( df, columnsToInclude ):
  fi = pd.DataFrame()

  columns = df.filter(regex='001E|002E|003E|004E|005E|006E|007E|O13E|tract').columns.values  #These are the columns that will show up in the final table (createAcsIndicators) 
  columns = numpy.append(columns, columnsToInclude)                                          #'tract' HAS to be there

  for col in columns:
      fi = addKey(df, fi, col)

  fi['nohhintXX']  = ( df.filter(regex='013E').sum(axis=1)
) / ( df.filter(regex='001E').sum(axis=1)) * 100

  #Baltimore city is tract 10000. Since it has a tract number, it was added to the CSA csv file and the code calculates its 'final' value automatically.
  #Do not remove any row before calculating Baltimore City's 'final,' or the value will be affected.
 
  #Delete "Unassigned--Jail" row -> tract 100300
  fi = fi[fi.tract != 100300]

  #Move Baltimore City row to the bottom of the list.
  bc = fi.loc['Baltimore City'] #save Baltimore City row
  fi = fi.drop(fi.index[1]) #Remove baltimore City row from fi based on index location - its index location is 1 for both 2010 and 2020 indicators.
  fi.loc['Baltimore City'] = bc

  return fi