This healthcare equity analysis explores the spatial distribution of hospitals in Fulton and Dekalb counties through the lenses of poverty, health insurance, and individuals with disability.

1. Import and tidy Yelp data

# Load required packages
library(sf)
library(dplyr)
library(tidycensus)
library(tmap)
library(jsonlite)
library(tidyverse)
library(httr)
library(reshape2)
library(here)
library(knitr)
library(skimr)
library(units)
library(tidyr)
library(purrr)

# Read the Yelp hospital data 
yelp_hospital <- st_read("https://raw.githubusercontent.com/ujhwang/urban-analytics-2024/main/Assignment/mini_3/yelp_hospital.geojson")
## Reading layer `yelp_hospital' from data source 
##   `https://raw.githubusercontent.com/ujhwang/urban-analytics-2024/main/Assignment/mini_3/yelp_hospital.geojson' 
##   using driver `GeoJSON'
## Simple feature collection with 129 features and 23 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -84.56242 ymin: 33.60009 xmax: -84.08677 ymax: 34.0701
## Geodetic CRS:  WGS 84
# Check for duplicates
sum(duplicated(yelp_hospital))
## [1] 0
# Check the class of each column
column_classes <- sapply(yelp_hospital, class)
print(column_classes)
## $id
## [1] "character"
## 
## $alias
## [1] "character"
## 
## $name
## [1] "character"
## 
## $image_url
## [1] "character"
## 
## $is_closed
## [1] "logical"
## 
## $url
## [1] "character"
## 
## $review_count
## [1] "integer"
## 
## $categories
## [1] "character"
## 
## $rating
## [1] "numeric"
## 
## $transactions
## [1] "character"
## 
## $phone
## [1] "character"
## 
## $display_phone
## [1] "character"
## 
## $distance
## [1] "numeric"
## 
## $coordinates.latitude
## [1] "numeric"
## 
## $coordinates.longitude
## [1] "numeric"
## 
## $location.address1
## [1] "character"
## 
## $location.address2
## [1] "character"
## 
## $location.address3
## [1] "character"
## 
## $location.city
## [1] "character"
## 
## $location.zip_code
## [1] "character"
## 
## $location.country
## [1] "character"
## 
## $location.state
## [1] "character"
## 
## $location.display_address
## [1] "character"
## 
## $geometry
## [1] "sfc_POINT" "sfc"
# View the structure of the dataset
str(yelp_hospital)
## Classes 'sf' and 'data.frame':   129 obs. of  24 variables:
##  $ id                      : chr  "fiSgDb29cZO-MffxwrT_LA" "hWXJFx9zCVDmiO6eldgHBA" "kuE7B_HLP57KnSIgn-jzpw" "0B80Az6DXX8ZLXZXhU1bCQ" ...
##  $ alias                   : chr  "northside-alpharetta-medical-campus-alpharetta-2" "regency-hospital-alpharetta" "northside-alpharetta-preventive-medicine-atlanta" "health-direct-alpharetta" ...
##  $ name                    : chr  "Northside Alpharetta Medical Campus" "Regency Hospital" "Northside Alpharetta Preventive Medicine" "Health Direct" ...
##  $ image_url               : chr  "https://s3-media4.fl.yelpcdn.com/bphoto/8Pe7ZlobOywD_CakTalTdg/o.jpg" "" "" "" ...
##  $ is_closed               : logi  FALSE FALSE FALSE FALSE FALSE FALSE ...
##  $ url                     : chr  "https://www.yelp.com/biz/northside-alpharetta-medical-campus-alpharetta-2?adjust_creative=kfv-AqbqsBxwk_npQxknW"| __truncated__ "https://www.yelp.com/biz/regency-hospital-alpharetta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_a"| __truncated__ "https://www.yelp.com/biz/northside-alpharetta-preventive-medicine-atlanta?adjust_creative=kfv-AqbqsBxwk_npQxknW"| __truncated__ "https://www.yelp.com/biz/health-direct-alpharetta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_"| __truncated__ ...
##  $ review_count            : int  1 0 0 0 0 34 0 0 0 0 ...
##  $ categories              : chr  "Hospitals" "Hospitals" "Hospitals" "Hospitals" ...
##  $ rating                  : num  4 0 0 0 0 3.2 0 0 0 0 ...
##  $ transactions            : chr  "" "" "" "" ...
##  $ phone                   : chr  "+17706674000" "+16786940553" "+17706674155" "+17708702500" ...
##  $ display_phone           : chr  "(770) 667-4000" "(678) 694-0553" "(770) 667-4155" "(770) 870-2500" ...
##  $ distance                : num  1497 2126 1497 2460 595 ...
##  $ coordinates.latitude    : num  34.1 34.1 34.1 34.1 33.8 ...
##  $ coordinates.longitude   : num  -84.3 -84.3 -84.3 -84.3 -84.4 ...
##  $ location.address1       : chr  "3400 A & C Old Milton Pkwy" "11175 Cicero Dr" "3400 A Old Milton Pkwy" "2550 Northwinds Pkwy" ...
##  $ location.address2       : chr  "" "Ste 300" "" "" ...
##  $ location.address3       : chr  "" NA "" "" ...
##  $ location.city           : chr  "Alpharetta" "Alpharetta" "Atlanta" "Alpharetta" ...
##  $ location.zip_code       : chr  "30004" "30022" "30303" "30004" ...
##  $ location.country        : chr  "US" "US" "US" "US" ...
##  $ location.state          : chr  "GA" "GA" "GA" "GA" ...
##  $ location.display_address: chr  "3400 A & C Old Milton Pkwy, Alpharetta, GA 30004" "11175 Cicero Dr, Ste 300, Alpharetta, GA 30022" "3400 A Old Milton Pkwy, Atlanta, GA 30303" "2550 Northwinds Pkwy, Alpharetta, GA 30004" ...
##  $ geometry                :sfc_POINT of length 129; first list element:  'XY' num  -84.3 34.1
##  - attr(*, "sf_column")= chr "geometry"
##  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
##   ..- attr(*, "names")= chr [1:23] "id" "alias" "name" "image_url" ...
# Check for list columns
list_columns <- sapply(yelp_hospital, is.list)
print(list_columns)
##                       id                    alias                     name 
##                    FALSE                    FALSE                    FALSE 
##                image_url                is_closed                      url 
##                    FALSE                    FALSE                    FALSE 
##             review_count               categories                   rating 
##                    FALSE                    FALSE                    FALSE 
##             transactions                    phone            display_phone 
##                    FALSE                    FALSE                    FALSE 
##                 distance     coordinates.latitude    coordinates.longitude 
##                    FALSE                    FALSE                    FALSE 
##        location.address1        location.address2        location.address3 
##                    FALSE                    FALSE                    FALSE 
##            location.city        location.zip_code         location.country 
##                    FALSE                    FALSE                    FALSE 
##           location.state location.display_address                 geometry 
##                    FALSE                    FALSE                     TRUE
# Flatten nested columns and handle nested structures
yelp_hospital_flat <- yelp_hospital %>% 
  jsonlite::flatten() %>% 
  mutate(
    transactions = map_chr(transactions, ~ str_c(., collapse = ", ")), 
    location.display_address = map_chr(location.display_address, ~ str_c(., collapse = ", ")), 
    categories = map_chr(categories, ~ str_c(., collapse = ", "))  
  )

