# Gentrification 2014 - 2024 # Michael Minn # 18 May 2026 library(sf) # Load tracts tracts = st_read("2020-2024-acs-tracts.geojson") tracts = tracts[, c("GEOIDFQ", "ST", "Name", "Total_Population", "Percent_Bachelors_Degree", "Percent_Jobs_Management", "Median_Household_Income", "Median_Home_Value", "Median_Monthly_Rent", "geometry")] tract_centroids = st_centroid(tracts) tract_centroids = tract_centroids[tract_centroids$Total_Population > 50,] # Spatial join to get 2014 data tracts_2014 = st_read("2010-2014-acs-tracts.geojson") tracts_2014 = tracts_2014[, c("Percent_Bachelors_Degree", "Percent_Jobs_Management", "Median_Household_Income", "Median_Home_Value", "Median_Monthly_Rent", "geometry")] names(tracts_2014) = c("Percent_Bachelors_Degree_2014", "Percent_Jobs_Management_2014", "Median_Household_Income_2014", "Median_Home_Value_2014", "Median_Monthly_Rent_2014", "geometry") tract_centroids = st_join(tract_centroids, tracts_2014) tracts = merge(tracts, st_drop_geometry(tract_centroids[, c("GEOIDFQ", "Percent_Bachelors_Degree_2014", "Percent_Jobs_Management_2014", "Median_Household_Income_2014", "Median_Home_Value_2014", "Median_Monthly_Rent_2014")]), all.x=T) # Aggregate to get county values tracts$County_GEOIDFQ = sub("1400000US", "0500000US", substr(tracts$GEOIDFQ, 1, 14)) tract_centroids = st_centroid(tracts) x = aggregate(tract_centroids$Percent_Bachelors_Degree_2014, list(tract_centroids$County_GEOIDFQ), function(x) median(x, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Bachelors_2014") county_change = x x = aggregate(tract_centroids$Percent_Jobs_Management_2014, list(tract_centroids$County_GEOIDFQ), function(x) median(x, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Management_2014") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Household_Income_2014, list(tract_centroids$County_GEOIDFQ), function(x) median(x, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Income_2014") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Household_Income_2014, list(tract_centroids$County_GEOIDFQ), function(x) quantile(x, probs=0.40, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Income_40pct_2014") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Household_Income_2014, list(tract_centroids$County_GEOIDFQ), function(x) quantile(x, probs=0.75, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Income_75pct_2014") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Percent_Bachelors_Degree - tract_centroids$Percent_Bachelors_Degree_2014, list(tract_centroids$County_GEOIDFQ), function(x) median(x, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Bachelor_Change") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Home_Value - tract_centroids$Median_Home_Value_2014, list(tract_centroids$County_GEOIDFQ), function(x) median(x, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Value_Change") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Home_Value - tract_centroids$Median_Home_Value_2014, list(tract_centroids$County_GEOIDFQ), function(x) quantile(x, probs=0.75, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Value_Change_75pct") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Monthly_Rent - tract_centroids$Median_Monthly_Rent_2014, list(tract_centroids$County_GEOIDFQ), function(x) median(x, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Rent_Change") county_change = merge(county_change, x, all=T) x = aggregate(tract_centroids$Median_Monthly_Rent - tract_centroids$Median_Monthly_Rent_2014, list(tract_centroids$County_GEOIDFQ), function(x) quantile(x, probs=0.75, na.rm=T)) names(x) = c("County_GEOIDFQ", "County_Rent_Change_75pct") county_change = merge(county_change, x, all=T) tracts = merge(tracts, county_change, all.x=T) # County polygons for display counties = st_read("2020-2024-acs-counties.geojson") counties = counties[,c("GEOIDFQ", "ST", "Percent_Jobs_Management", "Percent_Bachelors_Degree", "Median_Household_Income", "geometry")] names(county_change)[1] = "GEOIDFQ" counties = merge(counties, county_change) counties$SSI = counties$Percent_Jobs_Management + counties$Percent_Bachelors_Degree + log(counties$Median_Household_Income) counties$SSI_2014 = counties$County_Management_2014 + counties$County_Bachelors_2014 + log(counties$County_Income_2014) counties$SSI_Change = counties$SSI - counties$SSI_2014 st_write(counties, "2024-gentrification-counties.geojson", delete_dsn=T) # Gentrification classification tracts$Rent_Change = tracts$Median_Monthly_Rent - tracts$Median_Monthly_Rent_2014 tracts$Home_Value_Change = tracts$Median_Home_Value - tracts$Median_Home_Value_2014 tracts$Bachelor_Change = tracts$Percent_Bachelors_Degree - tracts$Percent_Bachelors_Degree_2014 # NYU Furman Center. 2016. “State of New York City’s Housing and Neighborhoods in 2015.” # Updated 9 May. https://furmancenter.org/research/sonychan/2015-report. tracts$Gentrified_Furman = ifelse(tracts$Median_Household_Income_2014 >= tracts$County_Income_40pct_2014, "Higher-Income", ifelse(tracts$Rent_Change >= tracts$County_Rent_Change, "Gentrifying", "Non-Gentrifying")) # Ding, Lei, Jackelyn Hwang, and Eileen Divringi. 2016. # "Gentrification and Residential Mobility in Philadelphia." # Regional Science and Urban Economics 61: 38-51. # https://doi.org/10.1016/j.regsciurbeco.2016.09.004. names(x) = c("County_GEOIDFQ", "County_Income_75pct_2014") tracts$Gentrified_Ding = ifelse(tracts$Median_Household_Income_2014 >= tracts$County_Income_75pct_2014, "Ineligible", ifelse(tracts$Bachelor_Change < tracts$County_Bachelor_Change, "Non-Gentrifying", ifelse(tracts$Rent_Change > tracts$County_Rent_Change_75pct, "Intense", ifelse(tracts$Rent_Change > tracts$County_Rent_Change, "Gentrifying", ifelse(tracts$Home_Value_Change > tracts$County_Value_Change_75pct, "Intense", ifelse(tracts$Home_Value_Change > tracts$County_Value_Change, "Gentrifying", "Non-Gentrifying")))))) # Yonto, Daniel, and Claire Schuch. 2020. # “Developing and Ground-Truthing Multi-Scalar Approaches to Mapping Gentrification.” # Papers in Applied Geography 6 (4): 352–68. https://doi.org/10.1080/23754931.2020.1789499. tracts$SSI = round(tracts$Percent_Jobs_Management + tracts$Percent_Bachelors_Degree + log(tracts$Median_Household_Income), 2) tracts$SSI_2014 = round(tracts$Percent_Jobs_Management_2014 + tracts$Percent_Bachelors_Degree_2014 + log(tracts$Median_Household_Income_2014), 2) tracts$SSI_Change = tracts$SSI - tracts$SSI_2014 st_write(tracts, "2024-gentrification-tracts.geojson", delete_dsn=T)