R Markdown

This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see http://rmarkdown.rstudio.com.

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

# Libraries
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.0, PROJ 9.6.0; sf_use_s2() is TRUE
library(tmap)
library(tidycensus)
library(janitor)
## 
## Attaching package: 'janitor'
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
library(stringr)

Instructions

In this assignment, you will examine the spatial distribution of hospitals in Metro Atlanta and explore how it relates to various socioeconomic factors. The goal is to better understand potential inequities in healthcare access across neighborhoods and sociodemographic groups. The definition of Metro Atlanta varies – in this assignment, we use the following 11 counties: Cherokee, Clayton, Cobb, DeKalb, Douglas, Fayette, Forsyth, Fulton, Gwinnett, Henry, and Rockdale.

You will use hospital POI data along with Census ACS data. Select relevant variables from the ACS, conduct exploratory data analysis with these two datasets, and share your findings. Be sure to address the guiding question: Is the spatial distribution of hospitals in Metro Atlanta equitable?

#Equity vs. Equality

Equity recognizes that each group of people has different circumstances/demands and allocates resources/opportunities accordingly.

Equality means each group of people is given the same resources or opportunities.

Directions

  1. Import the hospital POI data and make sure it is tidy and ready for analysis.

  2. Explore variables in the Census ACS 5-year estimates, carefully select those that are relevant for an equity analysis, and provide justification for each variable you select. Think about how each variable captures different circumstances and needs for healthcare.

  3. Download ACS data for the selected variables at the Census Tract level for the 11 counties using the tidycensus.

  4. Prepare the data for analysis: Check for missing values and handle them appropriately. Create new variables if needed (e.g., proportions, densities). Join the POI data with the ACS data. Ensure coordinate reference systems (CRS) are appropriate for distance calculations.

  5. Define and compute your operational measure of healthcare access (the dependent variable). Identify suitable metric(s) and justify your choices. Example metrics include: The number of hospitals within X miles. The presence of a hospital within X miles. The distance to the nearest hospital. The average distance to the X nearest hospitals. Compute your chosen measure(s).

  6. Analyze the spatial distribution of hospitals from an equity perspective: Conduct exploratory data analysis and present at least two graphs and at least two maps. Fit appropriate regression model(s) to test associations between healthcare access and socioeconomic factors. Conclude with your verdict: “Is the spatial distribution of hospitals in Metro Atlanta equitable?”

1. Importing and tidying hospital POI data

# Load hospital data
geojson_url <- "https://raw.githubusercontent.com/ujhwang/urban-analytics-2025/main/Assignment/mini_3/hospital_11counties.geojson"

hospitals <- st_read(geojson_url) %>%
  janitor::clean_names() %>%
  distinct(id, .keep_all = TRUE) %>%
  filter(!st_is_empty(geometry)) %>%
  st_transform(32616) %>% st_make_valid()  # projected CRS
## Reading layer `hospital_11counties' from data source 
##   `https://raw.githubusercontent.com/ujhwang/urban-analytics-2025/main/Assignment/mini_3/hospital_11counties.geojson' 
##   using driver `GeoJSON'
## Simple feature collection with 119 features and 8 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -84.73147 ymin: 33.42719 xmax: -83.92052 ymax: 34.24585
## Geodetic CRS:  WGS 84

2. Census ACS 5-year estimates

The following variable were selected based on its relevance to equity analysis;

  1. Total Population. This is needed to calculate hospitals per capita or normalize access metrics.
  2. Median household income. Lower income can limit transportation access and ability to afford care; proxy for economic vulnerability.
  3. population below poverty. Captures financial barriers and broader social vulnerability.
  4. Households without a vehicle. Directly influences ability to reach healthcare facilities, especially in low-transit areas.
  5. Disability status. People with disabilities may face mobility and care access challenges.

3. Downloading ACS data for the selected variables at the Census Tract level for the 11 counties

# Load ACS tract data
counties <- c("Cherokee","Clayton","Cobb","DeKalb","Douglas","Fayette",
              "Forsyth","Fulton","Gwinnett","Henry","Rockdale")
acs_vars <- c(
  total_pop   = "B01003_001",
  med_income  = "B19013_001",
  pov_total   = "B17001_001",
  pov_below   = "B17001_002",
  no_vehicle  = "B08201_002",
  total_hh    = "B08201_001",
  disability  = "B18135_001"
)

