Load packages and print the session info

## Load packages
library(tidycensus)
library(sf)
## Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
library(tmap)
library(jsonlite)
library(tidyverse)
## ── Attaching packages
## ───────────────────────────────────────
## tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6      ✔ purrr   0.3.4 
## ✔ tibble  3.1.8      ✔ dplyr   1.0.10
## ✔ tidyr   1.2.1      ✔ stringr 1.4.1 
## ✔ readr   2.1.2      ✔ forcats 0.5.2 
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter()  masks stats::filter()
## ✖ purrr::flatten() masks jsonlite::flatten()
## ✖ dplyr::lag()     masks stats::lag()
library(httr)
library(jsonlite)
library(reshape2)
## 
## Attaching package: 'reshape2'
## 
## The following object is masked from 'package:tidyr':
## 
##     smiths
library(here)
## here() starts at C:/Users/iskim/Dropbox (GaTech)/2022-2023/2022 Fall/CP 8883 Intro to Urban Analytics/UA_module1
# devtools::install_github("OmaymaS/yelpr")
library(yelpr)
library(knitr)


## Session info
sessionInfo()
## R version 4.2.1 (2022-06-23 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 22000)
## 
## Matrix products: default
## 
## locale:
## [1] LC_COLLATE=English_United States.utf8 
## [2] LC_CTYPE=English_United States.utf8   
## [3] LC_MONETARY=English_United States.utf8
## [4] LC_NUMERIC=C                          
## [5] LC_TIME=English_United States.utf8    
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] knitr_1.40       yelpr_0.1.0      here_1.0.1       reshape2_1.4.4  
##  [5] httr_1.4.4       forcats_0.5.2    stringr_1.4.1    dplyr_1.0.10    
##  [9] purrr_0.3.4      readr_2.1.2      tidyr_1.2.1      tibble_3.1.8    
## [13] ggplot2_3.3.6    tidyverse_1.3.2  jsonlite_1.8.0   tmap_3.3-3      
## [17] sf_1.0-8         tidycensus_1.2.3
## 
## loaded via a namespace (and not attached):
##  [1] fs_1.5.2            lubridate_1.8.0     RColorBrewer_1.1-3 
##  [4] rprojroot_2.0.3     tools_4.2.1         backports_1.4.1    
##  [7] bslib_0.4.0         utf8_1.2.2          rgdal_1.5-32       
## [10] R6_2.5.1            KernSmooth_2.23-20  DBI_1.1.3          
## [13] colorspace_2.0-3    raster_3.5-29       withr_2.5.0        
## [16] sp_1.5-0            tidyselect_1.1.2    leaflet_2.1.1      
## [19] compiler_4.2.1      leafem_0.2.0        cli_3.4.0          
## [22] rvest_1.0.3         xml2_1.3.3          sass_0.4.2         
## [25] scales_1.2.1        classInt_0.4-7      proxy_0.4-27       
## [28] rappdirs_0.3.3      digest_0.6.29       foreign_0.8-82     
## [31] rmarkdown_2.16      base64enc_0.1-3     dichromat_2.0-0.1  
## [34] pkgconfig_2.0.3     htmltools_0.5.3     dbplyr_2.2.1       
## [37] fastmap_1.1.0       readxl_1.4.1        htmlwidgets_1.5.4  
## [40] rlang_1.0.5         rstudioapi_0.14     jquerylib_0.1.4    
## [43] generics_0.1.3      crosstalk_1.2.0     googlesheets4_1.0.1
## [46] magrittr_2.0.3      Rcpp_1.0.9          munsell_0.5.0      
## [49] fansi_1.0.3         abind_1.4-5         lifecycle_1.0.2    
## [52] terra_1.6-17        stringi_1.7.8       leafsync_0.1.0     
## [55] yaml_2.3.5          plyr_1.8.7          tmaptools_3.1-1    
## [58] grid_4.2.1          maptools_1.1-4      parallel_4.2.1     
## [61] crayon_1.5.1        lattice_0.20-45     haven_2.5.1        
## [64] stars_0.5-6         hms_1.1.2           pillar_1.8.1       
## [67] uuid_1.1-0          codetools_0.2-18    reprex_2.0.2       
## [70] XML_3.99-0.10       glue_1.6.2          evaluate_0.16      
## [73] modelr_0.1.9        png_0.1-7           vctrs_0.4.1        
## [76] tzdb_0.3.0          cellranger_1.1.0    gtable_0.3.1       
## [79] assertthat_0.2.1    cachem_1.0.6        xfun_0.32          
## [82] lwgeom_0.2-8        broom_1.0.1         e1071_1.7-11       
## [85] class_7.3-20        googledrive_2.0.0   viridisLite_0.4.1  
## [88] gargle_1.2.1        tigris_1.6.1        units_0.8-0        
## [91] ellipsis_0.3.2

Download tract polygons in Fulton County and Dekalb County for Yelp queries

## Load my Census API key
load(here('data', 'census_api_key.RData'))              # Load the API key save in my local machine
census_api_key(census.api.key) %>% suppressMessages()   # Activate the key in this R session
rm(census.api.key)                                      # Remove from the environment

