Census & Yelp API Application in Ithaca

Written by Jiaqi Gu

2024-09-17

Census API Key

tidycensus::census_api_key(Sys.getenv("census_api"))
## To install your API key for use in future sessions, run this function with `install = TRUE`.

Getting Census Tract Boundary of Ithaca

#### Tract polygons for the Yelp query
tract <- suppressMessages(
  get_acs(geography = "tract", 
          state = "NY",
          county = c("Tompkins"), 
          variables = c(hhincome = 'B19019_001'),
          year = 2021,
          survey = "acs5", # American Community Survey 5-year estimate
          geometry = TRUE, # returns sf objects
          output = "wide") # wide vs. long
)

ithac <- tigris::places('NY') %>% 
  filter(NAME == 'Ithaca') 
## Retrieving data for the year 2022
tract_ithac <- tract[ithac,]
# Retaining only those I want.
# Notice that select function can also change names when it selects columns.
tract_ithac <- tract_ithac %>% 
  select(GEOID, 
         hhincome = hhincomeE) # New name = old name

tmap_mode("view")
## tmap mode set to interactive viewing
tm_shape(tract_ithac) + tm_borders(lwd = 2) + 
  tm_shape(ithac) + tm_polygons(col = 'red', alpha = 0.4)
# Function: Get tract-wise radius
get_r <- function(poly, epsg_id){
  #---------------------
  # Takes: a single POLYGON or LINESTRTING
  # Outputs: distance between the centroid of the boundingbox and a corner of the bounding box
  #---------------------
  
  # Get bounding box of a given polygon
  bb <- st_bbox(poly)
  # Get lat & long coordinates of any one corner of the bounding box.
  bb_corner <- st_point(c(bb[1], bb[2])) %>% st_sfc(crs = epsg_id)
  # Get centroid of the bb
  bb_center_x <- (bb[3]+bb[1])/2
  bb_center_y <- (bb[4]+bb[2])/2
  bb_center <- st_point(c(bb_center_x, bb_center_y)) %>% st_sfc(crs = epsg_id) %>% st_sf()
    
  # Get the distance between bb_p and c
  r <- st_distance(bb_corner, bb_center)
  # Multiply 1.1 to make the circle a bit larger than the Census Tract.
  # See the Yelp explanation of their radius parameter to see why we do this.
  bb_center$radius <- r*1.1
  return(bb_center)
}
## Using a loop -----------------------------------------------------------------
# Creating an empty vector of NA. 
# Results will fill this vector
epsg_id <- 4326

r4all_loop <- vector("list", nrow(tract_ithac))

# Starting a for-loop

for (i in 1:nrow(tract_ithac)){
  r4all_loop[[i]] <- tract_ithac %>% 
    st_transform(crs = epsg_id) %>% 
    st_geometry() %>% 
    .[[i]] %>% 
    get_r(epsg_id = epsg_id)
}

r4all_loop <- bind_rows(r4all_loop)


# Using a functional -----------------------------------------------------------
# We use a functional (sapply) to apply this custom function to each Census Tract.
r4all_apply <- tract_ithac %>%
  st_geometry() %>% 
  st_transform(crs = epsg_id) %>% 
  lapply(., function(x) get_r(x, epsg_id = epsg_id))

r4all_apply <- bind_rows(r4all_apply)

# Are these two identical?
identical(r4all_apply, r4all_loop)
## [1] TRUE
# Appending X Y coordinates as seprate columns
ready_4_yelp <- r4all_apply %>% 
  mutate(x = st_coordinates(.)[,1],
         y = st_coordinates(.)[,2])
tmap_mode('view')
## tmap mode set to interactive viewing
ready_4_yelp %>% 
  # Draw a buffer centered at the centroid of Tract polygons.
  # Radius of the buffer is the radius we just calculated using loop
  st_buffer(., dist = .$radius) %>% 
  # Display this buffer in red
  tm_shape(.) + tm_polygons(alpha = 0.5, col = 'red') +
  # Display the original polygon in blue
  tm_shape(tract_ithac) + tm_borders(col= 'blue')



yelpr package (Category: Restaurants, Flowers & Gifts)

which_tract <- 2
test <- business_search(api_key = Sys.getenv('yelp_api'), # like we did for census, store your api key
                        categories = 'restaurants,flowers', # return only restaurant businesses
                        latitude = ready_4_yelp$y[which_tract],
                        longitude = ready_4_yelp$x[which_tract],
                        offset = 0, # 1st page, 1st obs
                        radius = round(ready_4_yelp$radius[which_tract]), # radius requires integer value
                        limit = 50) # how many business per page