acs_data <- get_acs(
  geography = "tract",
  state = "GA",
  county = counties,
  variables = acs_vars,
  year = 2022,
  geometry = TRUE,
  output = "wide"
) %>%
  st_transform(32616) %>% st_make_valid() %>%
  mutate(
    poverty_rate = (pov_belowE / pov_totalE) * 100,
    pct_no_vehicle = (no_vehicleE / total_hhE) * 100,
    pop_density = total_popE / as.numeric(st_area(geometry)) * 1e6
  )
## Getting data from the 2018-2022 5-year ACS
## Downloading feature geometry from the Census website.  To cache shapefiles for use in future sessions, set `options(tigris_use_cache = TRUE)`.
##   |                                                                              |                                                                      |   0%  |                                                                              |=                                                                     |   1%  |                                                                              |=                                                                     |   2%  |                                                                              |==                                                                    |   2%  |                                                                              |==                                                                    |   3%  |                                                                              |==                                                                    |   4%  |                                                                              |===                                                                   |   4%  |                                                                              |===                                                                   |   5%  |                                                                              |====                                                                  |   5%  |                                                                              |====                                                                  |   6%  |                                                                              |=====                                                                 |   6%  |                                                                              |=====                                                                 |   7%  |                                                                              |=====                                                                 |   8%  |                                                                              |======                                                                |   8%  |                                                                              |=======                                                               |   9%  |                                                                              |=======                                                               |  10%  |                                                                              |=======                                                               |  11%  |                                                                              |========                                                              |  11%  |                                                                              |=========                                                             |  12%  |                                                                              |=========                                                             |  13%  |                                                                              |==========                                                            |  14%  |                                                                              |===========                                                           |  15%  |                                                                              |===========                                                           |  16%  |                                                                              |============                                                          |  17%  |                                                                              |=============                                                         |  18%  |                                                                              |=============                                                         |  19%  |                                                                              |==============                                                        |  20%  |                                                                              |===============                                                       |  21%  |                                                                              |===============                                                       |  22%  |                                                                              |================                                                      |  22%  |                                                                              |================                                                      |  23%  |                                                                              |=================                                                     |  24%  |                                                                              |=================                                                     |  25%  |                                                                              |==================                                                    |  25%  |                                                                              |==================                                                    |  26%  |                                                                              |===================                                                   |  27%  |                                                                              |===================                                                   |  28%  |                                                                              |====================                                                  |  28%  |                                                                              |====================                                                  |  29%  |                                                                              |=====================                                                 |  30%  |                                                                              |=====================                                                 |  31%  |                                                                              |======================                                                |  32%  |                                                                              |=======================                                               |  33%  |                                                                              |========================                                              |  34%  |                                                                              |========================                                              |  35%  |                                                                              |=========================                                             |  36%  |                                                                              |==========================                                            |  37%  |                                                                              |==========================                                            |  38%  |                                                                              |===========================                                           |  39%  |                                                                              |============================                                          |  39%  |                                                                              |============================                                          |  40%  |                                                                              |=============================                                         |  41%  |                                                                              |=============================                                         |  42%  |                                                                              |==============================                                        |  43%  |                                                                              |===============================                                       |  44%  |                                                                              |===============================                                       |  45%  |                                                                              |================================                                      |  45%  |                                                                              |================================                                      |  46%  |                                                                              |=================================                                     |  47%  |                                                                              |=================================                                     |  48%  |                                                                              |==================================                                    |  48%  |                                                                              |==================================                                    |  49%  |                                                                              |===================================                                   |  50%  |                                                                              |===================================                                   |  51%  |                                                                              |====================================                                  |  52%  |                                                                              |=====================================                                 |  52%  |                                                                              |=====================================                                 |  53%  |                                                                              |======================================                                |  54%  |                                                                              |======================================                                |  55%  |                                                                              |=======================================                               |  55%  |                                                                              |=======================================                               |  56%  |                                                                              |========================================                              |  57%  |                                                                              |========================================                              |  58%  |                                                                              |=========================================                             |  58%  |                                                                              |=========================================                             |  59%  |                                                                              |==========================================                            |  60%  |                                                                              |==========================================                            |  61%  |                                                                              |===========================================                           |  62%  |                                                                              |============================================                          |  62%  |                                                                              |============================================                          |  63%  |                                                                              |=============================================                         |  64%  |                                                                              |==============================================                        |  65%  |                                                                              |==============================================                        |  66%  |                                                                              |===============================================                       |  67%  |                                                                              |================================================                      |  68%  |                                                                              |================================================                      |  69%  |                                                                              |=================================================                     |  70%  |                                                                              |==================================================                    |  71%  |                                                                              |===================================================                   |  72%  |                                                                              |===================================================                   |  73%  |                                                                              |====================================================                  |  74%  |                                                                              |=====================================================                 |  75%  |                                                                              |=====================================================                 |  76%  |                                                                              |======================================================                |  77%  |                                                                              |=======================================================               |  78%  |                                                                              |=======================================================               |  79%  |                                                                              |========================================================              |  80%  |                                                                              |=========================================================             |  81%  |                                                                              |=========================================================             |  82%  |                                                                              |==========================================================            |  83%  |                                                                              |===========================================================           |  84%  |                                                                              |===========================================================           |  85%  |                                                                              |============================================================          |  86%  |                                                                              |=============================================================         |  86%  |                                                                              |=============================================================         |  87%  |                                                                              |==============================================================        |  88%  |                                                                              |==============================================================        |  89%  |                                                                              |===============================================================       |  89%  |                                                                              |===============================================================       |  90%  |                                                                              |================================================================      |  91%  |                                                                              |================================================================      |  92%  |                                                                              |=================================================================     |  92%  |                                                                              |=================================================================     |  93%  |                                                                              |==================================================================    |  94%  |                                                                              |==================================================================    |  95%  |                                                                              |===================================================================   |  95%  |                                                                              |===================================================================   |  96%  |                                                                              |====================================================================  |  97%  |                                                                              |====================================================================  |  98%  |                                                                              |===================================================================== |  98%  |                                                                              |===================================================================== |  99%  |                                                                              |======================================================================| 100%