## Download tract polygons in Fulton and Dekalb (Year = 2019)
tract <- get_acs(geography = "tract", 
                 state = "GA",
                 county = c("Fulton", "Dekalb"),
                 variables = c(workers = "B08006_001",               # SEX OF WORKERS BY MEANS OF TRANSPORTATION TO WORK: Total (Male and Female)
                               workers.bicycle.commute = "B08006_014"  # SEX OF WORKERS BY MEANS OF TRANSPORTATION TO WORK: Bicycle among Total (Male and Female)
                               ),
                 year = 2019,
                 survey = "acs5", 
                 geometry = T,    
                 output = "wide"  
                 ) %>% 
  suppressMessages()
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |=                                                                     |   1%
  |                                                                            
  |=                                                                     |   2%
  |                                                                            
  |==                                                                    |   3%
  |                                                                            
  |===                                                                   |   4%
  |                                                                            
  |====                                                                  |   5%
  |                                                                            
  |====                                                                  |   6%
  |                                                                            
  |=====                                                                 |   7%
  |                                                                            
  |======                                                                |   8%
  |                                                                            
  |======                                                                |   9%
  |                                                                            
  |=======                                                               |  10%
  |                                                                            
  |=======                                                               |  11%
  |                                                                            
  |========                                                              |  12%
  |                                                                            
  |=========                                                             |  12%
  |                                                                            
  |=========                                                             |  13%
  |                                                                            
  |==========                                                            |  14%
  |                                                                            
  |===========                                                           |  15%
  |                                                                            
  |============                                                          |  16%
  |                                                                            
  |============                                                          |  17%
  |                                                                            
  |============                                                          |  18%
  |                                                                            
  |=============                                                         |  19%
  |                                                                            
  |==============                                                        |  20%
  |                                                                            
  |===============                                                       |  21%
  |                                                                            
  |================                                                      |  22%
  |                                                                            
  |=================                                                     |  24%
  |                                                                            
  |=================                                                     |  25%
  |                                                                            
  |==================                                                    |  26%
  |                                                                            
  |===================                                                   |  27%
  |                                                                            
  |====================                                                  |  29%
  |                                                                            
  |=====================                                                 |  29%
  |                                                                            
  |======================                                                |  31%
  |                                                                            
  |=======================                                               |  32%
  |                                                                            
  |=======================                                               |  33%
  |                                                                            
  |========================                                              |  34%
  |                                                                            
  |=========================                                             |  36%
  |                                                                            
  |==========================                                            |  37%
  |                                                                            
  |==========================                                            |  38%
  |                                                                            
  |===========================                                           |  38%
  |                                                                            
  |============================                                          |  39%
  |                                                                            
  |=============================                                         |  41%
  |                                                                            
  |=============================                                         |  42%
  |                                                                            
  |==============================                                        |  43%
  |                                                                            
  |===============================                                       |  44%
  |                                                                            
  |================================                                      |  45%
  |                                                                            
  |=================================                                     |  47%
  |                                                                            
  |==================================                                    |  49%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |=====================================                                 |  52%
  |                                                                            
  |======================================                                |  54%
  |                                                                            
  |=======================================                               |  56%
  |                                                                            
  |========================================                              |  57%
  |                                                                            
  |==========================================                            |  60%
  |                                                                            
  |===========================================                           |  61%
  |                                                                            
  |============================================                          |  63%
  |                                                                            
  |=============================================                         |  64%
  |                                                                            
  |==============================================                        |  65%
  |                                                                            
  |===============================================                       |  67%
  |                                                                            
  |================================================                      |  68%
  |                                                                            
  |=================================================                     |  70%
  |                                                                            
  |==================================================                    |  71%
  |                                                                            
  |==================================================                    |  72%
  |                                                                            
  |====================================================                  |  74%
  |                                                                            
  |====================================================                  |  75%
  |                                                                            
  |=====================================================                 |  75%
  |                                                                            
  |======================================================                |  77%
  |                                                                            
  |=======================================================               |  79%
  |                                                                            
  |========================================================              |  80%
  |                                                                            
  |=========================================================             |  81%
  |                                                                            
  |==========================================================            |  82%
  |                                                                            
  |==========================================================            |  83%
  |                                                                            
  |===========================================================           |  85%
  |                                                                            
  |============================================================          |  86%
  |                                                                            
  |=============================================================         |  87%
  |                                                                            
  |==============================================================        |  88%
  |                                                                            
  |===============================================================       |  90%
  |                                                                            
  |================================================================      |  92%
  |                                                                            
  |=================================================================     |  93%
  |                                                                            
  |===================================================================   |  95%
  |                                                                            
  |====================================================================  |  97%
  |                                                                            
  |===================================================================== |  99%
  |                                                                            
  |======================================================================| 100%
## View the data
message(sprintf("Number of rows: %s, Number of columns: %s", nrow(tract), ncol(tract)))
## Number of rows: 349, Number of columns: 7
## Retain only those with estimates and rename them
tract <- tract %>% 
  select(GEOID, NAME,
         workers = workersE,
         workers.bicycle.commute = workers.bicycle.commuteE)