## No encoding supplied: defaulting to UTF-8.
lapply(test, head)
## $businesses
##                       id                            alias
## 1 h0nPGPVrqZHCrrauTrywrA    mix-kitchen-and-bar-ithaca-11
## 2 4GTwlHQ5qN9NGIpiySpBsA         silo-food-truck-no-title
## 3 MBISWEvAzDb710ZCyvNu2A              sunset-grill-ithaca
## 4 eTfO8fF3WWcyhN4SHG2TJw sandellas-flat-bread-cafe-ithaca
## 5 3QCY93kLbH29Cctus8IyKQ             rogans-corner-ithaca
## 6 2Aee_Fb6aPb1sYyXqvjsEA              tower-club-ithaca-2
##                         name
## 1          MIX Kitchen & Bar
## 2            Silo Food Truck
## 3               Sunset Grill
## 4 Sandella's Flat Bread Cafe
## 5             Rogan's Corner
## 6                 Tower Club
##                                                              image_url
## 1 https://s3-media4.fl.yelpcdn.com/bphoto/vPdGPwsAJf4X_B2NsZMdkg/o.jpg
## 2 https://s3-media2.fl.yelpcdn.com/bphoto/_O_grfubATER8HrkhwPzJA/o.jpg
## 3 https://s3-media1.fl.yelpcdn.com/bphoto/mAa-6PRyk3VPcQEm77E9HQ/o.jpg
## 4                                                                     
## 5 https://s3-media1.fl.yelpcdn.com/bphoto/HsJPLkZYReQgTSbQB95Mnw/o.jpg
## 6                                                                     
##   is_closed
## 1     FALSE
## 2     FALSE
## 3     FALSE
## 4     FALSE
## 5     FALSE
## 6     FALSE
##                                                                                                                                                                                             url
## 1    https://www.yelp.com/biz/mix-kitchen-and-bar-ithaca-11?adjust_creative=NJjwKPgIcFpchzBhkT2XWg&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=NJjwKPgIcFpchzBhkT2XWg
## 2         https://www.yelp.com/biz/silo-food-truck-no-title?adjust_creative=NJjwKPgIcFpchzBhkT2XWg&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=NJjwKPgIcFpchzBhkT2XWg
## 3              https://www.yelp.com/biz/sunset-grill-ithaca?adjust_creative=NJjwKPgIcFpchzBhkT2XWg&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=NJjwKPgIcFpchzBhkT2XWg
## 4 https://www.yelp.com/biz/sandellas-flat-bread-cafe-ithaca?adjust_creative=NJjwKPgIcFpchzBhkT2XWg&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=NJjwKPgIcFpchzBhkT2XWg
## 5             https://www.yelp.com/biz/rogans-corner-ithaca?adjust_creative=NJjwKPgIcFpchzBhkT2XWg&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=NJjwKPgIcFpchzBhkT2XWg
## 6              https://www.yelp.com/biz/tower-club-ithaca-2?adjust_creative=NJjwKPgIcFpchzBhkT2XWg&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=NJjwKPgIcFpchzBhkT2XWg
##   review_count
## 1          452
## 2           32
## 3          126
## 4            0
## 5           41
## 6            0
##                                                                             categories
## 1 tapasmallplates, cocktailbars, steak, Tapas/Small Plates, Cocktail Bars, Steakhouses
## 2             foodtrucks, comfortfood, breweries, Food Trucks, Comfort Food, Breweries
## 3 tradamerican, breakfast_brunch, sandwiches, American, Breakfast & Brunch, Sandwiches
## 4                         bakeries, mexican, sandwiches, Bakeries, Mexican, Sandwiches
## 5                                                 pizza, sandwiches, Pizza, Sandwiches
## 6                                                            newamerican, New American
##   rating coordinates.latitude coordinates.longitude     transactions price
## 1    4.3             42.43031             -76.50317         delivery    $$
## 2    4.4             42.43855             -76.50757                   <NA>
## 3    3.5             42.42888             -76.49730         delivery    $$
## 4    0.0             42.42278             -76.49420                   <NA>
## 5    2.6             42.42875             -76.49751 delivery, pickup     $
## 6    0.0             42.42106             -76.50111                   <NA>
##          location.address1 location.address2 location.address3 location.city
## 1            205 Elmira Rd              <NA>              <NA>        Ithaca
## 2           620 W Green St              <NA>                          Ithaca
## 3             823 Danby Rd              <NA>              <NA>        Ithaca
## 4 1101 Terrace Dining Hall                                            Ithaca
## 5             825 Danby Rd                                            Ithaca
## 6             953 Danby Rd                                            Ithaca
##   location.zip_code location.country location.state
## 1             14850               US             NY
## 2             14850               US             NY
## 3             14850               US             NY
## 4             14850               US             NY
## 5             14850               US             NY
## 6             14850               US             NY
##                     location.display_address        phone  display_phone
## 1            205 Elmira Rd, Ithaca, NY 14850 +16073194248 (607) 319-4248
## 2           620 W Green St, Ithaca, NY 14850                            
## 3             823 Danby Rd, Ithaca, NY 14850 +16072721986 (607) 272-1986
## 4 1101 Terrace Dining Hall, Ithaca, NY 14850 +16072741176 (607) 274-1176
## 5             825 Danby Rd, Ithaca, NY 14850 +16072777191 (607) 277-7191
## 6             953 Danby Rd, Ithaca, NY 14850 +16072743393 (607) 274-3393
##    distance
## 1 1162.6626
## 2 2110.2622
## 3  728.8960
## 4  136.5052
## 5  725.5237
## 6  604.7391
##                                                                                                                                                             business_hours
## 1 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 1100, 1100, 1100, 0900, 1630, 0900, 1630, 2130, 2130, 2130, 1500, 2130, 1500, 2130, 2, 3, 4, 5, 5, 6, 6, REGULAR, FALSE
## 2                                             FALSE, FALSE, FALSE, FALSE, FALSE, 1600, 1600, 1600, 1200, 1400, 2100, 2100, 2200, 2200, 2000, 2, 3, 4, 5, 6, REGULAR, FALSE
## 3 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0700, 0700, 0700, 0700, 0700, 0700, 0700, 1500, 1500, 2100, 2100, 2100, 2100, 1500, 0, 1, 2, 3, 4, 5, 6, REGULAR, FALSE
## 4 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0730, 0730, 0730, 0730, 0730, 1200, 1200, 2200, 2200, 2200, 2200, 1700, 1900, 1900, 0, 1, 2, 3, 4, 5, 6, REGULAR, FALSE
## 5 FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 2215, 2215, 2215, 2215, 2215, 2215, 2215, 0, 1, 2, 3, 4, 5, 6, REGULAR, FALSE
## 6                                                                                                                                                                     NULL
##   attributes.business_temp_closed
## 1                              NA
## 2                              NA
## 3                              NA
## 4                              NA
## 5                              NA
## 6                              NA
##                                      attributes.menu_url
## 1                        https://www.mixithaca.com/menus
## 2                   https://silo-food-truck.square.site/
## 3                                                       
## 4                                                   <NA>
## 5 http://www.roganscornerrest.com/page2.cfm?idd=1&more=1
## 6                                                   <NA>
##   attributes.open24_hours attributes.waitlist_reservation
## 1                      NA                              NA
## 2                      NA                              NA
## 3                      NA                              NA
## 4                      NA                              NA
## 5                      NA                              NA
## 6                      NA                              NA
## 
## $total
## [1] 11
## 
## $region
## $region$center
## $region$center$longitude
## [1] -76.49268
## 
## $region$center$latitude
## [1] 42.42328
# See what's inside
names(test)
## [1] "businesses" "total"      "region"
# Business
paste0("is it a data.frame?: ", is.data.frame(test$businesses), ", ",
       " how many rows?: ", nrow(test$businesses), ", ",
       " how many columns?: ", ncol(test$businesses))