4. Preparing the data for analysis:

# Assign hospitals to tracts
hospitals_tract_join <- st_join(hospitals, acs_data, join = st_within)

# Count hospitals per tract
hospital_counts <- hospitals_tract_join %>%
  st_drop_geometry() %>%
  count(GEOID, name = "hospital_count")

# Join counts back to ACS tracts and compute metrics
hospitals_acs_joined <- left_join(acs_data, hospital_counts, by = "GEOID") %>%
  mutate(
    hospital_count = replace_na(hospital_count, 0),
    hospitals_per_10k = (hospital_count / total_popE) * 10000,
    tract_area = as.numeric(st_area(geometry)),
    poverty_rate = (pov_belowE / pov_totalE) * 100,             # tract-level poverty rate
    pct_no_vehicle = (no_vehicleE / total_hhE) * 100             # % households without a vehicle
  ) %>%
  st_make_valid()

# Compute distance to nearest hospital
acs_centroids <- st_centroid(hospitals_acs_joined)
## Warning: st_centroid assumes attributes are constant over geometries
dist_matrix <- st_distance(acs_centroids, hospitals)
min_dist <- apply(dist_matrix, 1, min)

# Add hospital access metrics back to data
hospitals_acs_joined <- hospitals_acs_joined %>%
  mutate(
    dist_to_nearest_hosp_m  = as.numeric(min_dist),
    dist_to_nearest_hosp_km = dist_to_nearest_hosp_m / 1000
  )

5. Defining and computing operational measure of healthcare access.

Healthcare access is operationalized using two complementary metrics:

  1. The average poverty rate for each county was calculated as an area-weighted mean of tract-level poverty rates, providing a measure of socioeconomic disadvantage across neighborhoods. This metric allows us to evaluate whether lower-income areas experience reduced healthcare access, for instance, longer distances to hospitals or lower hospital density, highlighting potential spatial inequities in the Metro Atlanta region.

  2. The distance to the nearest hospital (dist_to_nearest_hosp_km) to capture spatial proximity, The number of hospitals per 10,000 residents (hospitals_per_10k) to account for population-adjusted availability. Distance was computed for each Census tract using hospital point-of-interest data

# Extract county names from tract NAME (e.g., "Tract 101, Fulton County, Georgia")
hospitals_acs_joined <- hospitals_acs_joined %>%
  mutate(county_name = str_extract(NAME, "(?<=, )[^,]+(?= County)")) %>%
  mutate(county_name = str_trim(county_name))

# Aggregate to county level using area-weighted averages
county_access <- hospitals_acs_joined %>%
  st_drop_geometry() %>%
  group_by(NAME) %>%
  summarize(
    mean_dist_to_hosp_km = sum(dist_to_nearest_hosp_km * tract_area, na.rm = TRUE) /
                            sum(tract_area, na.rm = TRUE),
    mean_hosp_per_10k    = sum(hospitals_per_10k * tract_area, na.rm = TRUE) /
                            sum(tract_area, na.rm = TRUE),
    mean_poverty_rate    = sum(poverty_rate * tract_area, na.rm = TRUE) /
                            sum(tract_area, na.rm = TRUE),
    mean_pct_no_vehicle  = sum(pct_no_vehicle * tract_area, na.rm = TRUE) /
                            sum(tract_area, na.rm = TRUE),
    .groups = "drop"
  )