## Print the data
tract
## Simple feature collection with 349 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension:     XY
## Bounding box:  xmin: -84.85071 ymin: 33.50251 xmax: -84.02371 ymax: 34.18629
## Geodetic CRS:  NAD83
## First 10 features:
##          GEOID                                        NAME workers
## 1  13121001100     Census Tract 11, Fulton County, Georgia    3972
## 2  13121009603  Census Tract 96.03, Fulton County, Georgia    3293
## 3  13121005800     Census Tract 58, Fulton County, Georgia     736
## 4  13121010117 Census Tract 101.17, Fulton County, Georgia    2941
## 5  13121009502  Census Tract 95.02, Fulton County, Georgia    2087
## 6  13089021213 Census Tract 212.13, DeKalb County, Georgia    1365
## 7  13121011202 Census Tract 112.02, Fulton County, Georgia    1788
## 8  13089023506 Census Tract 235.06, DeKalb County, Georgia    2687
## 9  13121004900     Census Tract 49, Fulton County, Georgia    1665
## 10 13121004800     Census Tract 48, Fulton County, Georgia     402
##    workers.bicycle.commute                       geometry
## 1                       71 MULTIPOLYGON (((-84.38782 3...
## 2                        0 MULTIPOLYGON (((-84.38738 3...
## 3                       12 MULTIPOLYGON (((-84.41692 3...
## 4                       24 MULTIPOLYGON (((-84.36575 3...
## 5                        0 MULTIPOLYGON (((-84.39472 3...
## 6                        0 MULTIPOLYGON (((-84.34783 3...
## 7                        0 MULTIPOLYGON (((-84.46052 3...
## 8                        0 MULTIPOLYGON (((-84.25237 3...
## 9                       28 MULTIPOLYGON (((-84.38779 3...
## 10                       4 MULTIPOLYGON (((-84.38771 3...

Using Census tract boundaries for Yelp API

## Define a function that outputs the center of the bounding box of a polygon and the radius of a circle encompassing the bounding box tightly

# Function: Get tract-wise radius
get_r <- function(poly, epsg_id) {
  #---------------------------------------------------------------------------------------------#
  # Takes: a single POLYGON or LINESTRING                                                       #
  # Outputs: distance between the centroid of the bounding box 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_corner and bb_center
  r <- st_distance(bb_corner, bb_center)
  # Multiply 1.2 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.2
  return(bb_center)
}
## Use a functional (lapply) to apply this custom function to each Census Tract.
epsg_id <- 4326 # WGS 84 (World Geodetic System 1984) used in GPS
r4all_apply <- tract %>% 
  st_geometry() %>% 
  st_transform(crs = epsg_id) %>% 
  lapply(., function(x) get_r(x, epsg_id = epsg_id))

r4all_apply <- bind_rows(r4all_apply)
## Appending XY coordinates as separate columns
ready_4_yelp <- r4all_apply %>% 
  mutate(x = st_coordinates(.)[, 1], 
         y = st_coordinates(.)[, 2])
## Visualize the results
# Activate the interactive mode
tmap_mode('view') %>% suppressMessages()

# Display data (the first 10 rows)
ready_4_yelp[1:10, ] %>% 
  st_buffer(., dist = .$radius) %>% 
  tm_shape(.) + tm_polygons(alpha = 0.5, col = 'red') +
  tm_shape(tract[1:10, ]) + tm_borders(col = 'blue')

Getting a Yelp API Key

## Load my Yelp API key
load(here('data', 'yelp_api_key.RData')) # Load the API key save in my local machine

Defining function for accessing Yelp API for one Census Tract

## Define a function that downloads all businesses of a selected category in a Census tract
get_yelp <- function(tract, category){
  # ---------------------------------------------------------------- #
  # Gets one row of tract information (1,) and category name (str),  #
  # Outputs a list of business data.frame                            #  
  # ---------------------------------------------------------------- #
  n <- 1
  # First request ------------------------------------------------
  resp <- business_search(api_key = yelp.api.key, 
                          categories = category, 
                          latitude = tract$y, 
                          longitude = tract$x, 
                          offset = (n - 1) * 50,
                          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 n-th 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 more than 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 = 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
    } 
    
    # Merge all elements in the list into a single data frame
    out <- out %>% bind_rows()
    
    return(out)
  }
}

Repeating for all other Census Tracts