## [1] "is it a data.frame?: TRUE,  how many rows?: 11,  how many columns?: 18"

Defining function for accessing Yelp API for one Census Tract

# FUNCTION
get_yelp <- function(tract, category){
  # ----------------------------------
  # Gets one row of tract information (1,) and category name (str),
  # Outputs a list of business data.frame
  Sys.sleep(1)
  n <- 1
  # First request --------------------------------------------------------------
  resp <- business_search(api_key = Sys.getenv("yelp_api"), 
                          categories = category, 
                          latitude = tract$y, 
                          longitude = tract$x, 
                          offset = (n - 1) * 50, # = 0 when n = 1
                          radius = round(tract$radius), 
                          limit = 50)
  # Calculate how many requests are needed in total
  required_n <- ceiling(resp$total/50)
  
  # out is where the results will be appended to.
  out <- vector("list", required_n)
  
  # Store the business information to nth slot in out
  out[[n]] <- resp$businesses
  
  # Change the name of the elements to the total required_n
  # This is to know if there are more than 1000 businesses,
  # we know how many.
  names(out)[n] <- required_n
  
  # Throw error if more than 1000
  if (resp$total >= 1000)
  {
    # glue formats string by inserting {n} with what's currently stored in object n.
    print(glue::glue("{n}th row has >= 1000 businesses."))
    # Stop before going into the loop because we need to
    # break down Census Tract to something smaller.
    return(out)
  } 
  else 
  {
    # add 1 to n
    n <- n + 1
    
    # Now we know required_n -----------------------------------------------------
    # Starting a loop
    while(n <= required_n){
      resp <- business_search(api_key = Sys.getenv("yelp_api"), 
                              categories = category, 
                              latitude = tract$y, 
                              longitude = tract$x, 
                              offset = (n - 1) * 50, 
                              radius = round(tract$radius), 
                              limit = 50)
      
      out[[n]] <- resp$businesses
      
      n <- n + 1
    } #<< end of while loop
    
    # Merge all elements in the list into a single data frame
    out <- out %>% bind_rows()
    
    return(out)
  }
}
# Apply the function for the first Census Tract
yelp_first_tract1 <- get_yelp(ready_4_yelp[1,], 'restaurants') %>% 
  as_tibble()
## No encoding supplied: defaulting to UTF-8.
## No encoding supplied: defaulting to UTF-8.
yelp_first_tract2 <- get_yelp(ready_4_yelp[1,], 'flowers') %>% 
  as_tibble()
## No encoding supplied: defaulting to UTF-8.
# Print
yelp_first_tract1 %>% print
## # A tibble: 67 × 18
##    id       alias name  image_url is_closed url   review_count categories rating
##    <chr>    <chr> <chr> <chr>     <lgl>     <chr>        <int> <list>      <dbl>
##  1 3XDW8Ot… gola… Gola… https://… FALSE     http…          169 <df>          4  
##  2 4o6C5dF… itha… Itha… https://… FALSE     http…          586 <df>          3.9
##  3 JlCzPAt… de-t… De T… https://… FALSE     http…          125 <df>          3.4
##  4 T-n8QFM… reds… Red'… https://… FALSE     http…          271 <df>          3.9
##  5 v1zbzBE… le-c… Le C… https://… FALSE     http…          120 <df>          4.6
##  6 uOxHLne… merc… Merc… https://… FALSE     http…          179 <df>          4.1
##  7 BdMKj3r… thom… Thom… https://… FALSE     http…          184 <df>          4.4
##  8 dycxEZt… creo… Creo… https://… FALSE     http…           43 <df>          4.3
##  9 ud9RNk5… wing… Wing… https://… FALSE     http…           91 <df>          3.9
## 10 ntH3yiP… sime… Sime… https://… FALSE     http…          294 <df>          3.8
## # ℹ 57 more rows
## # ℹ 9 more variables: coordinates <df[,2]>, transactions <list>, price <chr>,
## #   location <df[,8]>, phone <chr>, display_phone <chr>, distance <dbl>,
## #   business_hours <list>, attributes <df[,4]>
yelp_first_tract2 %>% print
## # A tibble: 2 × 18
##   id        alias name  image_url is_closed url   review_count categories rating
##   <chr>     <chr> <chr> <chr>     <lgl>     <chr>        <int> <list>      <dbl>
## 1 jDsvWSwt… bool… Bool… https://… FALSE     http…           23 <df>          4.1
## 2 UHDpAts-… melo… Melo… https://… FALSE     http…            0 <df>          0  
## # ℹ 9 more variables: coordinates <df[,2]>, transactions <list>, price <chr>,
## #   location <df[,8]>, phone <chr>, display_phone <chr>, distance <dbl>,
## #   business_hours <list>, attributes <df[,3]>


Repeating for all other Census Tracts

# Prepare a collector
yelp_all_list <- vector("list", nrow(ready_4_yelp))
yelp_all_list1 <- vector("list", nrow(ready_4_yelp))
yelp_all_list2 <- vector("list", nrow(ready_4_yelp))

