1. Load Data

# Load data
files <- list.files(pattern = "*.csv")
list2env(
  lapply(
    setNames(files, make.names(str_to_lower(gsub("*.csv", "", files)))),
    read_csv
  ),
  envir = .GlobalEnv
)
## <environment: R_GlobalEnv>
# Check dataset
members_23 <- members.2.2023.01.10
glimpse(members_23)
## Rows: 761
## Columns: 46
## $ `Name (Prefix)`                                                         <lgl> …
## $ `Name (First)`                                                          <chr> …
## $ `Name (Middle)`                                                         <lgl> …
## $ `Name (Last)`                                                           <chr> …
## $ `Name (Suffix)`                                                         <lgl> …
## $ Phone                                                                   <chr> …
## $ `Date of Birth`                                                         <date> …
## $ Gender                                                                  <chr> …
## $ `American Indian or Alaska Native`                                      <chr> …
## $ Asian                                                                   <chr> …
## $ `Black or African American`                                             <chr> …
## $ `Hispanic or Latino(a) or Spanish Origin`                               <chr> …
## $ `Native Hawaiian or Other Pacific Islander`                             <chr> …
## $ White                                                                   <chr> …
## $ `2 or more races`                                                       <chr> …
## $ Other                                                                   <chr> …
## $ Email                                                                   <chr> …
## $ `Address (Street Address)`                                              <chr> …
## $ `Address (Address Line 2)`                                              <chr> …
## $ `Address (City)`                                                        <chr> …
## $ `Address (State / Province)`                                            <chr> …
## $ `Address (ZIP / Postal Code)`                                           <chr> …
## $ `Address (Country)`                                                     <lgl> …
## $ `Civilian or Veteran/Military member`                                   <chr> …
## $ `Current Service Status (If applicable)`                                <chr> …
## $ `Branch of Service (if applicable)`                                     <chr> …
## $ `Shirt Size`                                                            <chr> …
## $ `Tell us about yourself or what can we do to improve Chicago Veterans?` <chr> …
## $ Fundraising                                                             <chr> …
## $ `Events/Promotions`                                                     <chr> …
## $ `Employment/Resume Assistance`                                          <chr> …
## $ Blogs                                                                   <chr> …
## $ `Marketing/Social Media`                                                <chr> …
## $ `General Volunteer (Working Party)`                                     <chr> …
## $ `Educational Assistance`                                                <chr> …
## $ `Created By (User Id)`                                                  <lgl> …
## $ `Entry Id`                                                              <dbl> …
## $ `Entry Date`                                                            <dttm> …
## $ `Source Url`                                                            <chr> …
## $ `Transaction Id`                                                        <lgl> …
## $ `Payment Amount`                                                        <lgl> …
## $ `Payment Date`                                                          <lgl> …
## $ `Payment Status`                                                        <lgl> …
## $ `Post Id`                                                               <lgl> …
## $ `User Agent`                                                            <chr> …
## $ `User IP`                                                               <chr> …
# Missing values
colSums(is.na(members_23))
##                                                         Name (Prefix) 
##                                                                   761 
##                                                          Name (First) 
##                                                                     0 
##                                                         Name (Middle) 
##                                                                   761 
##                                                           Name (Last) 
##                                                                     0 
##                                                         Name (Suffix) 
##                                                                   761 
##                                                                 Phone 
##                                                                     0 
##                                                         Date of Birth 
##                                                                     0 
##                                                                Gender 
##                                                                     0 
##                                      American Indian or Alaska Native 
##                                                                   753 
##                                                                 Asian 
##                                                                   725 
##                                             Black or African American 
##                                                                   625 
##                               Hispanic or Latino(a) or Spanish Origin 
##                                                                   619 
##                             Native Hawaiian or Other Pacific Islander 
##                                                                   757 
##                                                                 White 
##                                                                   485 
##                                                       2 or more races 
##                                                                   730 
##                                                                 Other 
##                                                                   743 
##                                                                 Email 
##                                                                     0 
##                                              Address (Street Address) 
##                                                                     0 
##                                              Address (Address Line 2) 
##                                                                   544 
##                                                        Address (City) 
##                                                                     0 
##                                            Address (State / Province) 
##                                                                     0 
##                                           Address (ZIP / Postal Code) 
##                                                                     0 
##                                                     Address (Country) 
##                                                                   761 
##                                   Civilian or Veteran/Military member 
##                                                                     0 
##                                Current Service Status (If applicable) 
##                                                                     0 
##                                     Branch of Service (if applicable) 
##                                                                     0 
##                                                            Shirt Size 
##                                                                     0 
## Tell us about yourself or what can we do to improve Chicago Veterans? 
##                                                                   295 
##                                                           Fundraising 
##                                                                   575 
##                                                     Events/Promotions 
##                                                                   333 
##                                          Employment/Resume Assistance 
##                                                                   520 
##                                                                 Blogs 
##                                                                   667 
##                                                Marketing/Social Media 
##                                                                   592 
##                                     General Volunteer (Working Party) 
##                                                                   403 
##                                                Educational Assistance 
##                                                                   571 
##                                                  Created By (User Id) 
##                                                                   761 
##                                                              Entry Id 
##                                                                     0 
##                                                            Entry Date 
##                                                                     0 
##                                                            Source Url 
##                                                                     0 
##                                                        Transaction Id 
##                                                                   761 
##                                                        Payment Amount 
##                                                                   761 
##                                                          Payment Date 
##                                                                   761 
##                                                        Payment Status 
##                                                                   761 
##                                                               Post Id 
##                                                                   761 
##                                                            User Agent 
##                                                                     0 
##                                                               User IP 
##                                                                     0

