Setup

Introduction

As cities and counties across the country see an influx of population growth, developing rich transit communities that are connected, accessible and integrated into the larger regional context, are becoming crucial when planning for the future. New Jersey’s advantageous location between New York City, and Philadelphia, make Hudson county and Essex county an important potential case study to analyze transit oriented developments(TODs), and understanding if households are willing to pay to be near them. TODs or transit rich areas have the opportunity to better connect citizens to jobs, travel, health care, and education.This memo attempts to analyze and interpret the spatial and social biases that may present themselves when doing this type of analysis and persuade councilmen from Essex and Hudson county on why better, quantitative and qualitative data is needed to better understand the residents’ transit values and needs.

# Hudson County
tracts09_Hud <-  
   get_acs(geography = "tract",
          variables = c("B25026_001E","B02001_002E",
                        "B15001_050E","B15001_009E",
                        "B19013_001E", "B25058_001E",
                        "B06012_002E", "B02001_003E"),
          year=2009, state=34, county = 017, geometry=TRUE)
 
# Essex County
tracts09_Essex <-  
   get_acs(geography = "tract",
          variables = c("B25026_001E","B02001_002E",
                        "B15001_050E","B15001_009E",
                        "B19013_001E", "B25058_001E",
                        "B06012_002E", "B02001_003E"),
          year=2009, state=34, county = 013, geometry=TRUE)

#Bind geographies
tracts09 <- rbind(tracts09_Essex,tracts09_Hud)
## Naming desired Variables
tracts09 <- 
  tracts09 %>%
  dplyr::select( -NAME, -moe) %>%
  spread(variable, estimate) %>%
  rename(TotalPop = B25026_001, 
         Whites = B02001_002,
         FemaleBachelors = B15001_050, 
         MaleBachelors = B15001_009,
         MedHHInc = B19013_001, 
         MedRent = B25058_001,
         TotalPoverty = B06012_002,
         Black_pop = B02001_003)
##Mutating 09 variables
tracts09 <- 
 tracts09 %>%
  mutate(pctWhite = ifelse (TotalPop > 0, Whites / TotalPop, 0),
         pctBachelors = ifelse(TotalPop > 0, ((FemaleBachelors + MaleBachelors) / TotalPop), 0),
         pctPoverty = ifelse(TotalPop > 0, TotalPoverty / TotalPop, 0), 
         pctblack = ifelse(TotalPop > 0, Black_pop / TotalPop, 0),
         year = "2009") %>%
  dplyr::select(-Whites,-FemaleBachelors,-MaleBachelors,-TotalPoverty, -Black_pop)

Wrangling New Jersey Transit Data

Understanding the landscape: Hudson & Essex County

Essex and Hudson county were used for this analysis to better observe regional shifts in demographics, income, and transit needs. For the purpose of this memo, the New Jersey Light Rail system stops data was used but it is important to note that is not the only transit available in the two counties.

ggplot() + 
  geom_sf(data=st_union(tracts09)) +
  geom_sf(data=NJ_Stops,aes(color= LAYER,fill = "orange"))+
  labs(title="NJ Transit Stops, 2009", 
       subtitle="Philadelphia, PA", 
       caption="Figure 1")  + theme_void() +theme(legend.position = "none")

ggplot() + 
  geom_sf(data=st_union(tracts19)) +
  geom_sf(data=NJ_Stops,aes(color= LAYER,fill = "orange"))+
  labs(title="NJ Transit Stops, 2019", 
       subtitle="Philadelphia, PA", 
       caption="Figure 2") +  theme_void()+ theme(legend.position = "none")

ggplot() +
  geom_sf(data=NJBuffers, fill = "white", color = "#a059a0", alpha=.65) +
  geom_sf(data=NJ_Stops, show.legend = "point") +
  facet_wrap(~Legend) + 
  labs(caption = "Figure 3") + theme(legend.position = "none")+ mapTheme()

buffer <- filter(NJBuffers, Legend=="Unioned Buffer")
sf::sf_use_s2(FALSE)

clip <- 
  st_intersection(buffer, tracts09) %>%
  dplyr::select(TotalPop) %>%
  mutate(Selection_Type = "Clip") 

selection1 <- 
  tracts09[buffer,] %>%
  dplyr::select(TotalPop) %>%
  mutate(Selection_Type = "Spatial Selection") 

selectCentroids <-
  st_centroid(tracts09)[buffer,] %>%
  st_drop_geometry() %>%
  left_join(., dplyr::select(tracts09, GEOID), by = "GEOID") %>%
  st_sf() %>%
  dplyr::select(TotalPop) %>%
  mutate(Selection_Type = "Select by Centroids")