# Looping through all Census Tracts
for (row in 1:nrow(ready_4_yelp)){
  yelp_all_list[[row]] <- suppressMessages(get_yelp(ready_4_yelp[row,], "restaurants,flowers"))
  print(paste0("Current row: ", row))
}
## [1] "Current row: 1"
## [1] "Current row: 2"
## [1] "Current row: 3"
## [1] "Current row: 4"
## [1] "Current row: 5"
## [1] "Current row: 6"
## [1] "Current row: 7"
## [1] "Current row: 8"
## [1] "Current row: 9"
## [1] "Current row: 10"
## [1] "Current row: 11"
## [1] "Current row: 12"
## [1] "Current row: 13"
## [1] "Current row: 14"
## [1] "Current row: 15"
for (row in 1:nrow(ready_4_yelp)){
  yelp_all_list1[[row]] <- suppressMessages(get_yelp(ready_4_yelp[row,], "restaurants"))
  print(paste0("Current row: ", row))
}
## [1] "Current row: 1"
## [1] "Current row: 2"
## [1] "Current row: 3"
## [1] "Current row: 4"
## [1] "Current row: 5"
## [1] "Current row: 6"
## [1] "Current row: 7"
## [1] "Current row: 8"
## [1] "Current row: 9"
## [1] "Current row: 10"
## [1] "Current row: 11"
## [1] "Current row: 12"
## [1] "Current row: 13"
## [1] "Current row: 14"
## [1] "Current row: 15"
for (row in 1:nrow(ready_4_yelp)){
  yelp_all_list2[[row]] <- suppressMessages(get_yelp(ready_4_yelp[row,], "flowers"))
  print(paste0("Current row: ", row))
}
## [1] "Current row: 1"
## [1] "Current row: 2"
## [1] "Current row: 3"
## [1] "Current row: 4"
## [1] "Current row: 5"
## [1] "Current row: 6"
## [1] "Current row: 7"
## [1] "Current row: 8"
## [1] "Current row: 9"
## [1] "Current row: 10"
## [1] "Current row: 11"
## [1] "Current row: 12"
## [1] "Current row: 13"
## [1] "Current row: 14"
## [1] "Current row: 15"
# Collapsing the list into a data.frame
yelp_all <- yelp_all_list %>% bind_rows() %>% as_tibble()
yelp_all1 <- yelp_all_list1 %>% bind_rows() %>% as_tibble()
yelp_all2 <- yelp_all_list2 %>% bind_rows() %>% as_tibble()