1.2 Clean columns

members_23 <- members_23 %>%
  clean_names() %>%
  mutate(
    year_of_birth = year(date_of_birth), # only keep year
    address_city = str_to_title(address_city),
    race = as.factor(ifelse(
      is.na(american_indian_or_alaska_native) == FALSE, # Alkaska/Native
      "American Indian/Alaskan Native",
      ifelse(
        is.na(asian) == FALSE, # Asian
        "Asian",
        ifelse(
          is.na(black_or_african_american) == FALSE,
          "Black",
          ifelse(
            is.na(white) == FALSE,
            "White",
            ifelse(
              is.na(native_hawaiian_or_other_pacific_islander) == FALSE,
              "Hawaiian/Pacific Islander",
              ifelse(
                is.na(x2_or_more_races) == FALSE,
                "Multirace",
                NA
              )
            )
          )
        )
      )
    )),
    hispanic = as.factor(ifelse(
      is.na(hispanic_or_latino_a_or_spanish_origin) == FALSE, # Hispanic
      "Hispanic",
      NA
    )),
    across(civilian_or_veteran_military_member:branch_of_service_if_applicable,
           as.factor), # Convert columns on veteran history, current veteran status and branch
    event = as.factor(ifelse(
      is.na(fundraising) == FALSE, # Fundraising
      "Fundraising",
      ifelse(
        is.na(events_promotions) == FALSE, # Event promotion
        "Event Promotions",
        ifelse(
          is.na(employment_resume_assistance) == FALSE,
          "Employment", # Employment
          ifelse(
            is.na(blogs) == FALSE,
            "Blog", # Blog
            ifelse(
              is.na(marketing_social_media) == FALSE,
              "Media Marketing", # Marketing
              ifelse(
                is.na(general_volunteer_working_party) == FALSE,
                "General Volunteer", # General Volunteer
                ifelse(
                  is.na(educational_assistance) == FALSE,
                  "Education", # Education
                  NA
                )
              )
            )
          )
        )
      )
    ))
  )

# Keep informative columns
members_23 <- members_23 %>%
  rename(
    "veteran" = "civilian_or_veteran_military_member",
    "veteran_current" = "current_service_status_if_applicable",
    "branch" = "branch_of_service_if_applicable"
  ) %>%
  select(
    name_first, name_last, phone:gender, email:address_zip_postal_code,
    veteran:shirt_size, entry_date, year_of_birth:event
  ) %>%
  select(
    entry_date, name_first, name_last, phone, email,
    year_of_birth, gender, race, hispanic,
    veteran:branch, event, everything()
  )

1.3 Remove Duplicates

dup <- members_23 %>%
  get_dupes(
    name_first, name_last, # same time
    year_of_birth, gender, race, # same flight
    veteran, branch
  ) %>%
  group_by(name_first, name_last, year_of_birth, gender, phone) %>%
  arrange(entry_date)
