Blog Post Instructions

Preliminary results (500 - 750 words, 1-2 tables, 1-2 figures). This is where you will describe the preliminary results of your project. Here you will describe the justification of which techniques you used, and describe the preliminary results of your analysis based on the procedures you conducted.

Identifying Gentrification in San Antonio, Bexar County with GIS

Research Questions

This study utilizes data from the American Community Survey (ACS), made available by the U.S. Census Bureau. Five-year estimates of the percentage of total population by Black, Hispanic, and white racial/ethnic groups, level of education, and median household income in 2009 and 2019 were referenced to investigate the following research questions:

  • What are the geospatial relationships between changes in racial/ethnic composition, educational attainment, household poverty status and median household income over time between 2009 and 2019 in Bexar County at the census tract level?

  • How do the relationships between socioeconomic indicators at the census tract level relate to qualitatively and quantitatively observed gentrification patterns in San Antonio?

Data and Methods

Using change mapping techniques, four socioeconomic indicators: racial/ethnic composition, educational attainment, household poverty status, and median household income level were compared between two 5-year data collection spans– 2005-09 and 2014-2019– by Bexar County census tracts. The generated maps in this study compare changing racial/ethnic, education, and housing patterns over the last decade in Bexar County to investigate the impacts of gentrification on residential shifts across the county. These maps provide a geospatial data visualization of the analysis to examine demographic and socioeconomic trends between 2009 and 2019 by census tract.

This study will measure the spatial autocorrelation of census tracts by poverty level and household median income to test whether certain neighboring census tracts are negatively-autocorrelated, offering evidence for gentrifying neighborhoods with developed tracts neighbored by tracts with lower levels of development or access to resources.

A secondary comparative analysis of data in the Housing Affordability Data System (HADS) published by the U.S. Department of Housing and Development will compliment the GIS processes accomplished in this study. This report will compare housing cost burden (a household’s monthly housing cost divided by its monthly income) for owner and renter households from 2010 and 2019 to examine housing affordability and cost burden trends for households in Bexar County.

Results

According to the change map examining poverty rates between 2009 and 2019 5-year ACS estimates, 29 census tracts demonstrated significant increase in poverty rate.

(Change maps will be generated on the basis of median household income and education.) see maps below

Appendix

The following R code was used to produce the results examined in this study:

#load libraries
library(tidycensus)
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5     v purrr   0.3.4
## v tibble  3.1.6     v dplyr   1.0.7
## v tidyr   1.1.4     v stringr 1.4.0
## v readr   2.1.1     v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(sf)
## Linking to GEOS 3.9.1, GDAL 3.2.1, PROJ 7.2.1; sf_use_s2() is TRUE
library(tmap)

#install api key
census_api_key(key= "d42eebdfb8a5be15b37eb8cef2a3abc37a71f12b", install=T, overwrite=T)
## Your original .Renviron will be backed up and stored in your R HOME directory if needed.
## Your API key has been stored in your .Renviron and can be accessed by Sys.getenv("CENSUS_API_KEY"). 
## To use now, restart R or run `readRenviron("~/.Renviron")`

The following code will be used to extract ACS data from the Census Bureau using a researcher-unique API key:

#download acs data from census api

v2009_Profile = load_variables(2009,
                       "acs5/profile",
                       cache=T)

v2019_Profile = load_variables(2019,
                               "acs5/profile",
                               cache=T)
#search for variables using grep()
v2009_Profile[grep(x = v2009_Profile$label,
                   "education",
                   ignore.case = T),
              c("name", "label")]

v2019_Profile[grep(x = v2019_Profile$label,
                   "poverty",
                   ignore.case = T),
              c("name", "label")]

Below is an example of the change mapping technique applied to household median income for comparing 2005-09 estimates to that of 2016-20. Here, estimates for household median income by tract are derived from the 2005-09 ACS and compared to the estimates from the 2016-20 ACS.

#extracting acs summary file data profile variables from 2005 and 2020.
bexar_acs.09 = get_acs(geography = "tract",
                state = "048",
                county = "029",
                year = 2009,
                variables = c("DP03_0103", "DP03_0063", "DP05_0072P", "DP05_0073P", "DP05_0066P", "DP02_0067"),
                geometry = T,
                output = "wide")