# print
yelp_all %>% print(width=1000)
## # A tibble: 1,534 × 18
##    id                     alias                            
##    <chr>                  <chr>                            
##  1 3XDW8Ot7jSVH_rsm5WBwQA gola-osteria-ithaca              
##  2 4o6C5dFjyjBvF1g9st78NA ithaca-ale-house-ithaca          
##  3 JlCzPAtL7rA5GdCmyUEPow de-tasty-hot-pot-ithaca-2        
##  4 T-n8QFMx2zceV5M_ZKtgIA reds-place-ithaca                
##  5 v1zbzBEnZ7odA9oeu25e4A le-cafe-cent-dix-ithaca-2        
##  6 uOxHLnePU2wyTqPJ_p7ryw mercato-bar-and-kitchen-ithaca   
##  7 BdMKj3rHVnHxZvxe_NCDHA thompson-and-bleecker-ithaca-2   
##  8 dycxEZtWSaAv4xDAlidZPw creola-southern-steakhouse-ithaca
##  9 ud9RNk52okJkisfMOAHtyw wings-over-ithaca-ithaca-3       
## 10 ntH3yiPIjLyMxYDCfY-UUQ simeons-on-the-commons-ithaca    
##    name                      
##    <chr>                     
##  1 Gola Osteria              
##  2 Ithaca Ale House          
##  3 De Tasty Hot Pot          
##  4 Red's Place               
##  5 Le Cafe Cent-Dix          
##  6 Mercato Bar & Kitchen     
##  7 Thompson and Bleecker     
##  8 Creola Southern Steakhouse
##  9 Wings Over Ithaca         
## 10 Simeon's On The Commons   
##    image_url                                                           
##    <chr>                                                               
##  1 https://s3-media3.fl.yelpcdn.com/bphoto/HC9v38sBsVMz62uFKy8Y0A/o.jpg
##  2 https://s3-media2.fl.yelpcdn.com/bphoto/1AeybJBqPvyniCGL9sGMmg/o.jpg
##  3 https://s3-media4.fl.yelpcdn.com/bphoto/nbBvObp5AunbyrsP3GqtLA/o.jpg
##  4 https://s3-media2.fl.yelpcdn.com/bphoto/AGjFqTEa3EJzWwCLVkJaTw/o.jpg
##  5 https://s3-media3.fl.yelpcdn.com/bphoto/1OUhGwPRzZLlkwOTaTcjlQ/o.jpg
##  6 https://s3-media4.fl.yelpcdn.com/bphoto/YpkL8iviu0KXMOuKN_FY9Q/o.jpg
##  7 https://s3-media4.fl.yelpcdn.com/bphoto/Ccl2pjXgvKRRxZShz-O8ww/o.jpg
##  8 https://s3-media1.fl.yelpcdn.com/bphoto/iuBG6OD7__XRYmDHVAOADg/o.jpg
##  9 https://s3-media1.fl.yelpcdn.com/bphoto/S2oyB-RhWXDQfT6Hjb7Nxg/o.jpg
## 10 https://s3-media3.fl.yelpcdn.com/bphoto/rzrle6pCS_-gKKjZYFuN9A/o.jpg
##    is_closed
##    <lgl>    
##  1 FALSE    
##  2 FALSE    
##  3 FALSE    
##  4 FALSE    
##  5 FALSE    
##  6 FALSE    
##  7 FALSE    
##  8 FALSE    
##  9 FALSE    
## 10 FALSE    
##    url                                                                          
##    <chr>                                                                        
##  1 https://www.yelp.com/biz/gola-osteria-ithaca?adjust_creative=NJjwKPgIcFpchzB…
##  2 https://www.yelp.com/biz/ithaca-ale-house-ithaca?adjust_creative=NJjwKPgIcFp…
##  3 https://www.yelp.com/biz/de-tasty-hot-pot-ithaca-2?adjust_creative=NJjwKPgIc…
##  4 https://www.yelp.com/biz/reds-place-ithaca?adjust_creative=NJjwKPgIcFpchzBhk…
##  5 https://www.yelp.com/biz/le-cafe-cent-dix-ithaca-2?adjust_creative=NJjwKPgIc…
##  6 https://www.yelp.com/biz/mercato-bar-and-kitchen-ithaca?adjust_creative=NJjw…
##  7 https://www.yelp.com/biz/thompson-and-bleecker-ithaca-2?adjust_creative=NJjw…
##  8 https://www.yelp.com/biz/creola-southern-steakhouse-ithaca?adjust_creative=N…
##  9 https://www.yelp.com/biz/wings-over-ithaca-ithaca-3?adjust_creative=NJjwKPgI…
## 10 https://www.yelp.com/biz/simeons-on-the-commons-ithaca?adjust_creative=NJjwK…
##    review_count categories   rating coordinates$latitude $longitude transactions
##           <int> <list>        <dbl>                <dbl>      <dbl> <list>      
##  1          169 <df [2 × 2]>    4                   42.4      -76.5 <chr [1]>   
##  2          586 <df [3 × 2]>    3.9                 42.4      -76.5 <chr [1]>   
##  3          125 <df [3 × 2]>    3.4                 42.4      -76.5 <chr [2]>   
##  4          271 <df [2 × 2]>    3.9                 42.4      -76.5 <chr [1]>   
##  5          120 <df [3 × 2]>    4.6                 42.4      -76.5 <chr [1]>   
##  6          179 <df [2 × 2]>    4.1                 42.4      -76.5 <chr [1]>   
##  7          184 <df [3 × 2]>    4.4                 42.4      -76.5 <chr [1]>   
##  8           43 <df [2 × 2]>    4.3                 42.4      -76.5 <chr [1]>   
##  9           91 <df [3 × 2]>    3.9                 42.4      -76.5 <chr [2]>   
## 10          294 <df [3 × 2]>    3.8                 42.4      -76.5 <chr [1]>   
##    price location$address1   $address2 $address3 $city  $zip_code $country
##    <chr> <chr>               <chr>     <chr>     <chr>  <chr>     <chr>   
##  1 $$$   115 South Quarry St ""        ""        Ithaca 14850     US      
##  2 $$    301 East State St   "Ste 1"   ""        Ithaca 14850     US      
##  3 $$    422 Eddy St         ""        ""        Ithaca 14850     US      
##  4 $$    107 N Aurora St     ""        ""        Ithaca 14850     US      
##  5 $$$   110 N Aurora St      <NA>     ""        Ithaca 14850     US      
##  6 $$$   108 N Aurora St     ""        ""        Ithaca 14850     US      
##  7 $$    211 E Seneca St      <NA>     ""        Ithaca 14850     US      
##  8 <NA>  112 N Aurora St     ""        <NA>      Ithaca 14850     US      
##  9 $$    121 Dryden Rd        <NA>     ""        Ithaca 14850     US      
## 10 $$    224 E State St      ""        ""        Ithaca 14850     US      
##    $state $display_address phone        display_phone  distance business_hours
##    <chr>  <list>           <chr>        <chr>             <dbl> <list>        
##  1 NY     <chr [2]>        +16072730333 (607) 273-0333     393. <df [1 × 3]>  
##  2 NY     <chr [3]>        +16072567977 (607) 256-7977     525. <df [1 × 3]>  
##  3 NY     <chr [2]>        +16078212312 (607) 821-2312     231. <df [1 × 3]>  
##  4 NY     <chr [2]>        +16073194486 (607) 319-4486     545. <df [1 × 3]>  
##  5 NY     <chr [2]>        +16073190750 (607) 319-0750     567. <df [1 × 3]>  
##  6 NY     <chr [2]>        +16073195171 (607) 319-5171     577. <df [1 × 3]>  
##  7 NY     <chr [2]>        +16073190851 (607) 319-0851     594. <df [1 × 3]>  
##  8 NY     <chr [2]>        +16072721438 (607) 272-1438     575. <df [1 × 3]>  
##  9 NY     <chr [2]>        +16073194664 (607) 319-4664     237. <df [1 × 3]>  
## 10 NY     <chr [2]>        +16072722212 (607) 272-2212     573. <df [1 × 3]>  
##    attributes$business_temp_closed $menu_url                             
##    <lgl>                           <chr>                                 
##  1 NA                              "https://golaosteria.com/menubkp"     
##  2 NA                              "http://www.ithacaalehouse.com/menu"  
##  3 NA                              "http://www.tastyhotpot.com/menu"     
##  4 NA                              "http://www.redsplaceithaca.com/menu/"
##  5 NA                              "https://www.lecafecentdix.com/menu"  
##  6 NA                              ""                                    
##  7 NA                               <NA>                                 
##  8 NA                               <NA>                                 
##  9 NA                              "https://www.wingsover.com/menu"      
## 10 NA                              ""                                    
##    $open24_hours $waitlist_reservation
##    <lgl>         <lgl>                
##  1 NA            NA                   
##  2 NA            NA                   
##  3 NA            NA                   
##  4 NA            NA                   
##  5 NA            NA                   
##  6 NA            NA                   
##  7 NA            NA                   
##  8 NA            TRUE                 
##  9 NA            NA                   
## 10 NA            NA                   
## # ℹ 1,524 more rows
yelp_all1 %>% print(width=1000)
## # A tibble: 1,449 × 18
##    id                     alias                            
##    <chr>                  <chr>                            
##  1 3XDW8Ot7jSVH_rsm5WBwQA gola-osteria-ithaca              
##  2 4o6C5dFjyjBvF1g9st78NA ithaca-ale-house-ithaca          
##  3 JlCzPAtL7rA5GdCmyUEPow de-tasty-hot-pot-ithaca-2        
##  4 T-n8QFMx2zceV5M_ZKtgIA reds-place-ithaca                
##  5 v1zbzBEnZ7odA9oeu25e4A le-cafe-cent-dix-ithaca-2        
##  6 uOxHLnePU2wyTqPJ_p7ryw mercato-bar-and-kitchen-ithaca   
##  7 BdMKj3rHVnHxZvxe_NCDHA thompson-and-bleecker-ithaca-2   
##  8 dycxEZtWSaAv4xDAlidZPw creola-southern-steakhouse-ithaca
##  9 ud9RNk52okJkisfMOAHtyw wings-over-ithaca-ithaca-3       
## 10 ntH3yiPIjLyMxYDCfY-UUQ simeons-on-the-commons-ithaca    
##    name                      
##    <chr>                     
##  1 Gola Osteria              
##  2 Ithaca Ale House          
##  3 De Tasty Hot Pot          
##  4 Red's Place               
##  5 Le Cafe Cent-Dix          
##  6 Mercato Bar & Kitchen     
##  7 Thompson and Bleecker     
##  8 Creola Southern Steakhouse
##  9 Wings Over Ithaca         
## 10 Simeon's On The Commons   
##    image_url                                                           
##    <chr>                                                               
##  1 https://s3-media3.fl.yelpcdn.com/bphoto/HC9v38sBsVMz62uFKy8Y0A/o.jpg
##  2 https://s3-media2.fl.yelpcdn.com/bphoto/1AeybJBqPvyniCGL9sGMmg/o.jpg
##  3 https://s3-media4.fl.yelpcdn.com/bphoto/nbBvObp5AunbyrsP3GqtLA/o.jpg
##  4 https://s3-media2.fl.yelpcdn.com/bphoto/AGjFqTEa3EJzWwCLVkJaTw/o.jpg
##  5 https://s3-media3.fl.yelpcdn.com/bphoto/1OUhGwPRzZLlkwOTaTcjlQ/o.jpg
##  6 https://s3-media4.fl.yelpcdn.com/bphoto/YpkL8iviu0KXMOuKN_FY9Q/o.jpg
##  7 https://s3-media4.fl.yelpcdn.com/bphoto/Ccl2pjXgvKRRxZShz-O8ww/o.jpg
##  8 https://s3-media1.fl.yelpcdn.com/bphoto/iuBG6OD7__XRYmDHVAOADg/o.jpg
##  9 https://s3-media1.fl.yelpcdn.com/bphoto/S2oyB-RhWXDQfT6Hjb7Nxg/o.jpg
## 10 https://s3-media3.fl.yelpcdn.com/bphoto/rzrle6pCS_-gKKjZYFuN9A/o.jpg
##    is_closed
##    <lgl>    
##  1 FALSE    
##  2 FALSE    
##  3 FALSE    
##  4 FALSE    
##  5 FALSE    
##  6 FALSE    
##  7 FALSE    
##  8 FALSE    
##  9 FALSE    
## 10 FALSE    
##    url                                                                          
##    <chr>                                                                        
##  1 https://www.yelp.com/biz/gola-osteria-ithaca?adjust_creative=NJjwKPgIcFpchzB…
##  2 https://www.yelp.com/biz/ithaca-ale-house-ithaca?adjust_creative=NJjwKPgIcFp…
##  3 https://www.yelp.com/biz/de-tasty-hot-pot-ithaca-2?adjust_creative=NJjwKPgIc…
##  4 https://www.yelp.com/biz/reds-place-ithaca?adjust_creative=NJjwKPgIcFpchzBhk…
##  5 https://www.yelp.com/biz/le-cafe-cent-dix-ithaca-2?adjust_creative=NJjwKPgIc…
##  6 https://www.yelp.com/biz/mercato-bar-and-kitchen-ithaca?adjust_creative=NJjw…
##  7 https://www.yelp.com/biz/thompson-and-bleecker-ithaca-2?adjust_creative=NJjw…
##  8 https://www.yelp.com/biz/creola-southern-steakhouse-ithaca?adjust_creative=N…
##  9 https://www.yelp.com/biz/wings-over-ithaca-ithaca-3?adjust_creative=NJjwKPgI…
## 10 https://www.yelp.com/biz/simeons-on-the-commons-ithaca?adjust_creative=NJjwK…
##    review_count categories   rating coordinates$latitude $longitude transactions
##           <int> <list>        <dbl>                <dbl>      <dbl> <list>      
##  1          169 <df [2 × 2]>    4                   42.4      -76.5 <chr [1]>   
##  2          586 <df [3 × 2]>    3.9                 42.4      -76.5 <chr [1]>   
##  3          125 <df [3 × 2]>    3.4                 42.4      -76.5 <chr [2]>   
##  4          271 <df [2 × 2]>    3.9                 42.4      -76.5 <chr [1]>   
##  5          120 <df [3 × 2]>    4.6                 42.4      -76.5 <chr [1]>   
##  6          179 <df [2 × 2]>    4.1                 42.4      -76.5 <chr [1]>   
##  7          184 <df [3 × 2]>    4.4                 42.4      -76.5 <chr [1]>   
##  8           43 <df [2 × 2]>    4.3                 42.4      -76.5 <chr [1]>   
##  9           91 <df [3 × 2]>    3.9                 42.4      -76.5 <chr [2]>   
## 10          294 <df [3 × 2]>    3.8                 42.4      -76.5 <chr [1]>   
##    price location$address1   $address2 $address3 $city  $zip_code $country
##    <chr> <chr>               <chr>     <chr>     <chr>  <chr>     <chr>   
##  1 $$$   115 South Quarry St ""        ""        Ithaca 14850     US      
##  2 $$    301 East State St   "Ste 1"   ""        Ithaca 14850     US      
##  3 $$    422 Eddy St         ""        ""        Ithaca 14850     US      
##  4 $$    107 N Aurora St     ""        ""        Ithaca 14850     US      
##  5 $$$   110 N Aurora St      <NA>     ""        Ithaca 14850     US      
##  6 $$$   108 N Aurora St     ""        ""        Ithaca 14850     US      
##  7 $$    211 E Seneca St      <NA>     ""        Ithaca 14850     US      
##  8 <NA>  112 N Aurora St     ""        <NA>      Ithaca 14850     US      
##  9 $$    121 Dryden Rd        <NA>     ""        Ithaca 14850     US      
## 10 $$    224 E State St      ""        ""        Ithaca 14850     US      
##    $state $display_address phone        display_phone  distance business_hours
##    <chr>  <list>           <chr>        <chr>             <dbl> <list>        
##  1 NY     <chr [2]>        +16072730333 (607) 273-0333     393. <df [1 × 3]>  
##  2 NY     <chr [3]>        +16072567977 (607) 256-7977     525. <df [1 × 3]>  
##  3 NY     <chr [2]>        +16078212312 (607) 821-2312     231. <df [1 × 3]>  
##  4 NY     <chr [2]>        +16073194486 (607) 319-4486     545. <df [1 × 3]>  
##  5 NY     <chr [2]>        +16073190750 (607) 319-0750     567. <df [1 × 3]>  
##  6 NY     <chr [2]>        +16073195171 (607) 319-5171     577. <df [1 × 3]>  
##  7 NY     <chr [2]>        +16073190851 (607) 319-0851     594. <df [1 × 3]>  
##  8 NY     <chr [2]>        +16072721438 (607) 272-1438     575. <df [1 × 3]>  
##  9 NY     <chr [2]>        +16073194664 (607) 319-4664     237. <df [1 × 3]>  
## 10 NY     <chr [2]>        +16072722212 (607) 272-2212     573. <df [1 × 3]>  
##    attributes$business_temp_closed $menu_url                             
##    <lgl>                           <chr>                                 
##  1 NA                              "https://golaosteria.com/menubkp"     
##  2 NA                              "http://www.ithacaalehouse.com/menu"  
##  3 NA                              "http://www.tastyhotpot.com/menu"     
##  4 NA                              "http://www.redsplaceithaca.com/menu/"
##  5 NA                              "https://www.lecafecentdix.com/menu"  
##  6 NA                              ""                                    
##  7 NA                               <NA>                                 
##  8 NA                               <NA>                                 
##  9 NA                              "https://www.wingsover.com/menu"      
## 10 NA                              ""                                    
##    $open24_hours $waitlist_reservation
##    <lgl>         <lgl>                
##  1 NA            NA                   
##  2 NA            NA                   
##  3 NA            NA                   
##  4 NA            NA                   
##  5 NA            NA                   
##  6 NA            NA                   
##  7 NA            NA                   
##  8 NA            TRUE                 
##  9 NA            NA                   
## 10 NA            NA                   
## # ℹ 1,439 more rows
yelp_all2 %>% print(width=1000)
## # A tibble: 103 × 18
##    id                     alias                          name                   
##    <chr>                  <chr>                          <chr>                  
##  1 jDsvWSwti8oL2qAIWp7noA bools-flower-shop-ithaca       Bool's Flower Shop     
##  2 UHDpAts-5yibQ1nedxGucA melodia-flowers-ithaca         Melodia Flowers        
##  3 lUNuOGkS43qKGe_PRtrEJQ willow-floral-studios-no-title Willow Floral Studios  
##  4 MFpBoQIK8MkBX9wxyFlUpg best-in-bloom-syracuse-2       Best in Bloom          
##  5 UHDpAts-5yibQ1nedxGucA melodia-flowers-ithaca         Melodia Flowers        
##  6 vXwTHb4ejO5Jm-FEhPjtnw sunny-days-ithaca-2            Sunny Days             
##  7 hVTDbmucYcA3hMYvoPWYDA mockingbird-paperie-ithaca     Mockingbird Paperie    
##  8 jDsvWSwti8oL2qAIWp7noA bools-flower-shop-ithaca       Bool's Flower Shop     
##  9 RGvfeizEiZgHC4GkFm8I6Q 3-d-light-loose-threads-ithaca 3-D Light-Loose Threads
## 10 b8QWnAKo4EnZpYckAZwS_g ithacamade-ithaca              Ithacamade             
##    image_url                                                           
##    <chr>                                                               
##  1 https://s3-media2.fl.yelpcdn.com/bphoto/Kd4czZCdJsBc1vuyE8MxEg/o.jpg
##  2 https://s3-media1.fl.yelpcdn.com/bphoto/QeByo90bX5ZOPA4Dzs8www/o.jpg
##  3 https://s3-media1.fl.yelpcdn.com/bphoto/nZMB9h0Myb6IF9vpYtVhUA/o.jpg
##  4 https://s3-media2.fl.yelpcdn.com/bphoto/8-WgnUN6BRnSu9ddE8UK3Q/o.jpg
##  5 https://s3-media1.fl.yelpcdn.com/bphoto/QeByo90bX5ZOPA4Dzs8www/o.jpg
##  6 https://s3-media2.fl.yelpcdn.com/bphoto/LsJVRiU5jieaiRVVsZm-Lg/o.jpg
##  7 https://s3-media3.fl.yelpcdn.com/bphoto/L2aznWmRtwrDGJuEIRd9Zw/o.jpg
##  8 https://s3-media2.fl.yelpcdn.com/bphoto/Kd4czZCdJsBc1vuyE8MxEg/o.jpg
##  9 https://s3-media1.fl.yelpcdn.com/bphoto/YfEdV-xQZ8eSaHoqBYQnpw/o.jpg
## 10 https://s3-media2.fl.yelpcdn.com/bphoto/orEte5AdbffixTIXzIZoTg/o.jpg
##    is_closed
##    <lgl>    
##  1 FALSE    
##  2 FALSE    
##  3 FALSE    
##  4 FALSE    
##  5 FALSE    
##  6 FALSE    
##  7 FALSE    
##  8 FALSE    
##  9 FALSE    
## 10 FALSE    
##    url                                                                          
##    <chr>                                                                        
##  1 https://www.yelp.com/biz/bools-flower-shop-ithaca?adjust_creative=NJjwKPgIcF…
##  2 https://www.yelp.com/biz/melodia-flowers-ithaca?adjust_creative=NJjwKPgIcFpc…
##  3 https://www.yelp.com/biz/willow-floral-studios-no-title?adjust_creative=NJjw…
##  4 https://www.yelp.com/biz/best-in-bloom-syracuse-2?adjust_creative=NJjwKPgIcF…
##  5 https://www.yelp.com/biz/melodia-flowers-ithaca?adjust_creative=NJjwKPgIcFpc…
##  6 https://www.yelp.com/biz/sunny-days-ithaca-2?adjust_creative=NJjwKPgIcFpchzB…
##  7 https://www.yelp.com/biz/mockingbird-paperie-ithaca?adjust_creative=NJjwKPgI…
##  8 https://www.yelp.com/biz/bools-flower-shop-ithaca?adjust_creative=NJjwKPgIcF…
##  9 https://www.yelp.com/biz/3-d-light-loose-threads-ithaca?adjust_creative=NJjw…
## 10 https://www.yelp.com/biz/ithacamade-ithaca?adjust_creative=NJjwKPgIcFpchzBhk…
##    review_count categories   rating coordinates$latitude $longitude transactions
##           <int> <list>        <dbl>                <dbl>      <dbl> <list>      
##  1           23 <df [1 × 2]>    4.1                 42.4      -76.5 <list [0]>  
##  2            0 <df [2 × 2]>    0                   42.4      -76.5 <list [0]>  
##  3            2 <df [2 × 2]>    5                   42.5      -76.5 <list [0]>  
##  4            0 <df [1 × 2]>    0                   43.1      -76.1 <list [0]>  
##  5            0 <df [2 × 2]>    0                   42.4      -76.5 <list [0]>  
##  6           34 <df [3 × 2]>    4.9                 42.4      -76.5 <list [0]>  
##  7           15 <df [3 × 2]>    3.8                 42.4      -76.5 <list [0]>  
##  8           23 <df [1 × 2]>    4.1                 42.4      -76.5 <list [0]>  
##  9            3 <df [3 × 2]>    4                   42.4      -76.5 <list [0]>  
## 10            2 <df [3 × 2]>    4                   42.4      -76.5 <list [0]>  
##    price location$address1    $address2  $address3 $city    $zip_code $country
##    <chr> <chr>                <chr>      <chr>     <chr>    <chr>     <chr>   
##  1 $$    209 N Aurora St      ""         ""        Ithaca   14850     US      
##  2 <NA>  105 Valley Rd         <NA>      ""        Ithaca   14850     US      
##  3 <NA>  2255 N Triphammer Rd  <NA>      ""        Ithaca   14850     US      
##  4 <NA>  6181 Thompson Rd     "Ste 400L" ""        Syracuse 13206     US      
##  5 <NA>  105 Valley Rd         <NA>      ""        Ithaca   14850     US      
##  6 $$    171 E State St 100   ""         ""        Ithaca   14850     US      
##  7 $$    144 E State St       ""         ""        Ithaca   14850     US      
##  8 $$    209 N Aurora St      ""         ""        Ithaca   14850     US      
##  9 <NA>  118 The Commons      ""         ""        Ithaca   14850     US      
## 10 <NA>  215 N Cayuga St      ""         ""        Ithaca   14850     US      
##    $state $display_address phone          display_phone    distance
##    <chr>  <list>           <chr>          <chr>               <dbl>
##  1 NY     <chr [2]>        "+16072728410" "(607) 272-8410"     532.
##  2 NY     <chr [2]>        "+19195970187" "(919) 597-0187"     672.
##  3 NY     <chr [2]>        "+16073390004" "(607) 339-0004"    6332.
##  4 NY     <chr [3]>        "+13157410220" "(315) 741-0220"   79110.
##  5 NY     <chr [2]>        "+19195970187" "(919) 597-0187"    1637.
##  6 NY     <chr [2]>        "+16073195260" "(607) 319-5260"     150.
##  7 NY     <chr [2]>        "+16073190556" "(607) 319-0556"     104.
##  8 NY     <chr [2]>        "+16072728410" "(607) 272-8410"     299.
##  9 NY     <chr [2]>        ""             ""                   153.
## 10 NY     <chr [2]>        "+16072721396" "(607) 272-1396"     128.
##    business_hours attributes$business_temp_closed $open24_hours
##    <list>         <lgl>                           <lgl>        
##  1 <df [1 × 3]>   NA                              NA           
##  2 <df [1 × 3]>   NA                              NA           
##  3 <df [1 × 3]>   NA                              NA           
##  4 <df [1 × 3]>   NA                              NA           
##  5 <df [1 × 3]>   NA                              NA           
##  6 <df [1 × 3]>   NA                              NA           
##  7 <df [1 × 3]>   NA                              NA           
##  8 <df [1 × 3]>   NA                              NA           
##  9 <df [1 × 3]>   NA                              NA           
## 10 <df [1 × 3]>   NA                              NA           
##    $waitlist_reservation $menu_url
##    <lgl>                 <lgl>    
##  1 NA                    NA       
##  2 NA                    NA       
##  3 NA                    NA       
##  4 NA                    NA       
##  5 NA                    NA       
##  6 NA                    NA       
##  7 NA                    NA       
##  8 NA                    NA       
##  9 NA                    NA       
## 10 NA                    NA       
## # ℹ 93 more rows