# Keep the latest submission
dup_keep <- dup %>%
  slice_tail()
# Remove duplicated data from dup
dup <- anti_join(dup, dup_keep)
# Remove duplicates
members_23 <- anti_join(members_23, dup,
                        by = c("entry_date", "name_first", "name_last"))

# Remove wrong entries
dup_wrong <- members_23 %>%
  get_dupes(name_first, name_last)
members_23_dup_edited <- members_23_dup_edited %>%
  select(-date_of_birth)

dup_wrong <- anti_join(dup_wrong, members_23_dup_edited) %>%
  filter(year_of_birth > 1900) # remove entries with birth year before 1900

# Final clean dataset without duplicates
members_23 <- anti_join(members_23, dup_wrong,
                        by = c("entry_date", "name_first", "name_last"))
# write_csv(members_23, "members_23_nodup.csv")

1.4. Clean Name data

members_23[!(nchar(members_23$name_first) < 2 | nchar(members_23$name_first) < 2), ]
## # A tibble: 611 × 20
##    entry_date          name_f…¹ name_…² phone email year_…³ gender race  hispa…⁴
##    <dttm>              <chr>    <chr>   <chr> <chr>   <dbl> <chr>  <fct> <fct>  
##  1 2023-01-07 04:22:52 Peter    Stavro… (630… Psta…    1986 Male   <NA>  Hispan…
##  2 2023-01-06 23:58:22 Patrycja Saida   (773… Patr…    1982 Female White <NA>   
##  3 2023-01-06 14:09:49 Justin   Wesley  (708… just…    1983 Male   White <NA>   
##  4 2022-12-31 02:11:03 Jacob    Alcaraz (910… jaco…    1986 Male   Mult… <NA>   
##  5 2022-12-29 21:54:03 Lexis    Procha… (773… lexi…    1992 Female White <NA>   
##  6 2022-12-29 16:08:40 Ismael   Quinte… (815… Quin…    1982 Male   <NA>  Hispan…
##  7 2022-12-28 22:37:33 Kristin  Davis   (850… kayl…    1987 Female White <NA>   
##  8 2022-12-28 04:01:42 Michael  Atkins… (801… Mich…    1984 Male   White <NA>   
##  9 2022-12-27 02:17:42 Allison  Lutes   (312… alut…    1984 Female White <NA>   
## 10 2022-12-27 02:08:56 Weston   Polaski (312… wpol…    1983 Male   White <NA>   
## # … with 601 more rows, 11 more variables: veteran <fct>,
## #   veteran_current <fct>, branch <fct>, event <fct>, date_of_birth <date>,
## #   address_street_address <chr>, address_address_line_2 <chr>,
## #   address_city <chr>, address_state_province <chr>,
## #   address_zip_postal_code <chr>, shirt_size <chr>, and abbreviated variable
## #   names ¹​name_first, ²​name_last, ³​year_of_birth, ⁴​hispanic
members_23 <- members_23 %>%
  mutate(name_first = str_to_title(name_first),
         name_last = str_to_title(name_last)) %>%
  filter(name_first != "N")

1.5. Clean Age Data

members_23 <- members_23 %>%
  filter(year_of_birth >= 1920) # Filter out people aged over 100

1.6. Correct Veteran Status

# Remove data with no veteran branch info
veteran_wrong <- members_23 %>%
  filter(branch == "None" & veteran == "Veteran")
# Remove wrong entries
members_23 <- anti_join(members_23, veteran_wrong)
# Sanity Check
members_23 %>%
  count(veteran, veteran_current, branch)
## # A tibble: 36 × 4
##    veteran  veteran_current branch             n
##    <fct>    <fct>           <fct>          <int>
##  1 Civilian Civilian        Air Force          1
##  2 Civilian Civilian        Marine Corps       2
##  3 Civilian Civilian        None              59
##  4 Civilian Civilian        US Army            3
##  5 Civilian Civilian        US Navy            7
##  6 Civilian Retired         US Army            1
##  7 Veteran  Active Duty     Air Force          6
##  8 Veteran  Active Duty     Marine Corps       4
##  9 Veteran  Active Duty     National Guard     1
## 10 Veteran  Active Duty     US Army           13
## # … with 26 more rows