# Filter to remove rows with missing coordinates from the flattened dataset
yelp_hospital_clean <- yelp_hospital_flat %>% 
  filter(!is.na(coordinates.latitude) & !is.na(coordinates.longitude))

2. Select the following variables for a socioeconomic equity analysis:

I selected the following variables for analysis: Total population for whom poverty status is determined, Population without health insurance, and Population with a disability.

Poverty is a key indicator of socioeconomic status and directly affects access to healthcare services, as individuals living in poverty often face barriers such as financial constraints, lack of transportation, and difficulty in accessing nearby healthcare facilities.

Insurance status is also a major determinant of access to healthcare services, as ndividuals without health insurance are less likely to seek timely medical care due to cost concerns.

Finally, people with disabilities often face physical and systemic barriers to healthcare, including transportation challenges, the need for specialized facilities, and difficulties in navigating the healthcare system.

These variables help assess whether hospital distribution is equitably clustered around at-risk populations.

# Set Census API key
tidycensus::census_api_key(Sys.getenv("CENSUS_API_KEY"))

3. Download ACS data for the for Census Tracts in Fulton and DeKalb counties using tidycensus

# Download ACS data for Census Tracts in Fulton and DeKalb counties
variables <- c(
  total_population = "B01003_001",           # Total population of the census tract
  population_below_poverty = "B17001_002",   # Population below the poverty level
  uninsured_total = "B27001_003",            # Population without health insurance
  population_with_disability = "B18101_002"  # Population with a disability
)