#Plotting the results of each method
intersections <- rbind(clip, selection1, selectCentroids)
ggplot() +
  geom_sf(data=st_union(tracts09)) +
  geom_sf(data=intersections, aes(fill = q5(TotalPop), color = NA)) +
  geom_sf(data=NJ_Stops, aes(color = COUNTY)) + 
  scale_fill_manual(values = pallete11,labels = qBr(intersections, "TotalPop"),
                    name = "Population\n(Quintile Breaks)") +
  facet_wrap(~Selection_Type) +
   labs(title="Total Population within 1/2 mi. of light rail", 
       subtitle="3 Spatial Selection Techniques", caption = "Figure 3") +
        guides(color = FALSE)

TOD Indicator Maps

In general, the overall population for both counties remained the same over the decade, with a marginally increase in non-TODs, and an 8% increase in TODs. Black populations living in both TOD and non-TOD areas did see a significant decrease in population of nearly 30%, while the white population did not experience any growth or decline in TOD areas, and a 16 decrease in non-TOD areas.

The percentage of bachelor degree holders did increase in both areas, which could suggest that there is an influx of residents from other parts of the region, or state. This increase in more educated residents could suggest a larger positive association between education attainment and income.

Poverty percentages and household income reveal more insight on non-TOD areas. The rate at which rent increased is not proportional to the rate of household income. While household income for non-TOD areas increased by 20%, household income increased by 20%. This further confirms the assumption about transit rich areas attracting higher earners. While non-TOD earners are not earning as fast at their rent increasing, TOD residents are earning on par to the rent increase.

allTracts.group <- 
  rbind(
    st_centroid(allTracts)[NJBuffers,] %>%
      st_drop_geometry() %>%
      left_join(allTracts) %>%
      st_sf() %>%
      mutate(TOD = "TOD"),
    st_centroid(allTracts)[NJBuffers, op = st_disjoint] %>%
      st_drop_geometry() %>%
      left_join(allTracts) %>%
      st_sf() %>%
      mutate(TOD = "Non-TOD")) %>%
  mutate(MedRent.inf = ifelse(year == "2009", MedRent * 1.19, MedRent)) %>% 
  mutate(pctPoverty.inf= ifelse(year=="2009", pctPoverty* 1.19, pctPoverty)) %>% 
  mutate(pctblack.100=ifelse(year=="2009", pctblack* 100, pctblack)) %>% 
  mutate(pctwhite.100=ifelse(year== "2009", pctWhite*100, pctWhite))

# Time & Space Map

ggplot(allTracts.group)+
  geom_sf(data=st_union(tracts09))+
  geom_sf(aes(fill =TOD))+ 
  facet_wrap(~year)+ 
  scale_fill_manual(values = rev(pallete11))+
  labs(title = "Indicator Differences Across Time & Space") +
  plotTheme() + theme(legend.position="bottom")+
  theme(panel.background = element_rect(fill = "white",
                                colour = "black",aes(alpha = .50),
                                size = 0.5, linetype = "solid"),
  panel.grid.major = element_line(size = 0.5, linetype = 'solid',
                                colour = "white"), 
  panel.grid.minor = element_line(size = 0.25, linetype = 'solid',
                                colour = "white"))

#Percent Black 
    ggplot(allTracts.group) +
    geom_sf(data = st_union(tracts09)) +
    geom_sf(aes(fill = q5(pctblack)), color = "NA") +
    geom_sf(data = st_union(buffer), fill = "NA", color = "black") +
    scale_fill_manual(values = rev(pallete11),
                      labels = qBr(allTracts.group, "pctblack", rnd=F),
                      name = "% Black\n(Quintile Breaks)") +
    labs(title = "Percent Black 2009-2019",  caption = "Figure 4") +
    facet_wrap(~year) +
      mapTheme() + 
    theme(plot.title = element_text(size=22))

# Percent White    
 ggplot(allTracts.group) +
    geom_sf(data = st_union(tracts09)) +
    geom_sf(aes(fill = q5(pctWhite)), color = "NA") +
    geom_sf(data = st_union(buffer), fill = "NA", color = "black") +
    scale_fill_manual(values = rev(pallete11),
                      labels = qBr(allTracts.group, "pctWhite", rnd=F),
                      name = "% White\n(Quintile Breaks)") +
    labs(title = "Percent White 2009-2019",  caption = "Figure 5") +
    facet_wrap(~year) +
    mapTheme() + 
    theme(plot.title = element_text(size=22))

# Percent Poverty Adjusted for Inflation 
  ggplot(allTracts.group) +
    geom_sf(data = st_union(tracts09)) +
    geom_sf(aes(fill = q5(pctPoverty)), color = "NA") +
    geom_sf(data = st_union(buffer), fill = "NA", color = "black") +
    scale_fill_manual(values = rev(pallete11),
                      labels = qBr(allTracts.group, "pctPoverty", rnd=F),
                      name = "% Poverty\n(Quintile Breaks)") +
    labs(title = "Percent Poverty 2009-2010", caption = "Figure 6") +
    facet_wrap(~year) +
    mapTheme() + 
    theme(plot.title = element_text(size=22))

  #Median Household Rent Adjusted for Inflation 
 
 ggplot(allTracts.group) +
    geom_sf(data = st_union(tracts09)) +
    geom_sf(aes(fill = q5(MedRent.inf)), color = "NA") +
    geom_sf(data = buffer, fill = "NA", color = "black")+
    scale_fill_manual(values = rev(pallete11),
                      labels = qBr(allTracts.group, "MedRent.inf"),
                      name = "Rent\n(Quintile Breaks)") +
    labs(title = "Median Household Income 2009-2019", caption = "Figure 7") +
    facet_wrap(~year) +
    mapTheme() + 
    theme(plot.title = element_text(size=22))