1.7. Clean Geographic Data

library(zipcodeR)
# Merge cleaned state data
zip_check <- members_23_zip_check_edited %>%
  select(address_state_province, address_zip_postal_code,
         entry_date, name_first, name_last, gender, race, year_of_birth)
# Merge
members_23 <- left_join(members_23, zip_check,
                        by = c("entry_date", "name_first", "name_last",
                               "gender", "race", "year_of_birth")) %>%
  select(-ends_with(".x"))

# Rename address columns
colnames(members_23) <- gsub("\\..*", "", colnames(members_23))

# Incorporate city information
members_23 <- members_23 %>%
  mutate(address_zip_postal_code = as.numeric(str_sub(address_zip_postal_code, 1, 5)),
    address_zip_postal_code = as.character(sprintf("%05d", address_zip_postal_code))
  )
# Zipcode merge
zip <- zip_code_db %>%
  select(zipcode, major_city, state:lng)

members_23 <- members_23 %>%
  left_join(zip, by = c("address_zip_postal_code" = "zipcode")) %>%
  select(-state)

# NA Community zip code
zip_na_check <- members_23 %>%
  filter(is.na(address_state_province))
# write_csv(zip_na_check, "zip_na_check.csv")

# Output dataset
write_csv(members_23, "members_23_clean.csv")

2. Summary Statistics

2.1. Unique number of each column

# Unique values of each column
values_unique <- vector("double", length(members_23))
names(values_unique) <- names(members_23)
for (i in names(members_23)) {
  values_unique[i] <- n_distinct(members_23[i])
}
# View results
as.data.frame(values_unique)
##                         values_unique
## entry_date                        606
## name_first                        424
## name_last                         526
## phone                             597
## email                             599
## year_of_birth                      66
## gender                              2
## race                                7
## hispanic                            2
## veteran                             2
## veteran_current                     6
## branch                              7
## event                               8
## date_of_birth                     591
## address_street_address            596
## address_address_line_2            158
## address_city                      191
## shirt_size                          5
## address_state_province             21
## address_zip_postal_code           240
## major_city                        166
## lat                               119
## lng                               110

2.2 Top cases of Each Columns

# Top cases
top_cases <- vector("list") 

get_top_cases <- function(df, cols){
for (i in cols){ top_cases[[i]] <- df %>%
    group_by(df[[i]]) %>%
    summarise(count = n()) %>%
    arrange(desc(count)) %>%
    head(10)
  colnames(top_cases[[i]]) <- c(i, "count")
  }
  top_cases
}
top_case_col <- c("year_of_birth", "gender",
                  "race", "veteran", "veteran_current", "branch",
                  "event", "address_city", "address_state_province")
get_top_cases(members_23, top_case_col)
## $year_of_birth
## # A tibble: 10 × 2
##    year_of_birth count
##            <dbl> <int>
##  1          1984    27
##  2          1989    25
##  3          1981    23
##  4          1986    20
##  5          1982    19
##  6          1983    19
##  7          1987    19
##  8          1980    18
##  9          1985    18
## 10          1990    18
## 
## $gender
## # A tibble: 2 × 2
##   gender count
##   <chr>  <int>
## 1 Male     374
## 2 Female   232
## 
## $race
## # A tibble: 7 × 2
##   race                           count
##   <chr>                          <int>
## 1 <NA>                             232
## 2 White                            208
## 3 Black                            107
## 4 Asian                             30
## 5 Multirace                         23
## 6 American Indian/Alaskan Native     5
## 7 Hawaiian/Pacific Islander          1
## 
## $veteran
## # A tibble: 2 × 2
##   veteran  count
##   <fct>    <int>
## 1 Veteran    533
## 2 Civilian    73
## 
## $veteran_current
## # A tibble: 6 × 2
##   veteran_current   count
##   <fct>             <int>
## 1 Civilian            368
## 2 Separated            79
## 3 Retired              50
## 4 Reserve              49
## 5 Active Duty          31
## 6 Medically Retired    29
## 
## $branch
## # A tibble: 7 × 2
##   branch         count
##   <fct>          <int>
## 1 US Army          236
## 2 US Navy          111
## 3 Marine Corps      99
## 4 Air Force         71
## 5 None              59
## 6 National Guard    27
## 7 Coast Guard        3
## 
## $event
## # A tibble: 8 × 2
##   event             count
##   <fct>             <int>
## 1 Event Promotions    210
## 2 Fundraising         146
## 3 <NA>                120
## 4 Employment           56
## 5 General Volunteer    33
## 6 Education            18
## 7 Media Marketing      13
## 8 Blog                 10
## 
## $address_city
## # A tibble: 10 × 2
##    address_city   count
##    <chr>          <int>
##  1 Chicago          308
##  2 Berwyn             8
##  3 Oak Park           6
##  4 Bolingbrook        5
##  5 Oak Lawn           5
##  6 Plainfield         5
##  7 Mount Prospect     4
##  8 Park Ridge         4
##  9 Schaumburg         4
## 10 Westchester        4
## 
## $address_state_province
## # A tibble: 10 × 2
##    address_state_province count
##    <chr>                  <int>
##  1 IL                       497
##  2 <NA>                      73
##  3 TX                         5
##  4 IN                         3
##  5 NC                         3
##  6 TN                         3
##  7 VA                         3
##  8 AE                         2
##  9 AZ                         2
## 10 CA                         2