# Download the ACS data for Fulton and DeKalb counties
tract_data <- get_acs(
  geography = "tract",
  state = "GA",
  county = c("DeKalb", "Fulton"),
  variables = variables,
  year = 2021,  # Use the latest available year
  survey = "acs5",
  geometry = TRUE,  # Include geometrical data
  output = "wide"   # Output format
)
##   |                                                                              |                                                                      |   0%  |                                                                              |=                                                                     |   1%  |                                                                              |==                                                                    |   2%  |                                                                              |==                                                                    |   3%  |                                                                              |====                                                                  |   5%  |                                                                              |====                                                                  |   6%  |                                                                              |=====                                                                 |   7%  |                                                                              |======                                                                |   9%  |                                                                              |========                                                              |  11%  |                                                                              |=========                                                             |  13%  |                                                                              |==========                                                            |  14%  |                                                                              |===========                                                           |  16%  |                                                                              |============                                                          |  17%  |                                                                              |==============                                                        |  20%  |                                                                              |===============                                                       |  22%  |                                                                              |================                                                      |  23%  |                                                                              |===================                                                   |  27%  |                                                                              |=====================                                                 |  30%  |                                                                              |======================                                                |  31%  |                                                                              |=======================                                               |  33%  |                                                                              |========================                                              |  35%  |                                                                              |===========================                                           |  39%  |                                                                              |===============================                                       |  45%  |                                                                              |================================                                      |  46%  |                                                                              |=================================                                     |  48%  |                                                                              |==================================                                    |  49%  |                                                                              |=====================================                                 |  52%  |                                                                              |=======================================                               |  55%  |                                                                              |========================================                              |  57%  |                                                                              |=========================================                             |  59%  |                                                                              |===========================================                           |  62%  |                                                                              |============================================                          |  63%  |                                                                              |===============================================                       |  67%  |                                                                              |================================================                      |  68%  |                                                                              |=================================================                     |  70%  |                                                                              |===================================================                   |  72%  |                                                                              |=====================================================                 |  76%  |                                                                              |=======================================================               |  78%  |                                                                              |========================================================              |  80%  |                                                                              |=========================================================             |  82%  |                                                                              |==========================================================            |  83%  |                                                                              |===========================================================           |  84%  |                                                                              |==============================================================        |  88%  |                                                                              |==============================================================        |  89%  |                                                                              |================================================================      |  92%  |                                                                              |==================================================================    |  95%  |                                                                              |===================================================================   |  96%  |                                                                              |===================================================================== |  99%  |                                                                              |======================================================================| 100%

4. Prepare the data for analysis

# Check for NA values in the dataset
na_summary <- tract_data %>% 
  summarise(across(everything(), ~ sum(is.na(.))))  # Count NAs in each column