## Prepare a collector
yelp_all_list <- 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,], "bikerentals"))
  if (row %% 1 == 0){
     Sys.sleep(1)
    print(paste0("Current row: ", row))
  }
}
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 1"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 2"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 3"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 4"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 5"
## [1] "Current row: 6"
## [1] "Current row: 7"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 8"
## [1] "Current row: 9"
## [1] "Current row: 10"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 11"
## [1] "Current row: 12"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 13"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 14"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 15"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 16"
## [1] "Current row: 17"
## [1] "Current row: 18"
## [1] "Current row: 19"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 20"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 21"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 22"
## [1] "Current row: 23"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 24"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 25"
## [1] "Current row: 26"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 27"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 28"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 29"
## [1] "Current row: 30"
## [1] "Current row: 31"
## [1] "Current row: 32"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 33"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 34"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 35"
## [1] "Current row: 36"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 37"
## [1] "Current row: 38"
## [1] "Current row: 39"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 40"
## [1] "Current row: 41"
## [1] "Current row: 42"
## [1] "Current row: 43"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 44"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 45"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 46"
## [1] "Current row: 47"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 48"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 49"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 50"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 51"
## [1] "Current row: 52"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 53"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 54"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 55"
## [1] "Current row: 56"
## [1] "Current row: 57"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 58"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 59"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 60"
## [1] "Current row: 61"
## [1] "Current row: 62"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 63"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 64"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 65"
## [1] "Current row: 66"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 67"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 68"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 69"
## [1] "Current row: 70"
## [1] "Current row: 71"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 72"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 73"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 74"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 75"
## [1] "Current row: 76"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 77"
## [1] "Current row: 78"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 79"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 80"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 81"
## [1] "Current row: 82"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 83"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 84"
## [1] "Current row: 85"
## [1] "Current row: 86"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 87"
## [1] "Current row: 88"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 89"
## [1] "Current row: 90"
## [1] "Current row: 91"
## [1] "Current row: 92"
## [1] "Current row: 93"
## [1] "Current row: 94"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 95"
## [1] "Current row: 96"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 97"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 98"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 99"
## [1] "Current row: 100"
## [1] "Current row: 101"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 102"
## [1] "Current row: 103"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 104"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 105"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 106"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 107"
## [1] "Current row: 108"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 109"
## [1] "Current row: 110"
## [1] "Current row: 111"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 112"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 113"
## [1] "Current row: 114"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 115"
## [1] "Current row: 116"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 117"
## [1] "Current row: 118"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 119"
## [1] "Current row: 120"
## [1] "Current row: 121"
## [1] "Current row: 122"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 123"
## [1] "Current row: 124"
## [1] "Current row: 125"
## [1] "Current row: 126"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 127"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 128"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 129"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 130"
## [1] "Current row: 131"
## [1] "Current row: 132"
## [1] "Current row: 133"
## [1] "Current row: 134"
## [1] "Current row: 135"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 136"
## [1] "Current row: 137"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 138"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 139"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 140"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 141"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 142"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 143"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 144"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 145"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 146"
## [1] "Current row: 147"
## [1] "Current row: 148"
## [1] "Current row: 149"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 150"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 151"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 152"
## [1] "Current row: 153"
## [1] "Current row: 154"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 155"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 156"
## [1] "Current row: 157"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 158"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 159"
## [1] "Current row: 160"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 161"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 162"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 163"
## [1] "Current row: 164"
## [1] "Current row: 165"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 166"
## [1] "Current row: 167"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 168"
## [1] "Current row: 169"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 170"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 171"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 172"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 173"
## [1] "Current row: 174"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 175"
## [1] "Current row: 176"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 177"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 178"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 179"
## [1] "Current row: 180"
## [1] "Current row: 181"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 182"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 183"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 184"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 185"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 186"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 187"
## [1] "Current row: 188"
## [1] "Current row: 189"
## [1] "Current row: 190"
## [1] "Current row: 191"
## [1] "Current row: 192"
## [1] "Current row: 193"
## [1] "Current row: 194"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 195"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 196"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 197"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 198"
## [1] "Current row: 199"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 200"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 201"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 202"
## [1] "Current row: 203"
## [1] "Current row: 204"
## [1] "Current row: 205"
## [1] "Current row: 206"
## [1] "Current row: 207"
## [1] "Current row: 208"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 209"
## [1] "Current row: 210"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 211"
## [1] "Current row: 212"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 213"
## [1] "Current row: 214"
## [1] "Current row: 215"
## [1] "Current row: 216"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 217"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 218"
## [1] "Current row: 219"
## [1] "Current row: 220"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 221"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 222"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 223"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 224"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 225"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 226"
## [1] "Current row: 227"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 228"
## [1] "Current row: 229"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 230"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 231"
## [1] "Current row: 232"
## [1] "Current row: 233"
## [1] "Current row: 234"
## [1] "Current row: 235"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 236"
## [1] "Current row: 237"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 238"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 239"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 240"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 241"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 242"
## [1] "Current row: 243"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 244"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 245"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 246"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 247"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 248"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 249"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 250"
## [1] "Current row: 251"
## [1] "Current row: 252"
## [1] "Current row: 253"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 254"
## [1] "Current row: 255"
## [1] "Current row: 256"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 257"
## [1] "Current row: 258"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 259"
## [1] "Current row: 260"
## [1] "Current row: 261"
## [1] "Current row: 262"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 263"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 264"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 265"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 266"
## [1] "Current row: 267"
## [1] "Current row: 268"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 269"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 270"
## [1] "Current row: 271"
## [1] "Current row: 272"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 273"
## [1] "Current row: 274"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 275"
## [1] "Current row: 276"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 277"
## [1] "Current row: 278"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 279"
## [1] "Current row: 280"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 281"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 282"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 283"
## [1] "Current row: 284"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 285"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 286"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 287"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 288"
## [1] "Current row: 289"
## [1] "Current row: 290"
## [1] "Current row: 291"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 292"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 293"
## [1] "Current row: 294"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 295"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 296"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 297"
## [1] "Current row: 298"
## [1] "Current row: 299"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 300"
## [1] "Current row: 301"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 302"
## [1] "Current row: 303"
## [1] "Current row: 304"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 305"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 306"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 307"
## [1] "Current row: 308"
## [1] "Current row: 309"
## [1] "Current row: 310"
## [1] "Current row: 311"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 312"
## [1] "Current row: 313"
## [1] "Current row: 314"
## [1] "Current row: 315"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 316"
## [1] "Current row: 317"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 318"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 319"
## [1] "Current row: 320"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 321"
## [1] "Current row: 322"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 323"
## [1] "Current row: 324"
## [1] "Current row: 325"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 326"
## [1] "Current row: 327"
## [1] "Current row: 328"
## [1] "Current row: 329"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 330"
## [1] "Current row: 331"
## [1] "Current row: 332"
## [1] "Current row: 333"
## [1] "Current row: 334"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 335"
## [1] "Current row: 336"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 337"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 338"
## [1] "Current row: 339"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 340"
## [1] "Current row: 341"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 342"
## [1] "Current row: 343"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 344"
## [1] "Current row: 345"
## [1] "Current row: 346"
## [1] "Current row: 347"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 348"
## Warning: Outer names are only allowed for unnamed scalar atomic inputs
## [1] "Current row: 349"
## Collapsing the list into a data.frame
yelp_all <- yelp_all_list %>% bind_rows() %>% as_tibble() 