3. Plot

# Theme
chicago_veteran = "#304573"
theme <- theme_economist() +
  theme(
    plot.title = element_text(size = 12, face = "bold", vjust = 1.5),
    plot.subtitle = element_text(size = 9, face = "italic", hjust = 0),
    axis.title = element_text(size = 9, face = "bold"),
    plot.caption = element_text(size = 6, face = "italic", hjust = 0),
    axis.text = element_text(size = 8),
    legend.key.size = unit(0.5, "cm"),
    legend.text = element_text(size = 8),
    legend.title = element_blank()
  )

#one disaggregation variable
get_pct <- function(col, df) {
  # get data frame
  data_pct <- df %>%
    group_by(df[[col]]) %>%
    summarise(cases = n())
  colnames(data_pct) <- c(col, "cases") # Change column name
  
  data_pct[[col]] <- as.factor(data_pct[[col]]) # Factorize variable
  data_pct
}

# Generate Plots
get_plt <- function(var, df) {
  # wage gap ts
  plt_pct <- df %>%
    ggplot() +
    geom_col(aes(var, cases, 
                 fill = factor(df[[var]])),
             position = "dodge") +
    theme
  plt_pct
}

3.1 Gender and Race Distribution

# Gender
gender_pct <- get_pct("gender", members_23)
gender_pct_plt <- ggplot(gender_pct) +
  geom_col(aes(fct_reorder(gender, desc(cases)), cases, fill = gender)) +
  labs(
    title = "Members Gender Distribution",
    x = "Gender",
    y = "Number of Members"
  ) +
  scale_y_continuous(
    limits = c(0, 400),
    breaks = seq(0, 400, 50)
  ) +
  scale_fill_economist() +
  theme
# Race
race_pct <- get_pct("race", members_23)
race_pct_plt <- ggplot(drop_na(race_pct)) +
  geom_col(aes(fct_reorder(race, desc(cases)), cases, fill = race)) +
  labs(
    title = "Members Racial Identity Distribution",
    x = "Race",
    y = "Number of Members"
  ) +
  scale_x_discrete(labels = function(x) str_wrap(x, width = 23)) +
  scale_y_continuous(
    limits = c(0, 230),
    breaks = seq(0, 210, 30)
  ) +
  scale_fill_economist() +
  theme
# Plot
gender_pct_plt

race_pct_plt

3.2 Age Distribution

age_pct <- get_pct("year_of_birth", members_23)
veteran_pct_plt <- ggplot(age_pct) +
  geom_col(aes(year_of_birth, cases)) +
  labs(
    title = "Age Distribution",
    x = "Age",
    y = "Number of Members"
  ) +
  theme

3.2 Veteran Status Distrituion

# Veteran status
veteran_pct <- get_pct("veteran", members_23)
veteran_pct_plt <- ggplot(veteran_pct) +
  geom_col(aes(fct_reorder(veteran, desc(cases)), cases, fill = veteran)) +
  labs(
    title = "Veteran Distribution",
    x = "Veteran",
    y = "Number of Members"
  ) +
  scale_y_continuous(
    limits = c(0, 550),
    breaks = seq(0, 550, 50)
  ) +
  theme