print(na_summary)
## Simple feature collection with 1 feature and 10 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: -84.85071 ymin: 33.50251 xmax: -84.02371 ymax: 34.18629
## Geodetic CRS:  NAD83
##   GEOID NAME total_populationE total_populationM population_below_povertyE
## 1     0    0                 0                 0                         0
##   population_below_povertyM uninsured_totalE uninsured_totalM
## 1                         0                0                0
##   population_with_disabilityE population_with_disabilityM
## 1                           0                           0
##                         geometry
## 1 POLYGON ((-84.09722 33.7983...
# Create Variable for Proportion of Uninsured Population
tract_data <- tract_data %>% 
  mutate(uninsured_proportion = uninsured_totalE / total_populationE)

# Create Variable for Proportion of Total Population in Poverty
tract_data <- tract_data %>% 
  mutate(poverty_proportion = population_below_povertyE / total_populationE)  

# Create Ratio of Population with Disabilities to Total Population
tract_data <- tract_data %>% 
  mutate(disability_ratio = population_with_disabilityE / total_populationE)

There are different coordinate references systems, so the ACS tract data must be transformed.

# Check the CRS of the Yelp hospital data
yelp_crs <- st_crs(yelp_hospital_clean)
print(yelp_crs)
## Coordinate Reference System:
##   User input: WGS 84 
##   wkt:
## GEOGCRS["WGS 84",
##     DATUM["World Geodetic System 1984",
##         ELLIPSOID["WGS 84",6378137,298.257223563,
##             LENGTHUNIT["metre",1]]],
##     PRIMEM["Greenwich",0,
##         ANGLEUNIT["degree",0.0174532925199433]],
##     CS[ellipsoidal,2],
##         AXIS["geodetic latitude (Lat)",north,
##             ORDER[1],
##             ANGLEUNIT["degree",0.0174532925199433]],
##         AXIS["geodetic longitude (Lon)",east,
##             ORDER[2],
##             ANGLEUNIT["degree",0.0174532925199433]],
##     ID["EPSG",4326]]
# Check the CRS of the ACS tract data
tract_crs <- st_crs(tract_data)
print(tract_crs)
## Coordinate Reference System:
##   User input: NAD83 
##   wkt:
## GEOGCRS["NAD83",
##     DATUM["North American Datum 1983",
##         ELLIPSOID["GRS 1980",6378137,298.257222101,
##             LENGTHUNIT["metre",1]]],
##     PRIMEM["Greenwich",0,
##         ANGLEUNIT["degree",0.0174532925199433]],
##     CS[ellipsoidal,2],
##         AXIS["latitude",north,
##             ORDER[1],
##             ANGLEUNIT["degree",0.0174532925199433]],
##         AXIS["longitude",east,
##             ORDER[2],
##             ANGLEUNIT["degree",0.0174532925199433]],
##     ID["EPSG",4269]]
# Transform ACS tract data CRS to WGS 84 
if (tract_crs != yelp_crs) {
  tract_data <- st_transform(tract_data, st_crs(yelp_hospital_clean))
}

# Join Yelp data with Census Tract data based on spatial location
joined_data <- st_join(yelp_hospital_clean, tract_data)