tmap_mode("plot")
## ℹ tmap modes "plot" - "view"
## ℹ toggle with `tmap::ttm()`
# Map: Poverty rate
tm_shape(hospitals_acs_joined) +
  tm_polygons("poverty_rate", 
              palette = "greens", 
              title = "Poverty Rate (%)") +
  tm_layout(title = "Spatial Distribution of Poverty and Hospital Accessibility")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).[v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'[v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`Multiple palettes called "greens" found: "brewer.greens", "matplotlib.greens". The first one, "brewer.greens", is returned.
## [plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

# Map: Distance to nearest hospital
tm_shape(hospitals_acs_joined) +
  tm_polygons("dist_to_nearest_hosp_km", 
              palette = "Reds", 
              title = "Distance to Nearest Hospital (km)") +
  tm_layout(title = "Spatial Distribution of Hospital Accessibility")
## 
## ── tmap v3 code detected ───────────────────────────────────────────────────────
## [v3->v4] `tm_tm_polygons()`: migrate the argument(s) related to the scale of
## the visual variable `fill` namely 'palette' (rename to 'values') to fill.scale
## = tm_scale(<HERE>).
## [v3->v4] `tm_polygons()`: migrate the argument(s) related to the legend of the
## visual variable `fill` namely 'title' to 'fill.legend = tm_legend(<HERE>)'
## [v3->v4] `tm_layout()`: use `tm_title()` instead of `tm_layout(title = )`
## [cols4all] color palettes: use palettes from the R package cols4all. Run
## `cols4all::c4a_gui()` to explore them. The old palette name "Reds" is named
## "brewer.reds"
## Multiple palettes called "reds" found: "brewer.reds", "matplotlib.reds". The first one, "brewer.reds", is returned.
## 
## [plot mode] fit legend/component: Some legend items or map compoments do not
## fit well, and are therefore rescaled.
## ℹ Set the tmap option `component.autoscale = FALSE` to disable rescaling.

6. Analyzing the spatial distribution of hospitals from an equity perspective

ggplot(hospitals_acs_joined, aes(x = poverty_rate, y = hospitals_per_10k)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", color = "red") +
  labs(title = "Hospitals per 10k Residents vs Poverty Rate",
       x = "Poverty Rate (%)", y = "Hospitals per 10k Residents")
## `geom_smooth()` using formula = 'y ~ x'
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_smooth()`).
## Warning: Removed 3 rows containing missing values or values outside the scale range
## (`geom_point()`).

ggplot(hospitals_acs_joined, aes(x = dist_to_nearest_hosp_km)) +
  geom_histogram(binwidth = 1, fill = "maroon", color = "black") +
  labs(title = "Distribution of Distance to Nearest Hospital", x = "Distance (km)", y = "Number of Tracts")

lm_density <- lm(hospitals_per_10k ~ poverty_rate + pct_no_vehicle + pop_density, 
                 data = hospitals_acs_joined)
summary(lm_density)
## 
## Call:
## lm(formula = hospitals_per_10k ~ poverty_rate + pct_no_vehicle + 
##     pop_density, data = hospitals_acs_joined)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.7334 -0.2590 -0.2201 -0.1914 13.8092 
## 
## Coefficients:
##                  Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     2.178e-01  4.803e-02   4.535 6.33e-06 ***
## poverty_rate   -4.665e-03  3.727e-03  -1.252  0.21094    
## pct_no_vehicle  1.202e-02  4.422e-03   2.718  0.00666 ** 
## pop_density     4.039e-06  2.033e-05   0.199  0.84258    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.029 on 1239 degrees of freedom
##   (5 observations deleted due to missingness)
## Multiple R-squared:  0.006679,   Adjusted R-squared:  0.004274 
## F-statistic: 2.777 on 3 and 1239 DF,  p-value: 0.04009

KEY TAKEAWAY

The analysis indicates that hospital accessibility in Metro Atlanta is unequal across socioeconomic groups. Areas with higher poverty tend to have fewer hospitals per capita and greater distances to the nearest hospital, suggesting spatial inequities in healthcare provision.