# Current veteran status
veteran_status_pct <- get_pct("veteran_current", members_23)
veteran_status_pct_plt <- ggplot(veteran_status_pct) +
  geom_col(aes(fct_reorder(veteran_current, desc(cases)), cases, fill = veteran_current)) +
  labs(
    title = "Current Veteran Status",
    x = "Current Veteran Status",
    y = "Number of Members"
  ) +
  scale_y_continuous(
    limits = c(0, 400),
    breaks = seq(0, 400, 50)
  ) +
  scale_fill_economist() +
  theme
# Branch served
branch_pct <- get_pct("branch", members_23)
branch_pct_plt <- ggplot(filter(branch_pct, branch != "None")) +
  geom_col(aes(fct_reorder(branch, desc(cases)), cases, fill = branch)) +
  labs(
    title = "Distribution of Branch Served Among Veterans",
    x = "Branch Served",
    y = "Number of Members"
  ) +
  scale_y_continuous(
    limits = c(0, 250),
    breaks = seq(0, 250, 50)
  ) +
  scale_fill_economist() +
  theme
# Plot
plt <- ggarrange(ggarrange(veteran_pct_plt, veteran_status_pct_plt, ncol = 2),
                 branch_pct_plt,
                 nrow = 2)
plt

3.4 Event of Interest

3.4.1 Event of Interest by Gender

plt_event_gender <- members_23 %>%
  drop_na(event) %>%
  count(event, gender) %>%
  ggplot(aes(fct_reorder(event,desc(n)), n,
             fill = factor(gender))
  ) +
  geom_col(position = "dodge") +
  labs(
    title = "Event of Interest by Gender",
    subtitle = "Event Promotion is the most popular; Preference is consistent across genders",
    x = "Interested Event Type",
    y = "Number of Responses") +
  scale_y_continuous(limits = c(0, 180),
                     breaks = seq(0, 170, 30)) +
  theme_economist() +
  theme(
    legend.position = c(0.09,0.95),
    legend.direction = "horizontal") +
  theme

plt_event_race <- members_23 %>%
  drop_na(event, race) %>%
  filter(race != "Multirace") %>%
  group_by(race) %>%
  mutate(event_total = n()) %>%
  group_by(race, event) %>%
  mutate(event_race = n()) %>%
  distinct(race, event, .keep_all = TRUE) %>%
  ggplot(aes(fct_reorder(race, -event_total), event_race,
             fill = fct_rev(factor(event))
  )) +
  geom_col() +
  labs(
    title = "Event of Interest by Race",
    x = "Race",
    y = "Number of Responses") +
  scale_x_discrete(labels = function(x) str_wrap(x, width = 20)) +
  scale_y_continuous(limits = c(0, 220),
                     breaks = seq(0, 210, 30)) +
  scale_fill_economist() +
  theme

3.4.2 Event of Interest by Race

plt_event_gender 

plt_event_race

members_23 %>%
  drop_na(event, race) %>%
  filter(race != "Multirace") %>%
  group_by(race) %>%
  mutate(total = n()) %>%
  group_by(race, event) %>%
  transmute(
    total = total,
    event_case = n(),
    event_pct = event_case/total) %>%
  distinct(.keep_all = FALSE) %>%
  ggplot(aes(fct_reorder(event, -event_case), event_pct,
             group = 1)) +
  geom_col() +
  labs(
    title = "Event of Interest by Race",
    subtitle = "Event Promotion is the most popular;Preference is consistent across genders",
    x = "Interested Event Type",
    y = "Number of Responses") +
  scale_y_continuous(limits = c(0, 1),
                     breaks = seq(0, 1, 0.2)) +
  facet_wrap(~race) +
  theme

3.5 Spatial Analysis

3.5.1 Chicago Communities

# Clean zipcode
chicago <- members_23 %>%
  arrange(desc(address_zip_postal_code)) %>%
  mutate(address_zip_postal_code = str_sub(address_zip_postal_code, 1, 5),
         zipcode = as.numeric(address_zip_postal_code)) %>%
  drop_na(zipcode) %>%
  mutate(zipcode = as.character(zipcode))