## Print
yelp_all %>% print(width=1000)
## # A tibble: 208 × 16
##    id                     alias                                      
##    <chr>                  <chr>                                      
##  1 FK7-M9BGyCgpEmVifcPfoA aztec-cycles-stone-mountain                
##  2 FK7-M9BGyCgpEmVifcPfoA aztec-cycles-stone-mountain                
##  3 JkkHRgYj0mvdgbMXFm436w civil-bikes-atlanta                        
##  4 FK7-M9BGyCgpEmVifcPfoA aztec-cycles-stone-mountain                
##  5 UmftRC3h0h_owHEm5ZLp7Q jump-atlanta-2                             
##  6 FK7-M9BGyCgpEmVifcPfoA aztec-cycles-stone-mountain                
##  7 JkkHRgYj0mvdgbMXFm436w civil-bikes-atlanta                        
##  8 kJJiJqGbiO_QXmdhol3hIQ british-and-american-bikes-atlanta         
##  9 FK7-M9BGyCgpEmVifcPfoA aztec-cycles-stone-mountain                
## 10 ot4UyUsRAlTFudTlCVRMrQ pedego-electric-bikes-alpharetta-alpharetta
##    name                            
##    <chr>                           
##  1 Aztec Cycles                    
##  2 Aztec Cycles                    
##  3 Civil Bikes                     
##  4 Aztec Cycles                    
##  5 JUMP                            
##  6 Aztec Cycles                    
##  7 Civil Bikes                     
##  8 British and American Bikes      
##  9 Aztec Cycles                    
## 10 Pedego Electric Bikes Alpharetta
##    image_url                                                           
##    <chr>                                                               
##  1 https://s3-media3.fl.yelpcdn.com/bphoto/re-aoEuun-QS1SE7dQCySQ/o.jpg
##  2 https://s3-media3.fl.yelpcdn.com/bphoto/re-aoEuun-QS1SE7dQCySQ/o.jpg
##  3 https://s3-media4.fl.yelpcdn.com/bphoto/JqTLT-chrqtbyuoB-52gdw/o.jpg
##  4 https://s3-media3.fl.yelpcdn.com/bphoto/re-aoEuun-QS1SE7dQCySQ/o.jpg
##  5 https://s3-media2.fl.yelpcdn.com/bphoto/D87H00XdLWZJS-LvQkTalA/o.jpg
##  6 https://s3-media3.fl.yelpcdn.com/bphoto/re-aoEuun-QS1SE7dQCySQ/o.jpg
##  7 https://s3-media4.fl.yelpcdn.com/bphoto/JqTLT-chrqtbyuoB-52gdw/o.jpg
##  8 https://s3-media2.fl.yelpcdn.com/bphoto/9I0G3Ge2yKFg6184t1XYEQ/o.jpg
##  9 https://s3-media3.fl.yelpcdn.com/bphoto/re-aoEuun-QS1SE7dQCySQ/o.jpg
## 10 https://s3-media2.fl.yelpcdn.com/bphoto/gPNidtknlSWKu3Bh4iOJ3Q/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/aztec-cycles-stone-mountain?adjust_creative=wA5TIrp…
##  2 https://www.yelp.com/biz/aztec-cycles-stone-mountain?adjust_creative=wA5TIrp…
##  3 https://www.yelp.com/biz/civil-bikes-atlanta?adjust_creative=wA5TIrpKGJmySk7…
##  4 https://www.yelp.com/biz/aztec-cycles-stone-mountain?adjust_creative=wA5TIrp…
##  5 https://www.yelp.com/biz/jump-atlanta-2?adjust_creative=wA5TIrpKGJmySk7ny-tL…
##  6 https://www.yelp.com/biz/aztec-cycles-stone-mountain?adjust_creative=wA5TIrp…
##  7 https://www.yelp.com/biz/civil-bikes-atlanta?adjust_creative=wA5TIrpKGJmySk7…
##  8 https://www.yelp.com/biz/british-and-american-bikes-atlanta?adjust_creative=…
##  9 https://www.yelp.com/biz/aztec-cycles-stone-mountain?adjust_creative=wA5TIrp…
## 10 https://www.yelp.com/biz/pedego-electric-bikes-alpharetta-alpharetta?adjust_…
##    review_count categories   rating coordinates$latitude $longitude transactions
##           <int> <list>        <dbl>                <dbl>      <dbl> <list>      
##  1           54 <df [3 × 2]>    5                   33.8      -84.2 <list [0]>  
##  2           54 <df [3 × 2]>    5                   33.8      -84.2 <list [0]>  
##  3            9 <df [2 × 2]>    4.5                 33.7      -84.4 <list [0]>  
##  4           54 <df [3 × 2]>    5                   33.8      -84.2 <list [0]>  
##  5            1 <df [2 × 2]>    1                   33.7      -84.4 <list [0]>  
##  6           54 <df [3 × 2]>    5                   33.8      -84.2 <list [0]>  
##  7            9 <df [2 × 2]>    4.5                 33.7      -84.4 <list [0]>  
##  8            2 <df [2 × 2]>    5                   33.9      -84.3 <list [0]>  
##  9           54 <df [3 × 2]>    5                   33.8      -84.2 <list [0]>  
## 10            7 <df [3 × 2]>    5                   34.0      -84.3 <list [0]>  
##    price location$address1          $address2   $address3 $city         
##    <chr> <chr>                      <chr>       <chr>     <chr>         
##  1 $$    "901 Main St"              ""          ""        Stone Mountain
##  2 $$    "901 Main St"              ""          ""        Stone Mountain
##  3 <NA>  ""                          <NA>       ""        Atlanta       
##  4 $$    "901 Main St"              ""          ""        Stone Mountain
##  5 <NA>  ""                         ""          <NA>      Atlanta       
##  6 $$    "901 Main St"              ""          ""        Stone Mountain
##  7 <NA>  ""                          <NA>       ""        Atlanta       
##  8 <NA>  "4264 F Winters Chapel Rd" ""          ""        Atlanta       
##  9 $$    "901 Main St"              ""          ""        Stone Mountain
## 10 <NA>  "6480 N Point Pkwy"        "Ste 1100b" <NA>      Alpharetta    
##    $zip_code $country $state $display_address phone        display_phone 
##    <chr>     <chr>    <chr>  <list>           <chr>        <chr>         
##  1 30083     US       GA     <chr [2]>        +16786369043 (678) 636-9043
##  2 30083     US       GA     <chr [2]>        +16786369043 (678) 636-9043
##  3 30312     US       GA     <chr [1]>        +14043238754 (404) 323-8754
##  4 30083     US       GA     <chr [2]>        +16786369043 (678) 636-9043
##  5 30301     US       GA     <chr [1]>        +18333006106 (833) 300-6106
##  6 30083     US       GA     <chr [2]>        +16786369043 (678) 636-9043
##  7 30312     US       GA     <chr [1]>        +14043238754 (404) 323-8754
##  8 30360     US       GA     <chr [2]>        +17704518868 (770) 451-8868
##  9 30083     US       GA     <chr [2]>        +16786369043 (678) 636-9043
## 10 30022     US       GA     <chr [3]>        +14042810264 (404) 281-0264
##    distance
##       <dbl>
##  1   22818.
##  2   29547.
##  3     366.
##  4   20724.
##  5    1238.
##  6   20887.
##  7     527.
##  8    1715.
##  9    1921.
## 10    2501.
## # … with 198 more rows
## Save the yelp data
write_rds(yelp_all, file = here('data', 'yelp_all_mini_assignment3.rds'))