TOD Indicator Tables

year TOD Rent Population Percent_White Percent_Bach Percent_Poverty
2009 Non-TOD 944.8665 3607.173 50.05598 1.158553 16.61119
2009 TOD 883.9442 3430.432 47.84318 1.297673 19.51298
2019 Non-TOD 1294.1798 3818.367 46.73237 1.316386 16.74749
2019 TOD 1238.9362 3728.096 47.57971 1.435621 18.87712

Table 8
Variable 2009: Non-TOD 2009: TOD 2019: Non-TOD 2019: TOD
Percent_Bach 1.16 1.30 1.32 1.44
Percent_Poverty 16.61 19.51 16.75 18.88
Percent_White 50.06 47.84 46.73 47.58
Population 3607.17 3430.43 3818.37 3728.10
Rent 944.87 883.94 1294.18 1238.94

Table 9

TOD Indicator Plots

Although there are slight associations between non, TODs, and TOD regions and the various variables chosen, both counties experiences similar trends in most categories.

ggplotly(allTracts.Summary %>%
  gather(Variable, Value, -year, -TOD) %>%
  ggplot(aes(year, Value, fill = TOD)) +
  geom_bar(stat = "identity", position = "dodge", alpha=0.55, color="white") +
  facet_wrap(~Variable, scales = "free", ncol=5) +
  scale_fill_manual(values =c("#a059a0", "#fac484","#fac484","#f8a07e"))+
  labs(title = "Indicator Differences Across Time & Space"))

Multiple Ring Buffer

sf::sf_use_s2(FALSE)
ggplot() +
    geom_sf(data=CT_MRB2) +
    geom_sf(data=NJ_Stops_MRB_3, size=1, aes(color= LAYER)) +
    geom_sf(data=st_union(tracts19), fill=NA, size=1.2) 

    labs(title="Half mile buffers", subtittle = " ", caption = "Figure 10")+
    mapTheme() + theme(plot.title = element_text(size=22))

Rent as a Function of Distance to Light Rail Stops

The graph below visualizes the relationship between rent and distance from the NJ Light rail station stops between 2009-2019. In 2009, indicated in purple, and 2019, indicated in orange; both years follow a similar trend of the closer to transit rich areas the higher the rent is. Rent in areas closer to TOD areas for both years were roughly around $1150. In 2019 rent increased significantly , which reflects larger trends of rent increases across the sate, while rent increased at a slower rate in 2009 the further away from the light rail station. One could assume that the further out residents live, the higher cost of living there is. Although those regions are non-TODs it is hard to say if they value TODs less, they may just have access to other types of transit, and moved farther away due to other factors that were not look at during this research period

Graduated Symbol Map

The final two maps represent quantities for each light rain stations proportionally, as a function of both population and rent in 2009.

Conclusion

The New Jersey Light Rail system services thousands of riders every single day with a current ridership of 13,828,00. A county’s like Hudson and Essex increase in population density, there is opportunity to expand the regions transit connectivity. Other cities like New Brunswick, and Newark are becoming smart mobility hubs where multi-modal transit is being tested and optimized to fit the needs of all types of residents. This initial surface level analysis lets us know that although the region is rather connected, there are still ways to provide equitable access to transit for everyone. There are two policy recommendation that I think would provide a better understating of your transit users:

Housing/Rent Affordability: From my research, the increased in rent, and slower increased rates of income in both non-TODs and TODs tells us that we cannot confidently decipher how residents are valuing TODs vs other areas lacking amenities. As rent continues to skyrocket it is difficult to say if residents are factoring in TOD areas as places to live because they value them or simply because the rent is more affordable. Other factors and datasets are needed to truly assess if residents value transit rich amenities, like quality of school districts,income, healthy food options, and adequate health care facilities are all needed to give a more comprehensive conclusion.

County-wide Transit Survey Program: Getting a better understanding of what residents value in transit, and how they use could potentially help the city better promote TOD areas. If the city is aware of how residents view TODs and their barriers to not living near one or in one, we can better address those hurdles and create a cultural shift on the benefits of TODs. Although this is no easy feat,it can lead to achieving long term goals, like implementation of new zoning overlays, better targeted promotions of TODs, and more robust indicators that better represent the needs and values of Hudson & Essex County.