Pulling ACS 2024 Data

Cleaning Data

I pulled the station’s listed in Bill 260517. Then, I built a buffer zone to use to capture, land use, parcels, and census block groups. The land use data had two and three digit codes for specific land use categories. After going through them, I picked the ones that fit the best with the bill’s language and contextualized them for mapping purposes.

# making all shapefiles in the same projection
groups <- st_transform(groups, 2272)                 
parcel  <- st_transform(parcel, 2272)
transit <- st_transform(transit, 2272)
bikes   <- st_transform(bikes, 2272)
landuse <- st_transform(landuse, 2272)
highspeed <- st_transform(highspeed, 2272)

highspeed <- highspeed %>%
  filter(Route == "L")

toc_zones <- c("Frankford Transportation Center", "Erie-Torresdale","Tioga",
               "Allegheny","Somerset","Huntingdon","Berks", "Spring Garden","46th"  ,"52nd", "56th", "60th", "63rd")

highspeed_toc <- highspeed %>%
  filter(Station %in% toc_zones)

#create a buffer intersect for land use and parcels

highspeed_toc <- highspeed_toc %>%
  mutate(
    neighborhood = case_when(
      Station %in% c("46th", "52nd", "56th", "60th", "63rd") ~ "west",
      TRUE ~ "north"))

highspeed_2272   <- st_transform(highspeed_toc, crs = 2272)
highspeed_buffer <- st_buffer(highspeed_2272, dist = 1320)


parcels_toc <- st_join(parcel, highspeed_buffer, join = st_intersects, left = FALSE) %>% mutate(layer_type = "Parcel")
landuse_toc <- st_join(landuse, highspeed_buffer, join = st_intersects, left = FALSE) %>% mutate(layer_type = "Land Use")
group_toc <- st_join(groups, highspeed_buffer, join = st_intersects, left = FALSE) %>%
  mutate(layer_type = 'Group')

#contextualizing land use
landuse_toc <- landuse_toc %>%
  mutate(
    use_case = case_when(
      c_dig2 == 23  ~ "Commercial Mixed Use",
      c_dig3 == 223 ~ "Other Commercial Mixed Use",
      c_dig3 == 122 ~ "RM1",
      c_dig3 == 123 ~ "RM1",
      c_dig3 == 124 ~ "RM1",
      c_dig3 == 125 ~ "RM1",
      c_dig3 == 129 ~ "RM1",
      c_dig3 == 131 ~ "RM1",
      c_dig2 == 91  ~ "Vacant",
      TRUE ~ NA_character_
    )
  ) 
#removing NAs
landuse_toc <- landuse_toc %>%
  filter(!is.na(use_case))

First Interactive Map

This interactive map allows for you to see what land use categories exist along with the station buffers.

tmap_mode('view')
tm_shape(highspeed_buffer) +
  tm_lines(col = 'red',
           lwd = 1.4) +
tm_shape(landuse_toc) +
  tm_polygons( col = "use_case",
               palette = c(
                 "Commercial Mixed Use"       = "#e41a1c",  # red
                 "Other Commercial Mixed Use" = "#ff7f00",  # orange
                 "RM1"                        = "#377eb8",  # blue
                 "Vacant"                     = "#4daf4a"   # green
               ))

Housing

I made renter and owner mix to get a sense if there are majority renters and owners by station. I exported it as a CSV to edit in Excel because, time-wise, it was faster.

group_toc <- group_toc %>%
  select(GEOID, variable, estimate, NAME, Station, neighborhood) %>%
  pivot_wider(names_from = variable,
              values_from = estimate)

tenuremix <- group_toc %>%
  mutate( own.tenure = (owner/`housing units`) * 100,
          rent.tenure = (renter/`housing units`) * 100)

# I pulled family median income to understand how local median incomes compared to the MSA affordability. Beecause I used 2024 ACS data with 2026 AMI, I discounted the family income by 5% for two years. 
ami = 122700
group_toc <- group_toc %>%
  mutate(
    incratio = ((fammedinc*1.05^2) / ami)*100)

Graphing

The first graph is a count of what type of land use is most common between the northern Philadelphia stations and the western Philadelphia stations. Visually, more parcels exist in the northern neighborhoods for redevelopment. Most noticeably, the western stations have zero residential parcels eligible for re-development. This is something that I would probe a bit more by reconfirming my land use codes.

The t.test and box plot visualize if the family median income-to-AMI ratios were meaningfully different between north Philadelphia and west Philadelphia. The t test shows us that they are not statistically different, but the boxplot reveals more. In the boxplot, we see that the northern neighborhood ratios are more widely spread out compared to the west neighborhood boxplot.

western stations incomes more consistently hover around the 50% AMI of the MSA. Development pressures in the western neighborhoods would be felt more consistently whereas northern development would vary neighborhood to neighborhood. This is where the missing data in the census block group family median income is a critical factor, and I would likely move up to census tract level for further analysis to get a clearer read on how family incomes are distributed across this area.

# Graphing Land Use Parcels
plot_1 <- ggplot(landuse_toc, aes(x = use_case, fill = neighborhood)) +
  geom_bar(position = 'dodge') +
  labs(
    x = "use case",
    y = 'count',
    title = 'Land Use Availability'
  )

print(plot_1)

# T.test to show how family median income ratios by neighborhood compare.
t.test(incratio ~ neighborhood, data = group_toc)
## 
##  Welch Two Sample t-test
## 
## data:  incratio by neighborhood
## t = 1.2624, df = 56.597, p-value = 0.212
## alternative hypothesis: true difference in means between group north and group west is not equal to 0
## 95 percent confidence interval:
##  -6.602506 29.118385
## sample estimates:
## mean in group north  mean in group west 
##            67.29867            56.04073
plot_2 <- ggplot(group_toc, aes(x = neighborhood, y = incratio, fill = neighborhood)) +
  geom_boxplot(outlier.shape = NA, width = 0.5, alpha = 0.7) +
  geom_jitter(width = 0.08, alpha = 0.4, size = 1.5) +
  labs(
    title = "Income-to-AMI Ratio by Neighborhood Group",
    x = NULL,
    y = "Family income as % of MSA AMI"
  ) +
  theme_minimal() +
  theme(legend.position = "none")
print(plot_2)

Housing & Land Use Interactive Map

The following map shows the census block groups with the family median income compared to AMI ratios, the stations, and the land use parcels eligible to be redeveloped. An assumption here is that there will be spatial autocorrelation for the missing census block groups, meaning that the ratios will be similar to surrounding data points.

tmap_mode("view")

tm_shape(group_toc) +
  tm_fill(
    col = "incratio",
    palette = "Blues",
    title = "Family Income to MSA AMI Ratio"
  ) +
  tm_shape(highspeed_buffer) +
  tm_lines(col = 'red',
           lwd = 1.4) +
  tm_shape(landuse_toc) +
  tm_polygons( col = "use_case",
               palette = c(
                 "Commercial Mixed Use"       = "#e41a1c",  # red
                 "Other Commercial Mixed Use" = "#ff7f00",  # orange
                 "RM1"                        = "#377eb8",  # blue
                 "Vacant"                     = "#4daf4a"   # green
               ))