# View the first few rows of the joined dataset
print(head(joined_data))
## Simple feature collection with 6 features and 36 fields
## Geometry type: POINT
## Dimension:     XY
## Bounding box:  xmin: -84.39409 ymin: 33.81016 xmax: -84.26324 ymax: 34.0701
## Geodetic CRS:  WGS 84
##                       id                                            alias
## 1 fiSgDb29cZO-MffxwrT_LA northside-alpharetta-medical-campus-alpharetta-2
## 2 hWXJFx9zCVDmiO6eldgHBA                      regency-hospital-alpharetta
## 3 kuE7B_HLP57KnSIgn-jzpw northside-alpharetta-preventive-medicine-atlanta
## 4 0B80Az6DXX8ZLXZXhU1bCQ                         health-direct-alpharetta
## 5 EaD2lKlKh4NpeSD25_vrHw                 ultimatemedicalhousecall-atlanta
## 6 O4DoAVRc6oTjUe9ufieTjA                          shepherd-center-atlanta
##                                       name
## 1      Northside Alpharetta Medical Campus
## 2                         Regency Hospital
## 3 Northside Alpharetta Preventive Medicine
## 4                            Health Direct
## 5                 Ultimatemedicalhousecall
## 6                          Shepherd Center
##                                                              image_url
## 1 https://s3-media4.fl.yelpcdn.com/bphoto/8Pe7ZlobOywD_CakTalTdg/o.jpg
## 2                                                                     
## 3                                                                     
## 4                                                                     
## 5                                                                     
## 6 https://s3-media2.fl.yelpcdn.com/bphoto/7H4uUz1eDFV1a2fM-5-e2A/o.jpg
##   is_closed
## 1     FALSE
## 2     FALSE
## 3     FALSE
## 4     FALSE
## 5     FALSE
## 6     FALSE
##                                                                                                                                                                                                             url
## 1 https://www.yelp.com/biz/northside-alpharetta-medical-campus-alpharetta-2?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=kfv-AqbqsBxwk_npQxknWQ
## 2                      https://www.yelp.com/biz/regency-hospital-alpharetta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=kfv-AqbqsBxwk_npQxknWQ
## 3 https://www.yelp.com/biz/northside-alpharetta-preventive-medicine-atlanta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=kfv-AqbqsBxwk_npQxknWQ
## 4                         https://www.yelp.com/biz/health-direct-alpharetta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=kfv-AqbqsBxwk_npQxknWQ
## 5                 https://www.yelp.com/biz/ultimatemedicalhousecall-atlanta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=kfv-AqbqsBxwk_npQxknWQ
## 6                          https://www.yelp.com/biz/shepherd-center-atlanta?adjust_creative=kfv-AqbqsBxwk_npQxknWQ&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=kfv-AqbqsBxwk_npQxknWQ
##   review_count                                                     categories
## 1            1                                                      Hospitals
## 2            0                                                      Hospitals
## 3            0                                                      Hospitals
## 4            0                                                      Hospitals
## 5            0                                                      Hospitals
## 6           34 Hospitals, Rehabilitation Center, Community Service/Non-Profit
##   rating transactions        phone  display_phone  distance
## 1    4.0              +17706674000 (770) 667-4000 1496.5068
## 2    0.0              +16786940553 (678) 694-0553 2125.5366
## 3    0.0              +17706674155 (770) 667-4155 1496.5068
## 4    0.0              +17708702500 (770) 870-2500 2460.2880
## 5    0.0                                           595.1797
## 6    3.2              +14043522020 (404) 352-2020  769.8365
##   coordinates.latitude coordinates.longitude          location.address1
## 1             34.07010             -84.26324 3400 A & C Old Milton Pkwy
## 2             34.05106             -84.27857            11175 Cicero Dr
## 3             34.07010             -84.26324     3400 A Old Milton Pkwy
## 4             34.06029             -84.28281       2550 Northwinds Pkwy
## 5             33.84957             -84.37021        3495 Buckhead Lp NE
## 6             33.81016             -84.39409       2020 Peachtree Rd NW
##   location.address2 location.address3 location.city location.zip_code
## 1                                        Alpharetta             30004
## 2           Ste 300              <NA>    Alpharetta             30022
## 3                                           Atlanta             30303
## 4                                        Alpharetta             30004
## 5                                <NA>       Atlanta             30305
## 6                                           Atlanta             30309
##   location.country location.state
## 1               US             GA
## 2               US             GA
## 3               US             GA
## 4               US             GA
## 5               US             GA
## 6               US             GA
##                           location.display_address       GEOID
## 1 3400 A & C Old Milton Pkwy, Alpharetta, GA 30004 13121011636
## 2   11175 Cicero Dr, Ste 300, Alpharetta, GA 30022 13121011637
## 3        3400 A Old Milton Pkwy, Atlanta, GA 30303 13121011636
## 4       2550 Northwinds Pkwy, Alpharetta, GA 30004 13121011639
## 5           3495 Buckhead Lp NE, Atlanta, GA 30305 13121010003
## 6          2020 Peachtree Rd NW, Atlanta, GA 30309 13121009104
##                                          NAME total_populationE
## 1 Census Tract 116.36, Fulton County, Georgia              1827
## 2 Census Tract 116.37, Fulton County, Georgia              2428
## 3 Census Tract 116.36, Fulton County, Georgia              1827
## 4 Census Tract 116.39, Fulton County, Georgia              1965
## 5 Census Tract 100.03, Fulton County, Georgia              3482
## 6  Census Tract 91.04, Fulton County, Georgia              2657
##   total_populationM population_below_povertyE population_below_povertyM
## 1               432                        18                        31
## 2               315                         0                        14
## 3               432                        18                        31
## 4               550                        99                        90
## 5               686                       398                       212
## 6               401                       290                       208
##   uninsured_totalE uninsured_totalM population_with_disabilityE
## 1                0               14                         995
## 2               44               53                        1186
## 3                0               14                         995
## 4              149              167                         874
## 5               56               54                        1820
## 6               29               51                        1048
##   population_with_disabilityM uninsured_proportion poverty_proportion
## 1                         279           0.00000000        0.009852217
## 2                         207           0.01812191        0.000000000
## 3                         279           0.00000000        0.009852217
## 4                         284           0.07582697        0.050381679
## 5                         470           0.01608271        0.114302125
## 6                         263           0.01091457        0.109145653
##   disability_ratio                   geometry
## 1        0.5446086  POINT (-84.26324 34.0701)
## 2        0.4884679 POINT (-84.27857 34.05106)
## 3        0.5446086  POINT (-84.26324 34.0701)
## 4        0.4447837 POINT (-84.28281 34.06029)
## 5        0.5226881 POINT (-84.37021 33.84957)
## 6        0.3944298 POINT (-84.39409 33.81016)
# Summary of the joined data
summary(joined_data)
##       id               alias               name            image_url        
##  Length:129         Length:129         Length:129         Length:129        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  is_closed           url             review_count    categories       
##  Mode :logical   Length:129         Min.   :  0.0   Length:129        
##  FALSE:129       Class :character   1st Qu.:  0.0   Class :character  
##                  Mode  :character   Median :  0.0   Mode  :character  
##                                     Mean   : 12.9                     
##                                     3rd Qu.:  2.0                     
##                                     Max.   :319.0                     
##      rating      transactions          phone           display_phone     
##  Min.   :0.000   Length:129         Length:129         Length:129        
##  1st Qu.:0.000   Class :character   Class :character   Class :character  
##  Median :0.000   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :1.054                                                           
##  3rd Qu.:2.000                                                           
##  Max.   :5.000                                                           
##     distance      coordinates.latitude coordinates.longitude location.address1 
##  Min.   : 204.1   Min.   :33.60        Min.   :-84.56        Length:129        
##  1st Qu.: 564.8   1st Qu.:33.77        1st Qu.:-84.39        Class :character  
##  Median :1199.7   Median :33.81        Median :-84.35        Mode  :character  
##  Mean   :1188.1   Mean   :33.86        Mean   :-84.34                          
##  3rd Qu.:1647.7   3rd Qu.:33.92        3rd Qu.:-84.32                          
##  Max.   :4098.4   Max.   :34.07        Max.   :-84.09                          
##  location.address2  location.address3  location.city      location.zip_code 
##  Length:129         Length:129         Length:129         Length:129        
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##  location.country   location.state     location.display_address
##  Length:129         Length:129         Length:129              
##  Class :character   Class :character   Class :character        
##  Mode  :character   Mode  :character   Mode  :character        
##                                                                
##                                                                
##                                                                
##     GEOID               NAME           total_populationE total_populationM
##  Length:129         Length:129         Min.   :1635      Min.   : 254.0   
##  Class :character   Class :character   1st Qu.:2103      1st Qu.: 450.0   
##  Mode  :character   Mode  :character   Median :2897      Median : 599.0   
##                                        Mean   :3229      Mean   : 602.3   
##                                        3rd Qu.:4212      3rd Qu.: 676.0   
##                                        Max.   :6542      Max.   :2352.0   
##  population_below_povertyE population_below_povertyM uninsured_totalE
##  Min.   :   0.0            Min.   : 14.0             Min.   :  0.00  
##  1st Qu.: 155.0            1st Qu.:104.0             1st Qu.: 44.00  
##  Median : 287.0            Median :188.0             Median : 64.00  
##  Mean   : 341.2            Mean   :199.7             Mean   : 91.15  
##  3rd Qu.: 447.0            3rd Qu.:258.0             3rd Qu.:120.00  
##  Max.   :1251.0            Max.   :670.0             Max.   :348.00  
##  uninsured_totalM population_with_disabilityE population_with_disabilityM
##  Min.   : 14.0    Min.   : 507                Min.   : 161               
##  1st Qu.: 38.0    1st Qu.:1023                1st Qu.: 295               
##  Median : 66.0    Median :1404                Median : 307               
##  Mean   : 71.6    Mean   :1543                Mean   : 375               
##  3rd Qu.:102.0    3rd Qu.:1936                3rd Qu.: 438               
##  Max.   :231.0    Max.   :3422                Max.   :1276               
##  uninsured_proportion poverty_proportion disability_ratio          geometry  
##  Min.   :0.00000      Min.   :0.00000    Min.   :0.1544   POINT        :129  
##  1st Qu.:0.01519      1st Qu.:0.03158    1st Qu.:0.4563   epsg:4326    :  0  
##  Median :0.02785      Median :0.10915    Median :0.4846   +proj=long...:  0  
##  Mean   :0.02763      Mean   :0.11735    Mean   :0.4799                      
##  3rd Qu.:0.04421      3rd Qu.:0.21255    3rd Qu.:0.4864                      
##  Max.   :0.11557      Max.   :0.40153    Max.   :0.6808