## Getting data from the 2005-2009 5-year ACS
## Downloading feature geometry from the Census website.  To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.
## Using the ACS Data Profile
bexar_acs.09_2 = bexar_acs.09 %>% 
  mutate(pct_poverty = DP03_0103E,
         pct_poverty.er = DP03_0103M/1.645,
         pct_poverty.cv = 100*(pct_poverty.er/pct_poverty)) %>% 
  mutate(med_inc = DP03_0063E,
         med_inc.er = DP03_0063M/1.645,
         med_inc.cv = 100*(med_inc.er/med_inc)) %>%
  mutate(pct_white = DP05_0072PE,
         pct_white.er = DP05_0072PM/1.645,
         pct_white.cv = 100*(pct_white.er/pct_white)) %>% 
  mutate(pct_black = DP05_0073PE,
         pct_black.er = DP05_0073PM/1.645,
         pct_black.cv = 100*(pct_black.er/pct_black)) %>% 
  mutate(pct_hisp = DP05_0066PE,
         pct_hisp.er = DP05_0066PM/1.645,
         pct_hisp.cv = 100*(pct_hisp.er/pct_hisp)) %>% 
  mutate(pct_educ = DP02_0067E,
         pct_educ.er = DP02_0067M/1.645,
         pct_educ.cv = 100*(pct_educ.er/pct_educ)) %>% 
  filter(complete.cases(pct_poverty, med_inc, pct_white, pct_black, pct_hisp, pct_educ)) %>% 
  select(GEOID, pct_poverty, pct_poverty.er, pct_poverty.cv, med_inc, med_inc.er, med_inc.cv, pct_white, pct_white.er, pct_white.cv, pct_black, pct_black.er, pct_black.cv, pct_hisp, pct_hisp.er, pct_hisp.cv, pct_educ, pct_educ.er, pct_educ.cv)

head(bexar_acs.09)


bexar_acs.19 = get_acs(geography = "tract",
                state = "048",
                county = "029",
                year = 2019,
                variables = c("DP03_0119P", "DP03_0062", "DP05_0077P", "DP05_0078P", "DP05_0071P", "DP02_0068P"),
                geometry = T,
                output = "wide")
## Getting data from the 2015-2019 5-year ACS
## Downloading feature geometry from the Census website.  To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.
## Using the ACS Data Profile
bexar_acs.19_2 = bexar_acs.19 %>% 
  mutate(pct_poverty = DP03_0119PE,
         pct_poverty.er = DP03_0119PM/1.645,
         pct_poverty.cv = 100*(pct_poverty.er/pct_poverty)) %>% 
  mutate(med_inc = DP03_0062E,
         med_inc.er = DP03_0062M/1.645,
         med_inc.cv = 100*(med_inc.er/med_inc)) %>%
  mutate(pct_white = DP05_0077PE,
         pct_white.er = DP05_0077PM/1.645,
         pct_white.cv = 100*(pct_white.er/pct_white)) %>% 
  mutate(pct_black = DP05_0078PE,
         pct_black.er = DP05_0078PM/1.645,
         pct_black.cv = 100*(pct_black.er/pct_black)) %>% 
  mutate(pct_hisp = DP05_0071PE,
         pct_hisp.er = DP05_0071PM/1.645,
         pct_hisp.cv = 100*(pct_hisp.er/pct_hisp)) %>% 
  mutate(pct_educ = DP02_0068PE,
         pct_educ.er = DP02_0068PE/1.645,
         pct_educ.cv = 100*(pct_educ.er/pct_educ)) %>% 
  filter(complete.cases(pct_poverty, med_inc, pct_white, pct_black, pct_hisp, pct_educ)) %>% 
  select(GEOID, pct_poverty, pct_poverty.er, pct_poverty.cv, med_inc, med_inc.er, med_inc.cv, pct_white, pct_white.er, pct_white.cv, pct_black, pct_black.er, pct_black.cv, pct_hisp, pct_hisp.er, pct_hisp.cv, pct_educ, pct_educ.er, pct_educ.cv)

head(bexar_acs.19_2)
##2009

