#### Tract polygons for the Yelp query
tract <-suppressMessages(
get_acs(geography = "tract", # or "block group", "county", "state" etc.
state = "GA",
county = c("White"),
variables = c(hhincome = 'B19019_001'),
year = 2022,
survey = "acs5", # American Community Survey 5-year estimate
geometry = TRUE, # returns sf objects
output = "wide")) # wide vs. long
# pull city boundaries
helen <- tigris::places('GA') %>% #tigris lets us pull city boundaries which census doesn't have
filter(NAME == 'Helen')
## Retrieving data for the year 2022
# pull tracts within city boundaries
tract_helen <- tract[helen,]
# select fewer columns
tract_helen <- tract_helen %>%
select(GEOID,
hhincome = hhincomeE)
# view city boundaries
tmap_mode("view")
## tmap mode set to interactive viewing
tm_shape(tract_helen) + tm_borders(lwd = 2) +
tm_shape(helen) + 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_helen))
# Starting a for-loop
for (i in 1:nrow(tract_helen)){
r4all_loop[[i]] <- tract_helen %>%
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_helen %>%
st_geometry() %>%
st_transform(crs = epsg_id) %>%
lapply(., function(x) get_r(x, epsg_id = epsg_id))
r4all_apply <- bind_rows(r4all_apply)
# Appending X Y coordinates as seprate columns
ready_4_yelp <- r4all_apply %>%
mutate(x = st_coordinates(.)[,1],
y = st_coordinates(.)[,2])
# check the buffers
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_helen) + tm_borders(col= 'blue')
## Get Yelp Data
which_tract <- 2
test <- business_search(api_key = Sys.getenv('yelp_api_key'), # like we did for census, store your api key
categories = 'localservices', # 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 8sI2EtjEu6_wgcxBIiw_pA planned-pethood-duluth-2
## 2 VqPyg5Vh-ukzpXE55-1F2w carpet-savers-lakemont-3
## 3 NQuHP24Zrf3UYltD5jt2gg on-the-move-flowery-branch
## 4 ZMXmsMMPHaD5JO3zyUu2uw aquarium-and-shark-lab-by-team-ecco-hendersonville-2
## 5 _7tLry_qnZwTIKHtvJ66dQ chris-motes-pumping-service-cleveland
## 6 FKT3ucAzns9-p-k_jp1a4g gilstrap-exterminating-dawsonville-2
## name
## 1 Planned PEThood
## 2 Carpet Savers
## 3 On The Move
## 4 Aquarium & Shark Lab by Team ECCO
## 5 Chris Mote's Pumping Service
## 6 Gilstrap Exterminating
## image_url
## 1 https://s3-media3.fl.yelpcdn.com/bphoto/vjz6KCBwXNup59nMFuw4-w/o.jpg
## 2 https://s3-media1.fl.yelpcdn.com/bphoto/-zZe8Ig9adbcqzUesY47VA/o.jpg
## 3 https://s3-media1.fl.yelpcdn.com/bphoto/6G8zpQ-d-KDZJe_MtLbSag/o.jpg
## 4 https://s3-media4.fl.yelpcdn.com/bphoto/jnks6ZOpW8Vdc4svLHQDRQ/o.jpg
## 5 https://s3-media1.fl.yelpcdn.com/bphoto/QZqEHFE2N2-Xu9vHAhfPKQ/o.jpg
## 6 https://s3-media4.fl.yelpcdn.com/bphoto/ckr9n7KByAxCbzQGw1qRdg/o.jpg
## is_closed
## 1 FALSE
## 2 FALSE
## 3 FALSE
## 4 FALSE
## 5 FALSE
## 6 FALSE
## url
## 1 https://www.yelp.com/biz/planned-pethood-duluth-2?adjust_creative=P_ibNlpy71Wj-TC2vsUAew&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=P_ibNlpy71Wj-TC2vsUAew
## 2 https://www.yelp.com/biz/carpet-savers-lakemont-3?adjust_creative=P_ibNlpy71Wj-TC2vsUAew&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=P_ibNlpy71Wj-TC2vsUAew
## 3 https://www.yelp.com/biz/on-the-move-flowery-branch?adjust_creative=P_ibNlpy71Wj-TC2vsUAew&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=P_ibNlpy71Wj-TC2vsUAew
## 4 https://www.yelp.com/biz/aquarium-and-shark-lab-by-team-ecco-hendersonville-2?adjust_creative=P_ibNlpy71Wj-TC2vsUAew&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=P_ibNlpy71Wj-TC2vsUAew
## 5 https://www.yelp.com/biz/chris-motes-pumping-service-cleveland?adjust_creative=P_ibNlpy71Wj-TC2vsUAew&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=P_ibNlpy71Wj-TC2vsUAew
## 6 https://www.yelp.com/biz/gilstrap-exterminating-dawsonville-2?adjust_creative=P_ibNlpy71Wj-TC2vsUAew&utm_campaign=yelp_api_v3&utm_medium=api_v3_business_search&utm_source=P_ibNlpy71Wj-TC2vsUAew
## review_count
## 1 62
## 2 12
## 3 23
## 4 25
## 5 5
## 6 12
## categories
## 1 vet, nonprofit, Veterinarians, Community Service/Non-Profit
## 2 carpet_cleaning, Carpet Cleaning
## 3 movers, selfstorage, packingservices, Movers, Self Storage, Packing Services
## 4 nonprofit, aquariums, Community Service/Non-Profit, Aquariums
## 5 septicservices, Septic Services
## 6 pest_control, wildlifecontrol, Pest Control, Wildlife Control
## rating coordinates.latitude coordinates.longitude transactions
## 1 4.5 34.00646 -84.13470 NULL
## 2 5.0 34.77966 -83.39705 NULL
## 3 4.1 34.21471 -83.88878 NULL
## 4 4.3 35.31794 -82.46090 NULL
## 5 4.8 34.63543 -83.84629 NULL
## 6 4.1 34.36337 -84.04568 NULL
## location.address1 location.address2 location.address3 location.city
## 1 2860 Buford Hwy Duluth
## 2 <NA> <NA> <NA> Lakemont
## 3 4050 Enterprise Way Ste 180 <NA> Flowery Branch
## 4 511 N Main St <NA> <NA> Hendersonville
## 5 669 Paradise Valley Rd <NA> <NA> Cleveland
## 6 30 Industrial Park Rd Ste 103 Dawsonville
## location.zip_code location.country location.state
## 1 30096 US GA
## 2 30552 US GA
## 3 30542 US GA
## 4 28792 US NC
## 5 30528 US GA
## 6 30534 US GA
## location.display_address phone
## 1 2860 Buford Hwy, Duluth, GA 30096 +16785613491
## 2 Lakemont, GA 30552 +17067820279
## 3 4050 Enterprise Way, Ste 180, Flowery Branch, GA 30542 +17069730175
## 4 511 N Main St, Hendersonville, NC 28792 +18286928386
## 5 669 Paradise Valley Rd, Cleveland, GA 30528 +17068655526
## 6 30 Industrial Park Rd, Ste 103, Dawsonville, GA 30534 +16786974430
## display_phone distance
## 1 (678) 561-3491 90373.22
## 2 (706) 782-0279 28672.94
## 3 (706) 973-0175 60943.17
## 4 (828) 692-8386 131648.63
## 5 (706) 865-5526 16454.69
## 6 (678) 697-4430 51617.01
## business_hours
## 1 FALSE, FALSE, FALSE, FALSE, 0700, 0700, 0700, 0700, 1630, 1630, 1630, 1630, 0, 1, 2, 3, REGULAR, FALSE
## 2 TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, 0, 1, 2, 3, 4, 5, 6, REGULAR, TRUE
## 3 FALSE, FALSE, FALSE, FALSE, FALSE, 0800, 0800, 0800, 0800, 0800, 1700, 1700, 1700, 1700, 1700, 0, 1, 2, 3, 4, REGULAR, FALSE
## 4 FALSE, FALSE, FALSE, 1300, 1300, 1300, 1600, 1600, 1600, 3, 4, 5, REGULAR, FALSE
## 5 FALSE, FALSE, FALSE, FALSE, FALSE, 0800, 0800, 0800, 0800, 0800, 1700, 1700, 1700, 1700, 1700, 0, 1, 2, 3, 4, REGULAR, FALSE
## 6 FALSE, FALSE, FALSE, FALSE, FALSE, 0800, 0800, 0800, 0800, 0800, 1700, 1700, 1700, 1700, 1700, 0, 1, 2, 3, 4, REGULAR, FALSE
## attributes.business_temp_closed attributes.waitlist_reservation
## 1 NA NA
## 2 NA NA
## 3 NA NA
## 4 NA NA
## 5 NA NA
## 6 NA NA
## attributes.open24_hours
## 1 NA
## 2 NA
## 3 NA
## 4 NA
## 5 NA
## 6 NA
##
## $total
## [1] 162
##
## $region
## $region$center
## $region$center$longitude
## [1] -83.72712
##
## $region$center$latitude
## [1] 34.7463
names(test)
## [1] "businesses" "total" "region"
test$total
## [1] 162
ceiling(test$total/50)
## [1] 4
# 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?: 50, how many columns?: 17"
# FUNCTION to get more than 50
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_key"),
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_key"),
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_tract <- get_yelp(ready_4_yelp[1,], "localservices") %>%
as_tibble()
## No encoding supplied: defaulting to UTF-8.
## No encoding supplied: defaulting to UTF-8.
## No encoding supplied: defaulting to UTF-8.
## No encoding supplied: defaulting to UTF-8.
# Print
yelp_first_tract %>% print
## # A tibble: 166 × 17
## id alias name image_url is_closed url review_count categories rating
## <chr> <chr> <chr> <chr> <lgl> <chr> <int> <list> <dbl>
## 1 8sI2Etj… plan… "Pla… https://… FALSE http… 62 <df> 4.5
## 2 VqPyg5V… carp… "Car… https://… FALSE http… 12 <df> 5
## 3 NQuHP24… on-t… "On … https://… FALSE http… 23 <df> 4.1
## 4 ZMXmsMM… aqua… "Aqu… https://… FALSE http… 25 <df> 4.3
## 5 FKT3ucA… gils… "Gil… https://… FALSE http… 12 <df> 4.1
## 6 _7tLry_… chri… "Chr… https://… FALSE http… 5 <df> 4.8
## 7 JpTBXer… sept… "Sep… https://… FALSE http… 5 <df> 5
## 8 nWKZ1bx… peac… "Pea… https://… FALSE http… 2 <df> 5
## 9 HAO_gNQ… ace1… "Ace… https://… FALSE http… 5 <df> 4.2
## 10 _MfGVua… pelo… "Pel… https://… FALSE http… 4 <df> 4
## # ℹ 156 more rows
## # ℹ 8 more variables: coordinates <df[,2]>, transactions <list>,
## # location <df[,8]>, phone <chr>, display_phone <chr>, distance <dbl>,
## # business_hours <list>, attributes <df[,3]>
# Pull yelp data for first category: localservices
# Prepare a collector
yelp_all_list1 <- vector("list", nrow(ready_4_yelp))
# Looping through all Census Tracts
for (row in 1:nrow(ready_4_yelp)){
yelp_all_list1[[row]] <- suppressMessages(get_yelp(ready_4_yelp[row,], "localservices"))
print(paste0("Current row: ", row))
}
## [1] "Current row: 1"
## [1] "Current row: 2"
# Collapsing the list into a data.frame
yelp_all1 <- yelp_all_list1 %>% bind_rows() %>% as_tibble()
# print
yelp_all1 %>% print(width=1000)
## # A tibble: 328 × 17
## id
## <chr>
## 1 8sI2EtjEu6_wgcxBIiw_pA
## 2 VqPyg5Vh-ukzpXE55-1F2w
## 3 NQuHP24Zrf3UYltD5jt2gg
## 4 ZMXmsMMPHaD5JO3zyUu2uw
## 5 FKT3ucAzns9-p-k_jp1a4g
## 6 _7tLry_qnZwTIKHtvJ66dQ
## 7 JpTBXern4L7NUTZpYv9Wpg
## 8 nWKZ1bx0bi9VipWe_eoOQw
## 9 HAO_gNQdD6s7zg6pzf-fOQ
## 10 _MfGVuaHrt7Gh48z-RNs7A
## alias
## <chr>
## 1 planned-pethood-duluth-2
## 2 carpet-savers-lakemont-3
## 3 on-the-move-flowery-branch
## 4 aquarium-and-shark-lab-by-team-ecco-hendersonville-2
## 5 gilstrap-exterminating-dawsonville-2
## 6 chris-motes-pumping-service-cleveland
## 7 septicxperts-dahlonega-2
## 8 peachy-pine-couture-gainesville-4
## 9 ace10-home-services-flowery-branch
## 10 pelorus-inspection-and-environmental-resource-group-atlanta
## name
## <chr>
## 1 "Planned PEThood"
## 2 "Carpet Savers"
## 3 "On The Move"
## 4 "Aquarium & Shark Lab by Team ECCO"
## 5 "Gilstrap Exterminating"
## 6 "Chris Mote's Pumping Service"
## 7 "SepticXperts "
## 8 "Peachy Pine Couture"
## 9 "Ace10 Home Services"
## 10 "Pelorus Inspection & Environmental Resource Group"
## image_url
## <chr>
## 1 https://s3-media3.fl.yelpcdn.com/bphoto/vjz6KCBwXNup59nMFuw4-w/o.jpg
## 2 https://s3-media1.fl.yelpcdn.com/bphoto/-zZe8Ig9adbcqzUesY47VA/o.jpg
## 3 https://s3-media1.fl.yelpcdn.com/bphoto/6G8zpQ-d-KDZJe_MtLbSag/o.jpg
## 4 https://s3-media4.fl.yelpcdn.com/bphoto/jnks6ZOpW8Vdc4svLHQDRQ/o.jpg
## 5 https://s3-media4.fl.yelpcdn.com/bphoto/ckr9n7KByAxCbzQGw1qRdg/o.jpg
## 6 https://s3-media1.fl.yelpcdn.com/bphoto/QZqEHFE2N2-Xu9vHAhfPKQ/o.jpg
## 7 https://s3-media2.fl.yelpcdn.com/bphoto/L3b8hdNv2M38LoYp318Prg/o.jpg
## 8 https://s3-media2.fl.yelpcdn.com/bphoto/h_Ft6_0XOSmLhaKIcwZ6PA/o.jpg
## 9 https://s3-media1.fl.yelpcdn.com/bphoto/hVopulrRds5hti3RjPzxpg/o.jpg
## 10 https://s3-media1.fl.yelpcdn.com/bphoto/s4o71EIk8Ca-RZjn1aGh9g/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/planned-pethood-duluth-2?adjust_creative=P_ibNlpy71…
## 2 https://www.yelp.com/biz/carpet-savers-lakemont-3?adjust_creative=P_ibNlpy71…
## 3 https://www.yelp.com/biz/on-the-move-flowery-branch?adjust_creative=P_ibNlpy…
## 4 https://www.yelp.com/biz/aquarium-and-shark-lab-by-team-ecco-hendersonville-…
## 5 https://www.yelp.com/biz/gilstrap-exterminating-dawsonville-2?adjust_creativ…
## 6 https://www.yelp.com/biz/chris-motes-pumping-service-cleveland?adjust_creati…
## 7 https://www.yelp.com/biz/septicxperts-dahlonega-2?adjust_creative=P_ibNlpy71…
## 8 https://www.yelp.com/biz/peachy-pine-couture-gainesville-4?adjust_creative=P…
## 9 https://www.yelp.com/biz/ace10-home-services-flowery-branch?adjust_creative=…
## 10 https://www.yelp.com/biz/pelorus-inspection-and-environmental-resource-group…
## review_count categories rating coordinates$latitude $longitude transactions
## <int> <list> <dbl> <dbl> <dbl> <list>
## 1 62 <df [2 × 2]> 4.5 34.0 -84.1 <list [0]>
## 2 12 <df [1 × 2]> 5 34.8 -83.4 <list [0]>
## 3 23 <df [3 × 2]> 4.1 34.2 -83.9 <list [0]>
## 4 25 <df [2 × 2]> 4.3 35.3 -82.5 <list [0]>
## 5 12 <df [2 × 2]> 4.1 34.4 -84.0 <list [0]>
## 6 5 <df [1 × 2]> 4.8 34.6 -83.8 <list [0]>
## 7 5 <df [1 × 2]> 5 34.5 -83.9 <list [0]>
## 8 2 <df [1 × 2]> 5 34.3 -83.8 <list [0]>
## 9 5 <df [2 × 2]> 4.2 34.2 -83.9 <list [0]>
## 10 4 <df [2 × 2]> 4 33.9 -84.3 <list [0]>
## location$address1 $address2 $address3 $city $zip_code
## <chr> <chr> <chr> <chr> <chr>
## 1 "2860 Buford Hwy" "" "" Duluth 30096
## 2 <NA> <NA> <NA> Lakemont 30552
## 3 "4050 Enterprise Way" "Ste 180" <NA> Flowery Branch 30542
## 4 "511 N Main St" <NA> <NA> Hendersonville 28792
## 5 "30 Industrial Park Rd" "Ste 103" "" Dawsonville 30534
## 6 "669 Paradise Valley Rd" <NA> <NA> Cleveland 30528
## 7 "326 Meeks Rd" <NA> <NA> Dahlonega 30533
## 8 <NA> <NA> "" Gainesville 30501
## 9 "" <NA> "" Flowery Branch 30542
## 10 <NA> <NA> <NA> Atlanta 30341
## $country $state $display_address phone display_phone distance
## <chr> <chr> <list> <chr> <chr> <dbl>
## 1 US GA <chr [2]> +16785613491 (678) 561-3491 86015.
## 2 US GA <chr [1]> +17067820279 (706) 782-0279 28045.
## 3 US GA <chr [3]> +17069730175 (706) 973-0175 55857.
## 4 US NC <chr [2]> +18286928386 (828) 692-8386 132794.
## 5 US GA <chr [3]> +16786974430 (678) 697-4430 48247.
## 6 US GA <chr [2]> +17068655526 (706) 865-5526 14552.
## 7 US GA <chr [2]> +17063004264 (706) 300-4264 30498.
## 8 US GA <chr [1]> +16787943877 (678) 794-3877 42820.
## 9 US GA <chr [1]> +16786301000 (678) 630-1000 60049.
## 10 US GA <chr [1]> +16787771559 (678) 777-1559 103990.
## business_hours attributes$business_temp_closed $waitlist_reservation
## <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
## $open24_hours
## <lgl>
## 1 NA
## 2 NA
## 3 NA
## 4 NA
## 5 NA
## 6 NA
## 7 NA
## 8 NA
## 9 NA
## 10 NA
## # ℹ 318 more rows
# Pull yelp data for second category: food
# Prepare a collector
yelp_all_list2 <- vector("list", nrow(ready_4_yelp))
# Looping through all Census Tracts
for (row in 1:nrow(ready_4_yelp)){
yelp_all_list2[[row]] <- suppressMessages(get_yelp(ready_4_yelp[row,], "food"))
print(paste0("Current row: ", row))
}
## [1] "Current row: 1"
## [1] "Current row: 2"
# Collapsing the list into a data.frame
yelp_all2 <- yelp_all_list2 %>% bind_rows() %>% as_tibble()
# print
yelp_all2 %>% print(width=1000)
## # A tibble: 143 × 18
## id alias
## <chr> <chr>
## 1 q8PIbaDALX2Wp3JhN9qtvg hofers-bakery-and-cafe-helen
## 2 xd3BFjzntYfGVYHml1GCyg harvest-habersham-sautee-nacoochee
## 3 YvyU9F8z9qj7Le_7i56GAw das-ice-cream-cafe-helen
## 4 jsnHcL1tBOL878T46ervcw sweetwater-coffeehouse-sautee-nacoochee
## 5 USsgR6qQW2YzvsR0jzYBSw nora-mill-granary-helen-2
## 6 BwqPl7gYvQV4WYzGutp4LA jumpingoat-coffee-roasters-helen
## 7 l_Im5mp3ylG7bWPKo-jvPg old-sautee-store-sautee-nacoochee-3
## 8 I19KavlBBVsBM-f6R9vZcQ yonah-coffee-helen
## 9 GYBgi39op2LxEKT7-xEG3w habersham-winery-helen
## 10 LCxek-4cB3FsIUIsH-HA8A hansel-and-gretel-candy-kitchen-helen-2
## name
## <chr>
## 1 Hofer's Bakery & Cafe
## 2 Harvest Habersham
## 3 Das Ice Cream Cafe
## 4 Sweetwater Coffeehouse
## 5 Nora Mill Granary
## 6 JumpinGoat Coffee Roasters
## 7 Old Sautee Store
## 8 Yonah Coffee
## 9 Habersham Winery
## 10 Hansel & Gretel Candy Kitchen
## image_url
## <chr>
## 1 https://s3-media4.fl.yelpcdn.com/bphoto/BBmcko9UYnKLE-ONZkWTqw/o.jpg
## 2 https://s3-media2.fl.yelpcdn.com/bphoto/SQGp5M9GYuCNzfrRs0hPgQ/o.jpg
## 3 https://s3-media3.fl.yelpcdn.com/bphoto/icgklA1YLsMxXhv6mAHUuQ/o.jpg
## 4 https://s3-media2.fl.yelpcdn.com/bphoto/Y4-Tzmd9Ftl_ukZKLkXhLQ/o.jpg
## 5 https://s3-media3.fl.yelpcdn.com/bphoto/9Lt-kqpNiBXbIkhKenAuKg/o.jpg
## 6 https://s3-media3.fl.yelpcdn.com/bphoto/gd87I1azlZCPEkbhL4QnNg/o.jpg
## 7 https://s3-media2.fl.yelpcdn.com/bphoto/GfUDDGFNbIa_Ldktzrf8Wg/o.jpg
## 8 https://s3-media2.fl.yelpcdn.com/bphoto/UEEH5rOhBTvVQWS7wI1RrA/o.jpg
## 9 https://s3-media2.fl.yelpcdn.com/bphoto/xfPnYpborvMceRiwS2-0lw/o.jpg
## 10 https://s3-media3.fl.yelpcdn.com/bphoto/OnlZSNs4LzldfjeMtlv40g/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/hofers-bakery-and-cafe-helen?adjust_creative=P_ibNl…
## 2 https://www.yelp.com/biz/harvest-habersham-sautee-nacoochee?adjust_creative=…
## 3 https://www.yelp.com/biz/das-ice-cream-cafe-helen?adjust_creative=P_ibNlpy71…
## 4 https://www.yelp.com/biz/sweetwater-coffeehouse-sautee-nacoochee?adjust_crea…
## 5 https://www.yelp.com/biz/nora-mill-granary-helen-2?adjust_creative=P_ibNlpy7…
## 6 https://www.yelp.com/biz/jumpingoat-coffee-roasters-helen?adjust_creative=P_…
## 7 https://www.yelp.com/biz/old-sautee-store-sautee-nacoochee-3?adjust_creative…
## 8 https://www.yelp.com/biz/yonah-coffee-helen?adjust_creative=P_ibNlpy71Wj-TC2…
## 9 https://www.yelp.com/biz/habersham-winery-helen?adjust_creative=P_ibNlpy71Wj…
## 10 https://www.yelp.com/biz/hansel-and-gretel-candy-kitchen-helen-2?adjust_crea…
## review_count categories rating coordinates$latitude $longitude transactions
## <int> <list> <dbl> <dbl> <dbl> <list>
## 1 682 <df [3 × 2]> 3.8 34.7 -83.7 <chr [0]>
## 2 30 <df [3 × 2]> 4.8 34.7 -83.7 <chr [1]>
## 3 57 <df [2 × 2]> 4.8 34.7 -83.7 <chr [0]>
## 4 169 <df [3 × 2]> 4.7 34.7 -83.7 <chr [0]>
## 5 43 <df [1 × 2]> 4.5 34.7 -83.7 <chr [0]>
## 6 53 <df [1 × 2]> 4.3 34.7 -83.7 <chr [0]>
## 7 64 <df [2 × 2]> 4.3 34.7 -83.7 <chr [0]>
## 8 110 <df [3 × 2]> 3.8 34.7 -83.7 <chr [0]>
## 9 130 <df [1 × 2]> 3.9 34.7 -83.7 <chr [0]>
## 10 81 <df [1 × 2]> 4 34.7 -83.7 <chr [0]>
## price location$address1 $address2 $address3 $city $zip_code
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 $$ 8758 N Main St "" "" Helen 30545
## 2 <NA> 2220 Ga Hwy 17 "" <NA> Sautee Nacoochee 30571
## 3 $$ 705 Brucken Strasse "Ste 108-A" <NA> Helen 30545
## 4 $ 2242 Hwy 17 "" "" Sautee Nacoochee 30571
## 5 $$ 7107 S Main St <NA> <NA> Helen 30545
## 6 $$ 7086 S Main St <NA> "" Helen 30545
## 7 $ 2315 Ga Hwy 17 "" "" Sautee Nacoochee 30571
## 8 $ 8650 N Main St "" <NA> Helen 30545
## 9 $$ 7025 S Main St "" "" Helen 30545
## 10 $$ 8078 S Main St "" "" Helen 30545
## $country $state $display_address phone display_phone distance
## <chr> <chr> <list> <chr> <chr> <dbl>
## 1 US GA <chr [2]> +17068788200 (706) 878-8200 2817.
## 2 US GA <chr [2]> +17067540056 (706) 754-0056 2763.
## 3 US GA <chr [3]> +17068787204 (706) 878-7204 1498.
## 4 US GA <chr [2]> +17068781521 (706) 878-1521 2792.
## 5 US GA <chr [2]> +17068782375 (706) 878-2375 799.
## 6 US GA <chr [2]> +18777974628 (877) 797-4628 794.
## 7 US GA <chr [2]> +17068782281 (706) 878-2281 2868.
## 8 US GA <chr [2]> +17068783229 (706) 878-3229 2642.
## 9 US GA <chr [2]> +17068789463 (706) 878-9463 906.
## 10 US GA <chr [2]> +17068782443 (706) 878-2443 1816.
## business_hours attributes$business_temp_closed
## <list> <lgl>
## 1 <df [1 × 3]> NA
## 2 <df [1 × 3]> NA
## 3 <df [1 × 3]> NA
## 4 <df [1 × 3]> NA
## 5 <df [1 × 3]> NA
## 6 <df [1 × 3]> NA
## 7 <df [1 × 3]> NA
## 8 <df [1 × 3]> NA
## 9 <df [1 × 3]> NA
## 10 <df [1 × 3]> NA
## $menu_url $open24_hours
## <chr> <lgl>
## 1 <NA> NA
## 2 <NA> NA
## 3 http://www.dasicecreamcafe.com NA
## 4 https://www.sweetwatercoffeehouse.com/menu NA
## 5 <NA> NA
## 6 <NA> NA
## 7 <NA> NA
## 8 https://yonahcoffeeandcafe.com/menu/ NA
## 9 <NA> NA
## 10 <NA> NA
## $waitlist_reservation
## <lgl>
## 1 NA
## 2 NA
## 3 NA
## 4 NA
## 5 NA
## 6 NA
## 7 NA
## 8 NA
## 9 NA
## 10 NA
## # ℹ 133 more rows
# combine the categories
yelp_all <- bind_rows(yelp_all1, yelp_all2)
# Extract coordinates
yelp_sf <- yelp_all %>%
mutate(x = .$coordinates$longitude,
y = .$coordinates$latitude) %>%
filter(!is.na(x) & !is.na(y)) %>%
st_as_sf(coords = c("x", "y"), crs = 4326)
# Map the full results
tm_shape(yelp_sf) +
tm_dots(col = "review_count", style="quantile")
Map 1. All Businesses
# map the local services
# 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)
# Map the full results
tm_shape(yelp_sf1) +
tm_dots(col = "review_count", style="quantile")
Map 2. Local Services Businesses
# map the local services
# Extract coordinates
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 the full results
tm_shape(yelp_sf2) +
tm_dots(col = "review_count", style="quantile")
Map 3. Food Businesses
Questions:
1. Which city did you choose? Helen, GA
2. How many businesses are there in total? 471
3. How many businesses are there for each business category?
Local services: 328
Food: 143
4. Upon visual inspection, can you see any noticeable spatial patterns
to the way they are distributed across the city (e.g., clustering of
businesses at some parts of the city)?
It looks like businesses are clustered on the Unicoi turnpike along the
Chattahoochee River which is where the most tourist-focused areas are.
When separating the businesses by category, the local services
businesses are more spread around the area, while the food businesses
are clustered in the tourist areas.