Examine the spatial distribution of hospitals from an equity perspective

# Step 1:Count hospitals within 0.25 miles (approximately 402.34 meters)
buffer_distance <- 0.25 * 1609.34  # Convert miles to meters
tract_data_buffered <- st_buffer(tract_data, dist = buffer_distance)

# Spatial join to count hospitals within the buffer
hospital_counts <- st_intersects(tract_data_buffered, yelp_hospital_clean) %>%
  lapply(length) %>%  
  unlist() %>%
  data.frame(hospital_count = ., row.names = NULL)

# Combine with tract data
tract_data <- cbind(tract_data, hospital_counts)

# Step 2: Calculate distance to the nearest hospital
# Convert the hospital data to simple feature points 
yelp_hospital_points <- st_as_sf(yelp_hospital_clean)

# Calculate the distance to the nearest hospital for each tract
tract_data$nearest_hospital_distance <- st_distance(tract_data, yelp_hospital_points) %>%
  apply(1, min)  # Find the minimum distance for each tract

# Convert distances to miles 
tract_data$nearest_hospital_distance_miles <- tract_data$nearest_hospital_distance / 1609.34

# Step 3: Review the updated tract data
print(head(tract_data[, c("hospital_count", "nearest_hospital_distance", "nearest_hospital_distance_miles")]))
## Simple feature collection with 6 features and 3 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -84.40818 ymin: 33.72657 xmax: -84.11855 ymax: 34.06896
## Geodetic CRS:  WGS 84
##   hospital_count nearest_hospital_distance nearest_hospital_distance_miles
## 1              0                  4904.611                      3.04759152
## 2              0                  1738.562                      1.08029517
## 3              2                   181.434                      0.11273812
## 4              1                   112.488                      0.06989696
## 5              0                  2034.834                      1.26439030
## 6              0                  2659.007                      1.65223448
##                         geometry
## 1 MULTIPOLYGON (((-84.19745 3...
## 2 MULTIPOLYGON (((-84.40818 3...
## 3 MULTIPOLYGON (((-84.27626 3...
## 4 MULTIPOLYGON (((-84.37003 3...
## 5 MULTIPOLYGON (((-84.24742 3...
## 6 MULTIPOLYGON (((-84.1484 33...