#poverty
tm_shape(bexar_acs.09_2)+
  tm_polygons(c("pct_poverty"),
              title=c("Percentage of Families in Poverty"),
              palette="YlOrRd",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Family Poverty in Bexar County, Texas - Quantile Breaks (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#median income
tm_shape(bexar_acs.09_2)+
  tm_polygons(c("med_inc"),
              title=c("Median Income Level"),
              palette="PuBuGn",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Household Median Income, Bexar County, Texas - Quantile Breaks (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#education
tm_shape(bexar_acs.09_2)+
  tm_polygons(c("pct_educ"),
              title=c("Percentage of Residents 25 Years or Older"),
              palette="YlGnBu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Percentage of Bexar County Residents with a Bachelors Degree or Higher (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#race/ethnicity
tm_shape(bexar_acs.09_2)+
  tm_polygons(c("pct_black"),
              title=c("Percentage of Non-Hispanic Black Residents"),
              palette="RdPu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Bexar County Residents by Race/Ethnicity (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

tm_shape(bexar_acs.09_2)+
  tm_polygons(c("pct_hisp"),
              title=c("Percentage of Latinx Residents"),
              palette="RdPu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Bexar County Residents by Race/Ethnicity (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

tm_shape(bexar_acs.09_2)+
  tm_polygons(c("pct_white"),
              title=c("Percentage of Non-Hispanic White Residents"),
              palette="RdPu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Bexar County Residents by Race/Ethnicity (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

##2019

#poverty
tm_shape(bexar_acs.19_2)+
  tm_polygons(c("pct_poverty"),
              title=c("Percentage of Families in Poverty"),
              palette="YlOrRd",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Family Poverty in Bexar County, Texas - Quantile Breaks (2019)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#median income
tm_shape(bexar_acs.19_2)+
  tm_polygons(c("med_inc"),
              title=c("Median Income Level"),
              palette="PuBuGn",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Household Median Income, Bexar County, Texas - Quantile Breaks (2019)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#education
tm_shape(bexar_acs.19_2)+
  tm_polygons(c("pct_educ"),
              title=c("Percentage of Residents 25 Years or Older"),
              palette="YlGnBu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Percentage of Bexar County Residents with a Bachelors Degree or Higher (2019)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#race/ethnicity
tm_shape(bexar_acs.19_2)+
  tm_polygons(c("pct_black"),
              title=c("Percentage of Non-Hispanic Black Residents"),
              palette="RdPu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Bexar County Residents by Race/Ethnicity (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

tm_shape(bexar_acs.19_2)+
  tm_polygons(c("pct_hisp"),
              title=c("Percentage of Latinx Residents"),
              palette="RdPu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Bexar County Residents by Race/Ethnicity (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

tm_shape(bexar_acs.19_2)+
  tm_polygons(c("pct_white"),
              title=c("Percentage of Non-Hispanic White Residents"),
              palette="RdPu",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Bexar County Residents by Race/Ethnicity (2009)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))

#merge data
st_geometry(bexar_acs.09_2)=NULL

mdat = left_join(bexar_acs.09_2, bexar_acs.19_2, by=c("GEOID"="GEOID"))

head(mdat)
acstest = function(names, geoid, est1, err1, est2, err2, alpha, yr1, yr2, span)
  {
  se1 = err1/qnorm(.90)
  se2 = err2/qnorm(.90)
  yrs1 = seq(yr1, to=yr1-span)
  yrs2 = seq(yr2, to=yr2-span)

  C = mean(yrs2%in%yrs1)
  diff = (est1-est2)
  test = (est1-est2) / (sqrt(1-C)*sqrt(se1^2+se2^2))
  crit = qnorm(1-alpha/2)
  pval = 1-pnorm(abs(test))
  result = NULL
  result[pval > alpha] = "insignificant change"
  result[pval < alpha & test < 0] = "significant increase"
  result[pval < alpha & test > 0] = "significant decrease" 
  
  data.frame(name=names,geoid=geoid, est1=est1, est2=est2, se1=se1, se2=se2,difference=diff, test=test, result=result, pval=pval)
}
mdat$signif = significance(est1=mdat$pct_poverty.x,
                           est2=mdat$pct_poverty.y,
                           moe1=mdat$pct_poverty.er.x,
                           moe2 = mdat$pct_poverty.er.y,
                           clevel = .9)

diff09_19 = acstest(names = mdat$GEOID,
                    geoid = mdat$GEOID,
                    est1 = mdat$pct_poverty.x,
                    est2 = mdat$pct_poverty.y,
                    err1 = mdat$pct_poverty.er.x,
                    err2=mdat$pct_poverty.er.y,
                    alpha = .1,
                    yr1 = 2009, yr2 = 2019,
                    span = 5)

table(diff09_19$result)
acs_merge = left_join(mdat, diff09_19, by=c("GEOID"="geoid"))

tmap_mode("plot")
## tmap mode set to plotting
map_09 = tm_shape(acs_merge)+
  tm_polygons(c("pct_poverty.x"),
              title=c("Percentage of Families in Poverty"),
              palette="PuBuGn",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Family Poverty in Bexar County, Texas - Quantile Breaks (2009)",
            title.size =1.5,
            
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))+
  tm_credits("Source: 2005-09 ACS 5-Year Estimates")

map_19 = tm_shape(acs_merge)+
  tm_polygons(c("pct_poverty.y"),
              title=c("Percentage of Families in Poverty"),
              palette="PuBuGn",
              style="quantile",
              n=7)+
  tm_scale_bar()+
  tm_layout(title="Family Poverty in Bexar County, Texas - Quantile Breaks (2019)",
            title.size =1.5,
            legend.frame = TRUE,
            title.position = c('right', 'top'))+
  tm_compass()+
  tm_format("World",
            legend.position =  c("left", "bottom"),
            main.title.position =c("center"))+
   tm_credits("Source: 2016-20 ACS 5-Year Estimates")

#tmap_arrange(map_09, map_19, map_merge, nrow = 2)