Analysis

As noted in the table above, there are 1534 businesses in Ithaca in total. For each category, there are 1449 restaurants and 103 flowers & gifts shops in Ithaca. Based on the map below, most of the popular restaurants and flowers shop cluster in the area between E SENECA ST and E GREEN ST.

# Extract coordinates
yelp_sf1 <- yelp_all1 %>% 
  mutate(x = .$coordinates$longitude,
         y = .$coordinates$latitude) %>% 
  filter(!is.na(x) & !is.na(y)) %>% 
  st_as_sf(coords = c("x", "y"), crs = 4326)

yelp_sf2 <- yelp_all2 %>% 
  mutate(x = .$coordinates$longitude,
         y = .$coordinates$latitude) %>% 
  filter(!is.na(x) & !is.na(y)) %>% 
  st_as_sf(coords = c("x", "y"), crs = 4326)

# Map
tm_shape(yelp_sf1) +
  tm_dots(col = "review_count", palette = "Blues", style = "quantile", size = 0.1, alpha = 0.7, title = "Restaurants Review Count") +  # Blue gradient for yelp_sf1
tm_shape(yelp_sf2) +
  tm_dots(col = "review_count", palette = "Reds", style = "quantile", size = 0.1, alpha = 0.7, title = "Flowers & Gifts Review Count") +  # Red gradient for yelp_sf2
tm_layout(legend.outside = TRUE)  # Place legend outside the map
save(yelp_sf1, yelp_sf2, file="mini1_data.RData")