Tidy data

Delete duplicated rows (from 208 rows to 16 rows)
## Check duplicated values in the "id" column and delete duplicated rows
yelp_all <- yelp_all %>% 
  distinct(id, .keep_all = T)  # from 208 rows to 16 rows
## Print
yelp_all
## # A tibble: 16 × 16
##    id           alias name  image…¹ is_cl…² url   revie…³ categ…⁴ rating coord…⁵
##    <chr>        <chr> <chr> <chr>   <lgl>   <chr>   <int> <list>   <dbl>   <dbl>
##  1 FK7-M9BGyCg… azte… Azte… https:… FALSE   http…      54 <df>       5      33.8
##  2 JkkHRgYj0mv… civi… Civi… https:… FALSE   http…       9 <df>       4.5    33.7
##  3 UmftRC3h0h_… jump… JUMP  https:… FALSE   http…       1 <df>       1      33.7
##  4 kJJiJqGbiO_… brit… Brit… https:… FALSE   http…       2 <df>       5      33.9
##  5 ot4UyUsRAlT… pede… Pede… https:… FALSE   http…       7 <df>       5      34.0
##  6 LsNS77QoD4w… dads… Dad'… https:… FALSE   http…      64 <df>       4.5    33.8
##  7 b3nacMG8PR7… atla… Atla… https:… FALSE   http…     124 <df>       4.5    33.8
##  8 8PfRbXo6qhK… atla… Atla… https:… FALSE   http…      40 <df>       4.5    33.8
##  9 rbf8bVY0cuq… pede… Pede… https:… FALSE   http…       9 <df>       4.5    33.7
## 10 BozJwfoXvoD… podi… Podi… https:… FALSE   http…      19 <df>       4.5    33.8
## 11 OJVvH1CUZac… rosw… Rosw… https:… FALSE   http…      70 <df>       4      34.0
## 12 vfp82FZBVz1… rela… Rela… https:… FALSE   http…      12 <df>       2      33.6
## 13 0H4julqllnl… ston… Ston… https:… FALSE   http…       7 <df>       3.5    33.8
## 14 cRTM5f8ATvV… the-… The … https:… FALSE   http…       1 <df>       1      34.1
## 15 xF82sx0_jxT… atla… Atla… https:… FALSE   http…      13 <df>       4      33.4
## 16 gcl6O-ZWTTr… clou… Clou… https:… FALSE   http…       1 <df>       1      33.8
## # … with 7 more variables: coordinates$longitude <dbl>, transactions <list>,
## #   price <chr>, location <df[,8]>, phone <chr>, display_phone <chr>,
## #   distance <dbl>, and abbreviated variable names ¹​image_url, ²​is_closed,
## #   ³​review_count, ⁴​categories, ⁵​coordinates$latitude
Flatten nested columns
## Define a custom function that takes a data frame in "categories" column in Yelp data and returns a character vector
concate_list <- function(x) {
  # "x" is a data frame with columns "alias" and "title" from  Yelp$categories
  # The function returns a character vector
  titles <- x$title %>% str_c(collapse = ", ") 
  return(titles)
}