#Zipcode
geometry <- read_excel("uszips.xlsx")
geometry <- geometry %>%
  filter(city == "Chicago") %>%
  select(zip, lat, lng) %>%
  mutate(zipcode = as.character(zip)) %>%
  select(-1)
# Filter Chicago data
chicago <- inner_join(chicago, geometry, by = "zipcode")
#Geometry
community_shape <- st_read("Zip_Codes.shp")
## Reading layer `Zip_Codes' from data source 
##   `/Users/mia/Desktop/chicago-veterans/Zip_Codes.shp' using driver `ESRI Shapefile'
## Simple feature collection with 61 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: 1090000 ymin: 1810000 xmax: 1210000 ymax: 1950000
## Projected CRS: NAD83 / Illinois East (ftUS)
glimpse(community_shape)
## Rows: 61
## Columns: 5
## $ OBJECTID   <dbl> 33, 34, 35, 36, 37, 38, 39, 40, 1, 2, 3, 4, 5, 6, 7, 8, 9, …
## $ ZIP        <chr> "60647", "60639", "60707", "60622", "60651", "60611", "6063…
## $ SHAPE_AREA <dbl> 106052287, 127476051, 45069038, 70853834, 99039621, 2350605…
## $ SHAPE_LEN  <dbl> 42720, 48104, 27289, 42528, 47970, 34689, 67711, 48188, 339…
## $ geometry   <MULTIPOLYGON [US_survey_foot]> MULTIPOLYGON (((1162711 191..., M…
# Clean shape dataset
community_shape <- community_shape %>%
  rename("zipcode" = "ZIP") %>%
  select(zipcode, geometry)
community_shape <- st_sf(community_shape)
# Merge
chicago_plt <- inner_join(chicago, community_shape, by = "zipcode")
chicago_plt_sf <- st_sf(chicago_plt)

Plot

chicago_plt_sf %>%
  count(zipcode) %>%
  ggplot() +
  geom_sf(aes(fill = n)) +
  labs(
    title = "Chicago Veterans Members",
    subtitle = "Year 2022-2023",
    fill = element_blank()
  ) +
  scale_fill_distiller(
    palette = "Blues",
    direction = 1
  ) + # darker color represents higher value
  theme_economist() +
  theme(
    plot.title = element_text(
      size = 12, face = "bold"
    ),
    plot.subtitle = element_text(
      size = 9, face = "italic",
      vjust = -0.5,
      hjust = 0
    ),
    legend.text = element_text(size = 8),
    legend.position = "right",
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.text = element_blank(),
    axis.ticks = element_blank()
  )

3.5.2 US State

library(tigris)
# 1.Members by State
us_geo <- states(cb = TRUE, resolution = '20m') %>%
  select(STUSPS, geometry)
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |=                                                                     |   1%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |========                                                              |  12%
  |                                                                            
  |============                                                          |  16%
  |                                                                            
  |==================                                                    |  25%
  |                                                                            
  |=====================                                                 |  29%
  |                                                                            
  |========================                                              |  34%
  |                                                                            
  |==============================                                        |  43%
  |                                                                            
  |=================================                                     |  47%
  |                                                                            
  |========================================                              |  58%
  |                                                                            
  |================================================                      |  69%
  |                                                                            
  |=========================================================             |  82%
  |                                                                            
  |============================================================          |  86%
  |                                                                            
  |======================================================================| 100%
members_23_sf <- inner_join(members_23, us_geo, by = c("address_state_province" = "STUSPS")) %>%
  group_by(address_state_province) %>%
  mutate(members_cases = n()) %>%
  st_as_sf()
#Plot
mapview(members_23_sf, zcol = "members_cases", col.regions = brewer.pal(-6, "RdBu")) 
# 2.Members by City
members_city_sf <- members_23 %>%
  drop_na(lng) %>%
  st_as_sf(coords = c("lng", "lat"), crs = 4326)

mapview(members_23_sf, zcol = "members_cases", col.regions = brewer.pal(-6, "RdBu")) + 
  mapview(members_city_sf, cex = 3, alpha = 0.5, col.regions = "slateblue", legend = FALSE)