Visualize the results

tract_data <- tract_data %>% 
  mutate(uninsured_rate = (uninsured_totalE / total_populationE) * 100,         # Uninsured rate as a percentage
         disability_rate = (population_with_disabilityE / total_populationE) * 100)  # Disability rate as a percentage

# tmap mode set to interactive viewing
tmap_mode("view")

Map 1: Poverty Rate with Hospitals

map_poverty <- tm_shape(tract_data) + 
  tm_polygons(col = "poverty_proportion",                
              style = "quantile",                        
              palette = "Blues",                         
              title = "Poverty Rate") +               
  tm_shape(yelp_hospital_clean) +                         
  tm_dots(col = "red", size = 0.1, title = "Hospitals", shape = 21, border.col = "black") + 
  tm_add_legend(type = "symbol",                          
                col = "red", 
                shape = 21, 
                size = 1, 
                title = "Hospitals") + 
  tm_layout(title = "Poverty Rate by Census Tract with Hospitals", 
            legend.position = c("right", "bottom")) 
            
map_poverty  # Display interactive map for poverty rates

Map 2: Uninsured Rate with Hospitals

map_uninsured <- tm_shape(tract_data) + 
  tm_polygons(col = "uninsured_rate", 
               style = "quantile", 
               palette = "Reds", 
               title = "Uninsured Rate (%)") + 
  tm_shape(yelp_hospital_clean) + 
  tm_dots(col = "skyblue", size = 0.1, title = "Hospitals", shape = 21, border.col = "black") +  
  tm_add_legend(type = "symbol", 
                 col = "skyblue", 
                 shape = 21, 
                 size = 1, 
                 title = "Hospitals") +  
  tm_layout(title = "Uninsured Rate by Census Tract with Hospitals", 
            legend.position = c("right", "bottom"))
            