## Flatten columns
yelp_all <- yelp_all %>% 
  # Flatten data-frame-columns ("coordinates" and "location")
  jsonlite::flatten() %>% 
  relocate(coordinates.latitude, coordinates.longitude, .after = rating) %>% 
  relocate(location.address1, location.address2, location.address3, location.city, 
           location.zip_code, location.country, location.state, location.display_address, .after = price) %>% 
  as_tibble() %>%
  # Flatten list-columns ("transactions" (empty), "location.display_address", and "categories")
  mutate(transactions = transactions %>% map_chr(function(x) str_c(x, collapse = ", ")),
         location.display_address = location.display_address %>% map_chr(function(x) str_c(x, collapse = ", ")),
         categories = categories %>% map_chr(concate_list)
         )
## Print
yelp_all
## # A tibble: 16 × 24
##    id           alias name  image…¹ is_cl…² url   revie…³ categ…⁴ rating coord…⁵
##    <chr>        <chr> <chr> <chr>   <lgl>   <chr>   <int> <chr>    <dbl>   <dbl>
##  1 FK7-M9BGyCg… azte… Azte… https:… FALSE   http…      54 Bikes,…    5      33.8
##  2 JkkHRgYj0mv… civi… Civi… https:… FALSE   http…       9 Bike R…    4.5    33.7
##  3 UmftRC3h0h_… jump… JUMP  https:… FALSE   http…       1 Scoote…    1      33.7
##  4 kJJiJqGbiO_… brit… Brit… https:… FALSE   http…       2 Motorc…    5      33.9
##  5 ot4UyUsRAlT… pede… Pede… https:… FALSE   http…       7 Bike R…    5      34.0
##  6 LsNS77QoD4w… dads… Dad'… https:… FALSE   http…      64 Smog C…    4.5    33.8
##  7 b3nacMG8PR7… atla… Atla… https:… FALSE   http…     124 Bike R…    4.5    33.8
##  8 8PfRbXo6qhK… atla… Atla… https:… FALSE   http…      40 Bike R…    4.5    33.8
##  9 rbf8bVY0cuq… pede… Pede… https:… FALSE   http…       9 Bikes,…    4.5    33.7
## 10 BozJwfoXvoD… podi… Podi… https:… FALSE   http…      19 Bikes,…    4.5    33.8
## 11 OJVvH1CUZac… rosw… Rosw… https:… FALSE   http…      70 Bikes,…    4      34.0
## 12 vfp82FZBVz1… rela… Rela… https:… FALSE   http…      12 Party …    2      33.6
## 13 0H4julqllnl… ston… Ston… https:… FALSE   http…       7 Bikes,…    3.5    33.8
## 14 cRTM5f8ATvV… the-… The … https:… FALSE   http…       1 Bike R…    1      34.1
## 15 xF82sx0_jxT… atla… Atla… https:… FALSE   http…      13 Bike R…    4      33.4
## 16 gcl6O-ZWTTr… clou… Clou… https:… FALSE   http…       1 Scoote…    1      33.8
## # … with 14 more variables: coordinates.longitude <dbl>, transactions <chr>,
## #   price <chr>, location.address1 <chr>, location.address2 <chr>,
## #   location.address3 <chr>, location.city <chr>, location.zip_code <chr>,
## #   location.country <chr>, location.state <chr>,
## #   location.display_address <chr>, phone <chr>, display_phone <chr>,
## #   distance <dbl>, and abbreviated variable names ¹​image_url, ²​is_closed,
## #   ³​review_count, ⁴​categories, ⁵​coordinates.latitude
Delete rows with missing data in “coordinates” variables (No missing values -> all rows are kept)
## Check missing values in "coordinates.latitude" and "coordinates.longitude" variables
yelp_all %>% select(coordinates.latitude, coordinates.longitude) %>% summary()
##  coordinates.latitude coordinates.longitude
##  Min.   :33.44        Min.   :-84.59       
##  1st Qu.:33.75        1st Qu.:-84.38       
##  Median :33.79        Median :-84.35       
##  Mean   :33.81        Mean   :-84.34       
##  3rd Qu.:33.85        3rd Qu.:-84.29       
##  Max.   :34.06        Max.   :-84.10
## No missing values in  "coordinates.latitude" and "coordinates.longitude" -> Keep all rows
Delete rows that fall outside of Fulton and Dekalb County (from 16 rows to 14 rows)
## Create an sf object (crs = 4326)
yelp_sf <- yelp_all %>%
  mutate(x = .$coordinates.longitude,
         y = .$coordinates.latitude) %>%
  filter(!is.na(x) & !is.na(y)) %>%      # No row is removed
  st_as_sf(coords = c("x", "y"), crs = 4326)

## Change the CRS of "tract" so that the CRS is the same as that of "yelp_sf"
tract <- st_transform(tract, crs = 4326)
## Check current data
tmap_mode('view') %>% suppressMessages()

tm_shape(yelp_sf) + tm_dots() +
  tm_shape(tract %>% st_union()) + tm_borders()
## Keep only cases fall inside Fulton and Dekalb County
yelp_sf <- yelp_sf[tract %>% st_union(), , op = st_intersects] # from 16 rows to 14 rows

## Check the output
tmap_mode('view') %>% suppressMessages()
tm_shape(yelp_sf) + tm_dots() +
  tm_shape(tract) + tm_borders()

Join Census and Yelp

## Get the number of bike rentals by tract
bike_rentals_by_tract <- st_join(tract, yelp_sf %>% mutate(count = 1)) %>% 
  group_by(GEOID) %>% 
  summarize(count = sum(count, na.rm = T))

# Attach the result to the census data
tract_with_bike_rentals_count <- tract %>% 
  left_join(bike_rentals_by_tract %>% st_drop_geometry(), by = "GEOID")
# Mapping
tm_shape(tract_with_bike_rentals_count %>% mutate(count = as.integer(count))) + tm_polygons(col="count") +
  tm_shape(yelp_sf) + tm_dots()

Examine the associations among the variables bike rentals and bike commuting

## Create a variable for the proportion of workers commuting via bicycle by tract
tract_with_bike_rentals_count <- tract_with_bike_rentals_count %>% 
  mutate(proportion.workers.bicycle.commute = workers.bicycle.commute/workers)

## Remove 4 census tracts with no workers (among 349 census tracts)
## They do not have bike rental shops 
tract_with_bike_rentals_count <- tract_with_bike_rentals_count %>% 
  filter(workers != 0)
## Existence of bike rental shops and the proportion of workers commuting via bike
# Create a binary variable
tract_with_bike_rentals_count$Bike.rental <- ifelse(tract_with_bike_rentals_count$count > 0, "Yes", "No")

# Visualize using a box plot
boxplot(proportion.workers.bicycle.commute ~ Bike.rental, data = tract_with_bike_rentals_count, 
        main = "Boxplot of Bike Rental Shop and Proportion of Bike Commuters",
        xlab = "Whether Bike Rental Shops are Present",
        ylab = "Proportion of Bike Commuters")

## Mapping bike rental shops and the "number" of bike commuters
tm_shape(tract_with_bike_rentals_count) + 
  tm_polygons(col = "workers.bicycle.commute")
  tm_shape(yelp_sf) + tm_dots()
## Mapping bike rental shops and the "proportion" of bike commuters
tm_shape(tract_with_bike_rentals_count %>% rename()) + tm_polygons(col = "proportion.workers.bicycle.commute") +
  tm_shape(yelp_sf) + tm_dots()

Findings