map_uninsured  # Display interactive map for uninsured rates

The tracts with the highest poverty rate and uninsured rates are clustered in the southern regions of both counties. Meanwhile, the majority of hospitals are found in the central or northern regions. According to the data, there is a disparity between higher numbers of individuals in poverty as well as those who are uninsured amongst ease of access to hospitals. Therefore, the spatial distribution of hospitals in Fulton and DeKalb counties is not equitable.

# Proportion of Uninsured Population vs. Distance to Nearest Hospital
library(ggplot2)

# Scatter plot of uninsured proportion vs. nearest hospital distance
ggplot(tract_data, aes(x = nearest_hospital_distance_miles, y = uninsured_proportion)) +
  geom_point(color = "blue") +
  geom_smooth(method = "lm", se = FALSE, color = "red") +  
  labs(title = "Uninsured Population Proportion vs. Distance to Nearest Hospital",
       x = "Distance to Nearest Hospital (miles)",
       y = "Uninsured Population Proportion (%)") +
  theme_minimal()

# Hospital Count vs. Uninsured Population Proportion
ggplot(tract_data, aes(x = uninsured_proportion, y = hospital_count)) +
  geom_point(color = "blue") +
  labs(title = "Hospital Count vs. Uninsured Population Proportion",
       x = "Uninsured Population Proportion",
       y = "Number of Hospitals") +
  theme_minimal()

Scatter plot of poverty proportion vs. hospital count

library(ggplot2)

ggplot(tract_data, aes(x = hospital_count, y = poverty_proportion)) +
  geom_point(color = "blue") +  # Scatter points
  geom_smooth(method = "lm", se = FALSE, color = "red") + 
  labs(title = "Poverty Rate vs. Number of Hospitals", 
       x = "Number of Hospitals",                       
       y = "Poverty Rate (%)") +                       
  theme_minimal()