Google APIs: Geocoding, Places, Distance Matrix, Isochrones

geospatial google-APIs purrr

A demo of several useful Google APIs

Bryan Blanc https://github.com/bpb824
07-07-2021

This content was presented to Nelson\Nygaard Staff at a GIS Hangout on Thursday, July 7th, and is available as a recording here and embedded below.

Today’s Agenda

Introduction

Application Programming Interfaces (APIs) are how software interacts programatically with a user. That may sound like a mouthful, but is the way many web platforms offer services (both free and priced) to users. When you use Google Maps on your phone to get directions, the phone app is interacting with various Google APIs to get information about your route – the route is not being computed on your phone, but rather on a Google server based on the information you hand it (e.g., origin, destination). That route is then being sent back to your phone to display to the user. Similarly, there are a variety of Google APIs that can be accessed programatically through R to collect information useful to transportation planners.

Making a Google API key

The first thing you need to do to work with Google’s APIs (Application Programming Interface) is create your own API key so that your API calls can be tracked. Google does this because this is a service that they charge for if you do more than a couple thousand calls per day (each API has its own usage tiers). You can create your own key by going to the Google Developer Console, logging in with an account (I use an account linked to my NN email address), and then creating an initial API key in the ‘Credentials’ panel. It is helpful if you have multiple projects using APIs to create a key per project, as this will be easier to separate for billing purposes. You will need to provide a credit card for Google to charge to in order to use APIs – they will only charge your credit card if you go beyond the free usage tier, in which case you should be expensing those charges to a project. For practice, we shouldn’t need to go over the free usage tier.

After creating a key, you must enable API services tied to that key. For this tutorial, it is recommended you enable the following API services:

After you enable the APIs, use the below line of code to set your API key to be used by the googleway package. Prior, we must load the packages we will be using in this tutorial.

#Using an API Key set up for NN R training -- please use your own API key below
set_key('<YOUR API KEY HERE>')

Geocoding

The Google Maps Geocoding API is a service that provides geocoding and reverse geocoding of addresses. We are going to show off both geocoding and reverse geocoding using NN’s office locations.

nn_office_locations = read_csv('data/nn_office_locations.csv')

nn_office_locations
# A tibble: 9 x 7
  nn_office_id City          State JOIN_ID      X     Y street_address
         <dbl> <chr>         <chr> <chr>    <dbl> <dbl> <chr>         
1            1 Portland      OR    Portla~ -123.   45.5 621 SW Morris~
2            2 Seattle       WA    Seattl~ -122.   47.6 811 1st Avenu~
3            3 San Francisco CA    San Fr~ -122.   37.8 2 Bryant Stre~
4            4 Oakland       CA    Oaklan~ -122.   37.8 1629 Telegrap~
5            5 Los Angeles   CA    Los An~ -118.   34.1 706 South Hil~
6            6 Austin        TX    Austin~  -97.7  30.3 201 W 5th Str~
7            7 Washington    DC    Washin~  -77.0  38.9 1222 22nd St ~
8            8 New York      NY    New Yo~  -73.8  40.8 1250 Broadway~
9            9 Boston        MA    Boston~  -71.1  42.4 77 Franklin S~
geocoded_nn_office_locs = nn_office_locations %>%
  #the Google api seems to really not like '#' characters, so sanitize for these first (replace with spaces)
  mutate(street_address = str_replace(street_address,fixed('#'),'')) %>%
  mutate(geocode_result = map(street_address,~google_geocode(.x))) %>%
  mutate(geocode_lng = map_dbl(geocode_result,~.x$results$geometry$location$lng),
         geocode_lat = map_dbl(geocode_result,~.x$results$geometry$location$lat))


#Two options for mapping -- Google and Leaflet
#Google
google_map(geocoded_nn_office_locs) %>%
  add_markers(lat='geocode_lat',lon='geocode_lng',
              label='City')
#Leaflet
leaflet() %>%
  addProviderTiles('CartoDB.Positron') %>%
  addMarkers(data = geocoded_nn_office_locs, lng=~geocode_lng, lat =~geocode_lat,
             label=~ City)
#Reverse
rev_geocode_nn_office_locs = geocoded_nn_office_locs %>%
  mutate(rev_geocode_result = map2(geocode_lat,geocode_lng,
                                   ~google_reverse_geocode(c(.x,.y),
                                                           result_type = 'street_address',
                                                           location_type = 'rooftop')),
         rev_geocode_address = map_chr(rev_geocode_result,~.x$results$formatted_address[1]))

compare_address_table = rev_geocode_nn_office_locs %>%
  select(City,street_address,rev_geocode_address)

#Compare the two -- there are some differences, especially in very dense areas like NYC
compare_address_table %>%
  rename(`Actual Street Address` = street_address,
         `Reverse Geocoded Street Address` = rev_geocode_address) %>%
  datatable(options = list(info=FALSE,paging=FALSE,searching=FALSE),
            rownames=FALSE)

Google Places

The Google Maps Places API gets data from the same database used by Google Maps. Places features more than 100 million businesses and points of interest that are updated frequently through owner-verified listings and user-moderated contributions.

There are three types of search you can perform

A Nearby Search lets you search for places within a specified area. You can refine your search request by supplying keywords or specifying the type of place you are searching for.

A Text Search Service is a web service that returns information about a set of places based on a string — for example “pizza in New York” or “shoe stores near Seattle” or “123 Main Street”. The service responds with a list of places matching the text string and any location bias that has been set.

A Place Detail search (using google_place_details()) can be performed when you have a given place_id from one of the other two search methods.

Text

For a text search you are required to provide a search_string

For example, let’s see if we can find a Nelson\Nygaard office. With no additional information, it will try to find the closest Nelson\Nygaard to you. It can tell approximately where you are located from your IP address. More precise locational information would have to be provided in the query text itself – unlike querying on your phone, the browser doesn’t have your GPS coordinates by default.

res <- google_places(search_string = "Nelson\\Nygaard")
print(res)
$html_attributions
list()

$results
  business_status
1     OPERATIONAL
                                            formatted_address
1 621 SW Morrison St #1250, Portland, OR 97205, United States
  geometry.location.lat geometry.location.lng
1              45.51934             -122.6791
  geometry.viewport.northeast.lat geometry.viewport.northeast.lng
1                        45.52064                       -122.6778
  geometry.viewport.southwest.lat geometry.viewport.southwest.lng
1                        45.51794                       -122.6805
                                                                                 icon
1 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/generic_business-71.png
  icon_background_color
1               #7B9EB0
                                                   icon_mask_base_uri
1 https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet
             name open_now                    place_id
1 Nelson\\Nygaard    FALSE ChIJZRiw_gQKlVQRT7zuWnASRLg
   plus_code.compound_code plus_code.global_code rating
1 G89C+P9 Portland, Oregon           84QVG89C+P9      5
                    reference                            types
1 ChIJZRiw_gQKlVQRT7zuWnASRLg point_of_interest, establishment
  user_ratings_total
1                  2

$status
[1] "OK"
#Let's try to force it to find the Boston office

res <- google_places(search_string = "Nelson\\Nygaard Boston, MA")
print(res)
$html_attributions
list()

$results
  business_status
1     OPERATIONAL
                                      formatted_address
1 77 Franklin St #10th, Boston, MA 02110, United States
  geometry.location.lat geometry.location.lng
1              42.35531             -71.05799
  geometry.viewport.northeast.lat geometry.viewport.northeast.lng
1                        42.35669                       -71.05669
  geometry.viewport.southwest.lat geometry.viewport.southwest.lng
1                        42.35399                       -71.05939
                                                                                 icon
1 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/generic_business-71.png
  icon_background_color
1               #7B9EB0
                                                   icon_mask_base_uri
1 https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet
                                   name                    place_id
1 Nelson\\Nygaard Consulting Associates ChIJzahIpYNw44kR2NCpvp1_IcQ
        plus_code.compound_code plus_code.global_code rating
1 9W4R+4R Boston, Massachusetts           87JC9W4R+4R      0
                    reference                            types
1 ChIJzahIpYNw44kR2NCpvp1_IcQ point_of_interest, establishment
  user_ratings_total
1                  0

$status
[1] "OK"
#Google not smart enough to figure this query out
res <- google_places(search_string = "all Nelson Nygaard offices")
print(res)
$html_attributions
list()

$results
  business_status
1     OPERATIONAL
                                            formatted_address
1 621 SW Morrison St #1250, Portland, OR 97205, United States
  geometry.location.lat geometry.location.lng
1              45.51934             -122.6791
  geometry.viewport.northeast.lat geometry.viewport.northeast.lng
1                        45.52064                       -122.6778
  geometry.viewport.southwest.lat geometry.viewport.southwest.lng
1                        45.51794                       -122.6805
                                                                                 icon
1 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/generic_business-71.png
  icon_background_color
1               #7B9EB0
                                                   icon_mask_base_uri
1 https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet
             name open_now                    place_id
1 Nelson\\Nygaard    FALSE ChIJZRiw_gQKlVQRT7zuWnASRLg
   plus_code.compound_code plus_code.global_code rating
1 G89C+P9 Portland, Oregon           84QVG89C+P9      5
                    reference                            types
1 ChIJZRiw_gQKlVQRT7zuWnASRLg point_of_interest, establishment
  user_ratings_total
1                  2

$status
[1] "OK"

Let’s try something that we know will return multiple results – e.g., pizza restaurants in Portland, OR. A single query will return 20 results per page. You can view the next 20 results using the next_page_token that is returned as part of the initial query.

res <- google_places(search_string = "Pizza Restaurants in Portland, Oregon")

res$results
   business_status
1      OPERATIONAL
2      OPERATIONAL
3      OPERATIONAL
4      OPERATIONAL
5      OPERATIONAL
6      OPERATIONAL
7      OPERATIONAL
8      OPERATIONAL
9      OPERATIONAL
10     OPERATIONAL
11     OPERATIONAL
12     OPERATIONAL
13     OPERATIONAL
14     OPERATIONAL
15     OPERATIONAL
16     OPERATIONAL
17     OPERATIONAL
18     OPERATIONAL
19     OPERATIONAL
20     OPERATIONAL
                                                       formatted_address
1                 3632 N Williams Ave, Portland, OR 97227, United States
2                    2835 SE Stark St, Portland, OR 97214, United States
3              4039 N Mississippi Ave, Portland, OR 97217, United States
4                  6708 NE Sandy Blvd, Portland, OR 97213, United States
5                  1134 NW Everett St, Portland, OR 97209, United States
6                    5028 NE 42nd Ave, Portland, OR 97218, United States
7              3552 N Mississippi Ave, Portland, OR 97227, United States
8                     304 SE 28th Ave, Portland, OR 97214, United States
9                 2128 SE Division St, Portland, OR 97202, United States
10                  2727 NE Glisan St, Portland, OR 97232, United States
11 2434 NE Martin Luther King Jr Blvd, Portland, OR 97212, United States
12                4327 N Williams Ave, Portland, OR 97217, United States
13                  624 E Burnside St, Portland, OR 97214, United States
14                 5235 NE Sandy Blvd, Portland, OR 97213, United States
15                 4641 NE Fremont St, Portland, OR 97213, United States
16                   3449 NE 24th Ave, Portland, OR 97212, United States
17                     721 NW 9th Ave, Portland, OR 97209, United States
18           1603 NE Killingsworth St, Portland, OR 97211, United States
19                    628 NE Broadway, Portland, OR 97232, United States
20                   3345 NE Broadway, Portland, OR 97232, United States
   geometry.location.lat geometry.location.lng
1               45.54939             -122.6665
2               45.51944             -122.6365
3               45.55286             -122.6758
4               45.54616             -122.5942
5               45.52496             -122.6827
6               45.55937             -122.6202
7               45.54861             -122.6752
8               45.52056             -122.6371
9               45.50465             -122.6439
10              45.52670             -122.6376
11              45.54005             -122.6613
12              45.55478             -122.6669
13              45.52277             -122.6591
14              45.54049             -122.6094
15              45.54839             -122.6152
16              45.54811             -122.6413
17              45.52823             -122.6806
18              45.56286             -122.6489
19              45.53491             -122.6589
20              45.53527             -122.6298
   geometry.viewport.northeast.lat geometry.viewport.northeast.lng
1                         45.55072                       -122.6653
2                         45.52073                       -122.6351
3                         45.55420                       -122.6743
4                         45.54757                       -122.5928
5                         45.52638                       -122.6814
6                         45.56069                       -122.6190
7                         45.54995                       -122.6740
8                         45.52192                       -122.6358
9                         45.50609                       -122.6426
10                        45.52801                       -122.6362
11                        45.54150                       -122.6599
12                        45.55611                       -122.6655
13                        45.52420                       -122.6577
14                        45.54178                       -122.6080
15                        45.54969                       -122.6139
16                        45.54952                       -122.6399
17                        45.52962                       -122.6795
18                        45.56429                       -122.6476
19                        45.53634                       -122.6575
20                        45.53656                       -122.6284
   geometry.viewport.southwest.lat geometry.viewport.southwest.lng
1                         45.54802                       -122.6680
2                         45.51803                       -122.6378
3                         45.55150                       -122.6770
4                         45.54487                       -122.5955
5                         45.52368                       -122.6841
6                         45.55799                       -122.6217
7                         45.54725                       -122.6767
8                         45.51922                       -122.6385
9                         45.50339                       -122.6453
10                        45.52531                       -122.6389
11                        45.53880                       -122.6626
12                        45.55341                       -122.6682
13                        45.52150                       -122.6604
14                        45.53908                       -122.6107
15                        45.54699                       -122.6166
16                        45.54682                       -122.6426
17                        45.52692                       -122.6822
18                        45.56159                       -122.6503
19                        45.53364                       -122.6602
20                        45.53386                       -122.6311
                                                                            icon
1  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
2  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
3  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
4  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
5  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
6  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
7  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
8  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
9  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
10 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
11 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
12 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
13 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
14 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
15 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
16 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
17 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
18 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
19 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
20 https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png
   icon_background_color
1                #FF9E67
2                #FF9E67
3                #FF9E67
4                #FF9E67
5                #FF9E67
6                #FF9E67
7                #FF9E67
8                #FF9E67
9                #FF9E67
10               #FF9E67
11               #FF9E67
12               #FF9E67
13               #FF9E67
14               #FF9E67
15               #FF9E67
16               #FF9E67
17               #FF9E67
18               #FF9E67
19               #FF9E67
20               #FF9E67
                                                       icon_mask_base_uri
1  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
2  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
3  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
4  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
5  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
6  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
7  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
8  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
9  https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
10 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
11 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
12 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
13 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
14 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
15 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
16 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
17 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
18 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
19 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
20 https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet
                                name open_now
1                  Life of Pie Pizza    FALSE
2                    Baby Doll Pizza    FALSE
3               Lovely's Fifty Fifty    FALSE
4                      Pizzeria Otto    FALSE
5                    Oven and Shaker    FALSE
6                         Pizza Jerk    FALSE
7                  Mississippi Pizza    FALSE
8                Ken's Artisan Pizza    FALSE
9             Scottie's Pizza Parlor    FALSE
10                         Dove Vivi    FALSE
11 Sparky's Pizza: Portland - Brazee    FALSE
12     Rovente Pizzeria - N Williams    FALSE
13       Sizzle Pie Central Eastside    FALSE
14         Baby Blue Woodfired Pizza    FALSE
15                   Red Sauce Pizza    FALSE
16                             Lucca    FALSE
17             HOTLIPS Pizza - Pearl    FALSE
18                    Handsome Pizza    FALSE
19               Schmizza Pub & Grub    FALSE
20           Blind Onion Pizza & Pub    FALSE
                                                                                                                                                                                                                                                                                                     photos
1             2268, <a href="https://maps.google.com/maps/contrib/115423669611549750703">Mohammad Moussaoui</a>, Aap_uECMs-ihJTbiiTr1G-ntz2FykSkZUKlxMhyOE6VnZXDI0tEEOUoPu_go8yUbifmaxgDnCCWo4S4LWUMOu4N2wXg-6UkcEZ2-WKbPudPdiHtqJpka86Gly6ApbMy4fezhmNhUqsScVWlq9pgjCtGdkWCaFXlHIRtvIWGw3eauwfdnlb-6, 4032
2              2268, <a href="https://maps.google.com/maps/contrib/104185145718418942354">Franklin Weichelt</a>, Aap_uEBMrLgEqK-GL0OHqbqcpuLhodik4QMbsPouv6VnV8RpQoa-FsmWdrvmyR9T3h2G9dbakRGwNZBzRgAyC0CPV4QBCW9uBWB9DseyYQ8WM9qtQ8zL0GiOg0pnYF5Ab0BXyMQJgcthP-aSDGTBSWir8S6XWp0sIQZWhAlViIf9qKHJaG9h, 4032
3                           1960, <a href="https://maps.google.com/maps/contrib/108721980232408473396">Scam</a>, Aap_uECOL0bCkePaQdjHMqNVUWo9SoUekv9WWC3Ve5nZ8QGhCjIwGKEwwfGd39pBXKUa3FG7eCppNN_qe2eJmpBqmyLPf-MUt_312-PbndhuzTgfhYGD5p8dYMvpAjbuj2l6PAgCDWEa4fjs0v8RpIZCeWcuUC4havhdTO6yvTtdaPs-klQk, 4032
4                  1728, <a href="https://maps.google.com/maps/contrib/103559260072111141799">Pizzeria Otto</a>, Aap_uEB0DeoXZHRgN1-cQde8gG8WLF388V9_SFcchnU0DZI2Jvk8zxq9hzDwgAWI28wPhsqJPMSLeIiXRSuk942vwbyV3caMd6EDSkF_fVMB3yX-qAWGp4SC7JWBG2sjhTWralqTw_90m8YfOsQJhh3YJkLcDPkDv556TMy8SHL-NxVFgWjj, 2592
5                   3221, <a href="https://maps.google.com/maps/contrib/110929668784275848314">Dani Winters</a>, Aap_uEB-uPqmz0FUb3v_NsZ3PO7aV4VByh8WHMCc4ZNZkRnLaD24nbJhdIJtzBVpF-S-KMZZsWsBFCfUjDy-NuuSaxRW48jLPEd-MEFd1m8mnFkLB6eGBQbvU4fibDBegOaeLwneAQ_01s_xodXDiTwfXnQH3-wxppAYTwhAMkSqgYQxpkQd, 4831
6                        3024, <a href="https://maps.google.com/maps/contrib/111427090360672906927">Toto Vo</a>, Aap_uECiV5hiDy8LYbvtfv8fx1P64EA9PZ_Xz7zGokAfdOE0iqjAZqTNCUU0lDyYJtAQKoN9Y9qRRZSYVhGaIlz8rzQb9ME2GtNVT_1c2C3tSTW0jaa4XTKPCymomqAsY_ThX5Rv-DIAigteOZLZL46_0X6xu8xyiJQ3d6n3y9_OXLknOFez, 4032
7                 3024, <a href="https://maps.google.com/maps/contrib/112513389439706252436">Michael Brewer</a>, Aap_uEBdJrhEk7JV8TDz_BZ_Qq06hnGe48e3Btbj0zzc39bDx05XpbUgHlG1EneSo2uqCaG4qhbc9nfqixxVoXoExs5mrUZRnMUkzvnmPQ6Il9EmqkOiH9ETPlaNCTCSZhlX8o9K-jrpdy72r2u_lQ7ZogejgNwcMcIvdPRDbaYi_tOmdenC, 4032
8              3024, <a href="https://maps.google.com/maps/contrib/100284562054931061096">Michael DelGaudio</a>, Aap_uEASLXvhL-oR8uqQ7MaS3u3KGyri0DVvQGGAhlGrW-QYfjdSQDdYbeb3CwB3_1QwDo8GgJDIIkd2uaW1koTEBYD_5XffU9MXsTrn_zZjVDdrJC9I4-U9Q6UGZyA1mtKyy_2jiFbjbjtyoACcaN5YbfSZ5_WQ0_rpvbhdwRCDQRwNXOmk, 4032
9                 3024, <a href="https://maps.google.com/maps/contrib/100937861139798429847">Tyler Clements</a>, Aap_uEDguQBnFPHN55gLK4XA9wjpBZghLtRsKR6dbqHgYiuxf7OAMIgKdOeT5Z91lixKXGGNafFOzCxTPygOc3Xi85qZzbHfxDjiT53zM-ubD6Coa8GmBmHi_WFyvus4FJNPABNDtNH5JVdPm5ZkRAT9TdqHUzZbkE3NiSmrVrfg1f_u1jnt, 4032
10                       3024, <a href="https://maps.google.com/maps/contrib/111427090360672906927">Toto Vo</a>, Aap_uEB7pd0w2b8Cqfcn2ootRJRNQaj6SUH6LPZiJRUL49YQpeL2W7pzbFdhSwiyPYxlFTgtoewqiflIGG9keTgVroGcX-80Lr58CM9qV5HAp2qK043M2mirXaNpud0HNLNjgWv37ZXZzSNNuLq4jm65AdG6HqaTU8Tov7HSb-q0ik9Z4bUc, 4032
11                 2048, <a href="https://maps.google.com/maps/contrib/111895905980247196526">A Google User</a>, Aap_uEBTsDyiufSypsyOdbgUig7EXnjJ6au9cy9qYpdisRvAyW7AqIu_lBzGCKgDWzjJvua9wGhQfu1KdqIC-GVFqcFg9OjFlww6mf4pZ-oge8VkXl3xeDGo_Dld0FJsJL8lqpHq-_Knv0nCYYHzS3nziXanMMpvHsVLBVZQOTboE4pPddAD, 1536
12 2662, <a href="https://maps.google.com/maps/contrib/104255506511412642234">Rovente Pizzeria - N Williams</a>, Aap_uEAnjjUu1BmM8WxFMVIEr3lAiSSdkqftg988BM1ZcHQmnSAYIQ_axIfuTYy6LFucFyP2VBxwH3qXUalgPYLusirH6yT5XlLuMT4K86FfiRP3sk4fvbJMXkiFlUwtyITovx3H9PCxIuLemMt3f1ym_60rl-rrksXaQRgazN640Bs9KxE6, 4000
13              2432, <a href="https://maps.google.com/maps/contrib/109807843344021886684">PattandSyd White</a>, Aap_uEBOwAByPJAm8vb_3MgkbFkYdVptdD0ivEZwwxdLa-Ih8Pp4TZod8a8pS3RovsytlTIBWDO8iKLV6R0bK8ki7bu3W8RWPDW22ztUDxfc3wOaIfoA-SfoXPv2uu01wbAKshTJ22HL4vS5aVMTDuP8WaKEJakb5Jp2iuqFd1lDHjsQy6LX, 3286
14                 2838, <a href="https://maps.google.com/maps/contrib/117742998485838550616">A Google User</a>, Aap_uEDR-d8tbeVR-3uXPMYeR6BWyiqflJZzFdiLADHB9txpsfssPf9HoHhcd6hHSNxeSRSFg3pAxokLKf3f-0Uuulxqt5-viBy2gA_DM23dTqUoGJJ-7I0rPesmPMoIPCwnvVCv9eXVejaZ35D6LoL9WghP8cpaQ1jmiXLhhhI9ZX87zQpj, 3784
15                   4048, <a href="https://maps.google.com/maps/contrib/111514263504092262023">Raymond Lusk</a>, Aap_uEAEUSSIqJQPzhSmQGgNqx86hUnkKKI8OAVi3YSwQ5UErkGMJiaMyuQaNsEVUlXxiqmFjgHUyfDwchcUrru-VHn3BUC13Rwrjw2myglueZ4nXnXXYrLURP24PqG7TK8HI4VbCIx7RpJzAvkvzxpDaJ3ZmPqnPx5-mHh77C64MchZI7Y, 3036
16                  2988, <a href="https://maps.google.com/maps/contrib/115847917163557947123">Joseph Trinh</a>, Aap_uEBH-K-PcYNwUUnQOaObaWYByuM-m8FGDbTzGg8t97s3E4Gib48RgA6sjmce8C7wNUp7SzwcVlTuzvG8TyScKWijwfdPHGtDzGnv-b6thgn9RLOfxaDFciy4_r0xfVm6nLvdBUKUc7WKhHQE6kuL_3CPKeUnixczQpF_wRaMbmVI0hRm, 5312
17         1333, <a href="https://maps.google.com/maps/contrib/102271744552856165857">Hotlips Pizza - Pearl</a>, Aap_uED8W5z2XSGNzIZf4b99a40bs8CEf_nNH06Z5CPjh6Q-g8pgkWIo-IwHxm88YoBdcP4WwiNWVib6Dir_gHB-JUQnUcYq-bhLpzW0mYk4x8XMbnGjdnAsHNezmbp2WbRLD1BeMMcxMhfaMdvAX7BKcNUm4vlZCkIscEgSB1rNuOCOtiXk, 2000
18                2048, <a href="https://maps.google.com/maps/contrib/116714422629190292867">Handsome Pizza</a>, Aap_uEAc0jUys32N7F0sGG7QUeBXuoru_UTW-_jmmxSfH_6si8aMyakhsHXkCwOcDjD3pnT606spqahHgD4pu5rNl4zv4Hww-trjBnCP45WxlX0Ot1VM9MgyP4ovbXV-osNSMfmwBYBkGYJ1gcsMAQEC-SLLtDecL_dZgr454WKbtln8IeGz, 2048
19                   3024, <a href="https://maps.google.com/maps/contrib/102518614868730810624">Mr. Wallace</a>, Aap_uECt0HWTc8wHA7ngh4sYxivnSpTKuRYDZTU-WIhr4Ikl-xUkp82LCNnya-BB4pfwDXD0a3rZMCiIkQvy34XaSFhcT2ZcAC8VoZVVsKbtKF770c2a3UVZ4foi_KPwh_QLIDAN91gJsOLUc03V567kXoFLJF18a16fX_GGhByCeedS0GH6, 4032
20                 3024, <a href="https://maps.google.com/maps/contrib/118391669858448410567">A Google User</a>, Aap_uEA-knxTkQGhFksM5s4YHB0oGFXJk1dpg6thxkJhDrwXZgIh4xJQtxD4rUI6qfAcya2gOOlc8qotos5feb6SuBBnz2uTKDFpjWOEm-G9uvX-rULz4CZExljMTViOXHX3NE26BslA-nnC7twwIPcf9vAZHbtCuaVgt0bZknQlfmtQTijO, 4032
                      place_id  plus_code.compound_code
1  ChIJ37XwgT-nlVQRiFBDHwcXL08 G8XM+Q9 Portland, Oregon
2  ChIJPTqg95WglVQRlQ404FrXiDI G997+QC Portland, Oregon
3  ChIJT9ZbCWunlVQRIryTTXOWkEw H83F+4M Portland, Oregon
4  ChIJh8DFUjahlVQRQ1VwkI9vd1c GCW4+F8 Portland, Oregon
5  ChIJpSNOEAIKlVQRMSxrrUg32Y4 G8F8+XW Portland, Oregon
6  ChIJbR2qUcSmlVQRrAH7hs63TZw H95H+PW Portland, Oregon
7  ChIJ9SRcAkKnlVQRU2wR1eFxEew G8XF+CW Portland, Oregon
8  ChIJyetGFb6glVQRAKXnO6xBLoM G9C7+65 Portland, Oregon
9  ChIJIS1RjYKglVQRTiQbrbT8N8k G934+VC Portland, Oregon
10 ChIJKXOiFceglVQR6F5TjEacj8k G9G6+MW Portland, Oregon
11 ChIJh1-YG0mnlVQR6bVs7csfV8g G8RQ+2F Portland, Oregon
12 ChIJE7QOOhSnlVQRR3K1Cu9KeLM H83M+W6 Portland, Oregon
13 ChIJL6cxWK-glVQRQb0GBCQdRIU G8FR+49 Portland, Oregon
14 ChIJH-kjr6ShlVQRPLbkz31TyZE G9RR+57 Portland, Oregon
15 ChIJZSEr_sSmlVQR2EWPtgHcGOo G9XM+9W Portland, Oregon
16 ChIJV-MXEy-nlVQRJhsRJpcp3GQ G9X5+6F Portland, Oregon
17 ChIJXTsSpv8JlVQRy9gDQuP28Ns G8H9+7Q Portland, Oregon
18 ChIJxzm2ananlVQRdnpTr9d_fw4 H972+4C Portland, Oregon
19 ChIJWxEvmEynlVQRyFgr46kf0uw G8MR+XC Portland, Oregon
20 ChIJd9jW0dGglVQR3tOtwAPiBWw G9PC+43 Portland, Oregon
   plus_code.global_code price_level rating
1            84QVG8XM+Q9           2    4.7
2            84QVG997+QC           1    4.6
3            84QVH83F+4M           2    4.6
4            84QVGCW4+F8           2    4.6
5            84QVG8F8+XW           2    4.5
6            84QVH95H+PW           2    4.4
7            84QVG8XF+CW           1    4.5
8            84QVG9C7+65           2    4.7
9            84QVG934+VC           1    4.7
10           84QVG9G6+MW           2    4.6
11           84QVG8RQ+2F           1    4.4
12           84QVH83M+W6          NA    4.5
13           84QVG8FR+49           1    4.4
14           84QVG9RR+57          NA    4.9
15           84QVG9XM+9W           2    4.6
16           84QVG9X5+6F           2    4.4
17           84QVG8H9+7Q           1    4.3
18           84QVH972+4C           2    4.5
19           84QVG8MR+XC           1    3.9
20           84QVG9PC+43           2    4.5
                     reference
1  ChIJ37XwgT-nlVQRiFBDHwcXL08
2  ChIJPTqg95WglVQRlQ404FrXiDI
3  ChIJT9ZbCWunlVQRIryTTXOWkEw
4  ChIJh8DFUjahlVQRQ1VwkI9vd1c
5  ChIJpSNOEAIKlVQRMSxrrUg32Y4
6  ChIJbR2qUcSmlVQRrAH7hs63TZw
7  ChIJ9SRcAkKnlVQRU2wR1eFxEew
8  ChIJyetGFb6glVQRAKXnO6xBLoM
9  ChIJIS1RjYKglVQRTiQbrbT8N8k
10 ChIJKXOiFceglVQR6F5TjEacj8k
11 ChIJh1-YG0mnlVQR6bVs7csfV8g
12 ChIJE7QOOhSnlVQRR3K1Cu9KeLM
13 ChIJL6cxWK-glVQRQb0GBCQdRIU
14 ChIJH-kjr6ShlVQRPLbkz31TyZE
15 ChIJZSEr_sSmlVQR2EWPtgHcGOo
16 ChIJV-MXEy-nlVQRJhsRJpcp3GQ
17 ChIJXTsSpv8JlVQRy9gDQuP28Ns
18 ChIJxzm2ananlVQRdnpTr9d_fw4
19 ChIJWxEvmEynlVQRyFgr46kf0uw
20 ChIJd9jW0dGglVQR3tOtwAPiBWw
                                                                                       types
1                          meal_takeaway, restaurant, food, point_of_interest, establishment
2                                    bar, restaurant, food, point_of_interest, establishment
3                                         restaurant, food, point_of_interest, establishment
4                                         restaurant, food, point_of_interest, establishment
5      meal_delivery, meal_takeaway, bar, restaurant, food, point_of_interest, establishment
6                                    bar, restaurant, food, point_of_interest, establishment
7                                         restaurant, food, point_of_interest, establishment
8                                         restaurant, food, point_of_interest, establishment
9           meal_delivery, meal_takeaway, restaurant, food, point_of_interest, establishment
10                                        restaurant, food, point_of_interest, establishment
11          meal_delivery, meal_takeaway, restaurant, food, point_of_interest, establishment
12                         meal_delivery, restaurant, food, point_of_interest, establishment
13     meal_delivery, meal_takeaway, bar, restaurant, food, point_of_interest, establishment
14                                        restaurant, food, point_of_interest, establishment
15                                        restaurant, food, point_of_interest, establishment
16 night_club, meal_takeaway, bar, restaurant, food, point_of_interest, store, establishment
17     meal_delivery, meal_takeaway, bar, restaurant, food, point_of_interest, establishment
18                         bakery, restaurant, food, point_of_interest, store, establishment
19                            bar, restaurant, food, point_of_interest, store, establishment
20                                   bar, restaurant, food, point_of_interest, establishment
   user_ratings_total
1                1354
2                1262
3                 402
4                 734
5                1028
6                 706
7                1358
8                 834
9                 645
10                473
11                258
12                 83
13               2038
14                 84
15                353
16                432
17                378
18                173
19                241
20                547
res_next <- google_places(search_string = "Pizza Restaurants in Portland, Oregon",
                          page_token = res$next_page_token)

res_next$results
list()

Nearby

For a nearby search you are required to provide a location as a pair of latitude/longitude coordinates. You can refine your search by providing a keyword and / or a radius. For this example, let’s say I want to find coffee shops near (within 1/2 mile) Nelson\Nygaard’s Portland office.

coffee_places <- google_places(location = geocoded_nn_office_locs[geocoded_nn_office_locs$City=="Portland",
                                                    c('geocode_lat','geocode_lng')] %>%
                       as.numeric(),
                    keyword = "Coffee",
                    # 1/2 mile in meters
                    radius = 1609.344/2)

coffee_places$results
   business_status geometry.location.lat geometry.location.lng
1      OPERATIONAL              45.52181             -122.6734
2      OPERATIONAL              45.52357             -122.6826
3      OPERATIONAL              45.52381             -122.6820
4      OPERATIONAL              45.52376             -122.6718
5      OPERATIONAL              45.52046             -122.6805
6      OPERATIONAL              45.52372             -122.6748
7      OPERATIONAL              45.52203             -122.6817
8      OPERATIONAL              45.51909             -122.6795
9      OPERATIONAL              45.52175             -122.6764
10     OPERATIONAL              45.51868             -122.6767
11     OPERATIONAL              45.52516             -122.6834
12     OPERATIONAL              45.51517             -122.6759
13     OPERATIONAL              45.52580             -122.6747
14     OPERATIONAL              45.52054             -122.6788
15     OPERATIONAL              45.51908             -122.6823
16     OPERATIONAL              45.51694             -122.6749
17     OPERATIONAL              45.51898             -122.6749
18     OPERATIONAL              45.52167             -122.6782
19     OPERATIONAL              45.51594             -122.6817
20     OPERATIONAL              45.51921             -122.6752
   geometry.viewport.northeast.lat geometry.viewport.northeast.lng
1                         45.52318                       -122.6722
2                         45.52477                       -122.6810
3                         45.52516                       -122.6805
4                         45.52516                       -122.6704
5                         45.52176                       -122.6792
6                         45.52511                       -122.6734
7                         45.52346                       -122.6804
8                         45.52057                       -122.6782
9                         45.52349                       -122.6746
10                        45.52002                       -122.6753
11                        45.52649                       -122.6821
12                        45.51654                       -122.6746
13                        45.52715                       -122.6733
14                        45.52192                       -122.6773
15                        45.52050                       -122.6811
16                        45.51832                       -122.6737
17                        45.52028                       -122.6736
18                        45.52304                       -122.6769
19                        45.51726                       -122.6802
20                        45.52055                       -122.6738
   geometry.viewport.southwest.lat geometry.viewport.southwest.lng
1                         45.52048                       -122.6749
2                         45.52207                       -122.6837
3                         45.52246                       -122.6832
4                         45.52246                       -122.6731
5                         45.51906                       -122.6819
6                         45.52241                       -122.6761
7                         45.52076                       -122.6831
8                         45.51787                       -122.6809
9                         45.52079                       -122.6773
10                        45.51732                       -122.6780
11                        45.52379                       -122.6848
12                        45.51384                       -122.6773
13                        45.52445                       -122.6760
14                        45.51922                       -122.6800
15                        45.51780                       -122.6838
16                        45.51562                       -122.6764
17                        45.51758                       -122.6763
18                        45.52034                       -122.6796
19                        45.51456                       -122.6829
20                        45.51785                       -122.6765
                                                                                  icon
1              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
2              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
3              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
4              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
5              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
6  https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/generic_business-71.png
7              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
8              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
9              https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
10             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
11             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
12             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
13             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
14             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
15             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
16             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
17             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
18             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
19             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
20             https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/cafe-71.png
   icon_background_color
1                #FF9E67
2                #FF9E67
3                #FF9E67
4                #FF9E67
5                #FF9E67
6                #7B9EB0
7                #FF9E67
8                #FF9E67
9                #FF9E67
10               #FF9E67
11               #FF9E67
12               #FF9E67
13               #FF9E67
14               #FF9E67
15               #FF9E67
16               #FF9E67
17               #FF9E67
18               #FF9E67
19               #FF9E67
20               #FF9E67
                                                    icon_mask_base_uri
1     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
2     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
3     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
4     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
5     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
6  https://maps.gstatic.com/mapfiles/place_api/icons/v2/generic_pinlet
7     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
8     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
9     https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
10    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
11    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
12    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
13    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
14    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
15    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
16    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
17    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
18    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
19    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
20    https://maps.gstatic.com/mapfiles/place_api/icons/v2/cafe_pinlet
                              name open_now
1        Stumptown Coffee Roasters    FALSE
2                    Peet's Coffee     TRUE
3                        Starbucks     TRUE
4  Floyd’s Old Town Coffee and Tea    FALSE
5                      Good Coffee    FALSE
6        Deadstock Coffee Roasters    FALSE
7        Stumptown Coffee Roasters     TRUE
8                        Starbucks     TRUE
9                        Starbucks     TRUE
10                       Starbucks     TRUE
11                    Caffe Umbria    FALSE
12                       Starbucks     TRUE
13                Monte Rossa Cafe    FALSE
14                 Java Man Coffee     TRUE
15      Case Study Coffee Roasters    FALSE
16               40 LBS Coffee Bar    FALSE
17       Lotus & Bean Espresso Bar     TRUE
18               Oak Street Coffee    FALSE
19                    Caffe Umbria    FALSE
20                         Barista    FALSE
                                                                                                                                                                                                                                                                                       photos
1        3006, <a href="https://maps.google.com/maps/contrib/108954884157711984673">Pam Noble</a>, Aap_uEDLQKFXx0adGadxuIADcJr6H72tI52xX6vI-Fg5anyjH0Sb4XLuzL8Np6ab54S6w5000NtV9AQWZxrJlJJrHM8H9Fx2YdbsuJxvNgmV2NmqFTdi0QRNdv_giPv5vMyEkM63_ARdKULpESpt79bNP5Zp8kCX95yAuy6wrxOLBao7BiSp, 5344
2   3462, <a href="https://maps.google.com/maps/contrib/108080134944183141178">Rebekah Measor</a>, Aap_uEANpYA5cCOJ_Xv1Y_0TftiVbhk18BGP0CWErTFzq_jYuu4wvrnIvUpAe_Swomgn0Heav3DLh7F0JIPx-OUze6AtChojd3x439gdZCbbULf2rHAUPXDWzsGErSciirg8KFs7pyOSIoeL-pKkbYUtoVzp3PYehxby2U65vB7ZU-EOKzla, 3024
3          640, <a href="https://maps.google.com/maps/contrib/107975895444334477276">Starbucks</a>, Aap_uEASsWibBW4aZ_nPeIKTdQxsHyvccMLjNKi3LipsNoreUiN-IAYQhJ-LUnDv1x5EHM-jmv6mc4pca-A1Y_vf0_atLWmkHPtxWM2mQ35TZwUMRGAGXrfmZrXCMPVCU86elFlZtvpu1659NVf-StPs3OjfzNQ35mayW4EQ_5x2g9jNynyG, 640
4    2048, <a href="https://maps.google.com/maps/contrib/107386413977283801307">A Google User</a>, Aap_uEBLHiJH1CRbFv171xJAPWFqQvtvjll1JVEuIbR3AymCP30H1j_2vp1cwoaXaPWhyOKWkArwedX_c1D2C0MLf25cNwffNSpLYeBa5pDPDEyhEUuanv0mbwu8n35QZ_eIsEA2st7At517kd26Hu3E0aLYFR5eR6xf6CxdyrDEKiMAfyer, 1803
5  4032, <a href="https://maps.google.com/maps/contrib/108808317319422578823">Pechluck Laskey</a>, Aap_uECRKpBlKT3cLSH48Yi2RRuQotcyNcVnUr-0OVJueB67D0tw1HhFN7kiLE-Vo3cnOaxG3vVpdC0uwkidvP_3gxGSSa4jr2WJOgRH_ya9a1ewbEvfKpGlRHCRyEE4UdiZO-fN3rrdGdkgGs4JnFBkQNsFKxMHMO2vi7ym75Sbvxvu7ffk, 2268
6   3024, <a href="https://maps.google.com/maps/contrib/106010650814475146264">Dylan Glockler</a>, Aap_uED12RBtvU6QUTUrCEZwucbSP4gHQljJ8zLpCtOs_EwVnfv0hT9As_uQILnLtHwOqOKWqPROd3ZJTw41k2K_9CA2wKUI2BCrDmTxJi4rAjs50uHc3-JtJNXqg66Gv0g4HPPvtk7MdtawJ3WgLFspgOHyPTrAYQ-wiQ5XbfDOcjzjkvW3, 4032
7     2268, <a href="https://maps.google.com/maps/contrib/109489623836216076383">Sungwoo Shin</a>, Aap_uEBnpcditvXlS6UmlROQyH1qRGgH8hOoDEcGrvaw_0mp_rFs5UqwsN_atFAvgbZPUcpG7nHkARsisD1E5bLZhXjerh9Zufqu6Zj7hcwUffvCFMq67dZsK0jmX0TVbwAwTuecb_kmZJJFT8AEadtpK7eT4FqEN0bkzLgnl_b3bPh1cBv3, 4032
8          640, <a href="https://maps.google.com/maps/contrib/115380073066177256513">Starbucks</a>, Aap_uEBSqwkLQPmRZyCdZnHAwJ6cgek_er813bYOBq8l1RWCl24SwBYrrXIQL8mNYpYoJUy7h-IWywavh3_a5SA3pYeNtaDlc7k-XJRyPprRH5qRwUjx-gHoC4pzbn3qIiF4yYY27ItSFMFDZf0kYq8KqVIMeZDHqsx9CRyf_AqWMwfEyVWJ, 640
9          640, <a href="https://maps.google.com/maps/contrib/107882765268909810514">Starbucks</a>, Aap_uEDIpJax7aJ8bPWGMpORu2jDXKprdud8wGZjJ7jBnYgg1xuBiGK1f_V9-t36zw2a9FpUY1NaygA7RQ0l1D5mFhGO_ubNYV1IwQr2rJT1zyYQgETqXhoGRDzMQibT_sbicairbDnG70P2VVtJfOet7pqPLqZebI5IUuFlNhbQieDU6-Am, 640
10         640, <a href="https://maps.google.com/maps/contrib/104567762158665938088">Starbucks</a>, Aap_uEC0_Yip_HADZudZGUjJKutFPbjAmEGrAr30rzSDUhnYA1LOa5qThzdHQRBWS8JUK7yhk9IBCDsSuM-qgOX3LZJ9KFKPfz4JxMzUFsK6UjGhzSjMS65eNPzTmohgwoWtjHQh8obnqdUvDVRCpwRt2GUqC9TJc_TwaQ-0QPZbDuTJP6FA, 640
11     1962, <a href="https://maps.google.com/maps/contrib/103570895918485563288">Frank Clark</a>, Aap_uEAlQzZcW3Zp9OneMh2vcbn38Fdff7kblEB_oPXCUXQlDJiaGb2nXfvfl6lnVisMtrr4lXiZDfHO1EtlSUn-YzyCYriQYyNGsUdIwi5AAyKsnbxeYsMUNzhBDpBnAE_rIPTTG0nkF1v-xqW_CcO2HzB6y9Z2KFUvNum79jn7W_gjIk3r, 3500
12         640, <a href="https://maps.google.com/maps/contrib/102049530425505616473">Starbucks</a>, Aap_uEBZfPeTxjWf0UK_0VdQ3HFAAd3YeARaHQvaxQin4INkhKyGGtiaWAdbXEbkKJQNCbScjTSU3Xfvk4s5L5M2QAYEugSP0IueGkWc9nUF42qhdQ-11bRJqu6VukT_ybd5DHcUoRdeMGBfO7b94HhSrS2u4HNnjoGZ9cjTx_tglU1o1Osr, 640
13    2268, <a href="https://maps.google.com/maps/contrib/100908481932671333347">Jason Savard</a>, Aap_uEA4t6ku3CZdvVrHf6GoDM7mbtujKE93oegmoUtXIMd6sd0JDag_PKdNcbGzgUR-tVOdz1Fy6a1f5RUhiRZH41rGt1NfnLd0btTr3VvQr5xS6oZWuCJdKXtbYuVPsa5a0Ls-KEjyh0Rj-Ljl6CdpmOcyaLHVVpmqz1EiANH2B0YmD38B, 4032
14     1536, <a href="https://maps.google.com/maps/contrib/115792047204719328362">Erin Morgan</a>, Aap_uECWhXUJK43lPEwiHyTeoJ8yxsq6uC5nw2hGJSclEJXlVQM1wJDH13q0CQ2n5z309eTr5E_MTnetA4KJyQJudbZlPmIhqZZHDvqLRZSVrCveHm2GMIEgTJPKEp_JXy5vUJ7gJpN0Zs2C4W5WRBwfu4IbP-8b9ya0UuassBSFjCivGrrH, 1536
15   3024, <a href="https://maps.google.com/maps/contrib/105563671497046863385">A Google User</a>, Aap_uEBhWQJ5YOturOV5WEifw9pJ9JE_wTiOHf9jdfSlbSa18F6Fz8_vuXvbmmO0hc77_iJJOSm5K6DEvqF-OaaxA9al2CSpW3g6_CZw1BN5kVWcRngwrY-OzcANb5TZC-wrEGi7hlRdkBcAyRURiFj4aNzE8CBH8j8iUU12Q3RrUauUF-YC, 3024
16       4032, <a href="https://maps.google.com/maps/contrib/114536074152579087296">Quang Cao</a>, Aap_uEAriP79B8DstS0R749_TuN05LGcbqZ2QHQ5Sv4VSPHFS6XbHzgbRowA1n6Mli32bKQpLJ6EKR9-8X6G7YvpC8KPCELrtGfLw-el2e_ovdKe8tfx77AeLVP6VLBjlQv0qm4BLvjTDcgncnHa5Vlksm_dZGa-ZzsCZXFJuWABZSn4I2QL, 3024
17   3024, <a href="https://maps.google.com/maps/contrib/101976407617562625526">Tania Vazquez</a>, Aap_uEAXCL94hqiNk5YR1lkNLP2jWMKCUhZZ8t-uCc4vuz-BacCVWu9UMw9cyXujNBi-wlvkW9phmiOuGm6p7BzIAJzzjTlx1uGIFzEdcp4jdi_1nR3FFiDEKTm5j2ymnGMx2a_k3G7c-K7O4nSDeNgfvHJN9-_llo_lNSYh44xsjI8INuTJ, 4032
18             2268, <a href="https://maps.google.com/maps/contrib/102857705357739077500">M R</a>, Aap_uECpAVDqix6H_Tijv5olBFhlM3BDqr5s4m0kQdKB9k2_gVafB-A-6UrtLtUywCVuf5nPviJSO1QuIyFU3BZzDQHumK4JYzwQYts52BogOEuG0B5lA2MsfNEu-voM5EcZBMBEs5TizLZ1a48AgHf6Py-qGX5ggHQjIHRgCplRqnvKi-bq, 4032
19          1960, <a href="https://maps.google.com/maps/contrib/112824408072887338217">jitain</a>, Aap_uEBZhG2FgdKfAr4ntsE7yn2vOKao8CRBbdFS8PVgge7NuG_HVJ6KIgcR09ZifVhWNsudoql8lqiad8nMffGoCDBrgLCmUZKwDzpMgc44BkodOrn4GykQtdGQGzczwRFeOwmSXWheh-O8UFw2PmqNX2sNEebjg9bbvUpDSqmHjH_CFJ0Y, 4032
20 2988, <a href="https://maps.google.com/maps/contrib/110054745486284461024">Alexander Assaf</a>, Aap_uEBAp14Lhrp_GkCjjfuI4wW_xbF0aW8B6EgSBZkGbqo9sC2MVK3_LZ2ywuqxGt4gP3zkFuZJ8K-ulSbCioq15WpJGQDQSDTQZc44Urnq9OtOI_awsPT7MZ9Ni4RTqeCtAX0RkwTuTbo73PZj6bWT3ki2yYgzkZyt1decPhnbywm9uHwM, 3984
                      place_id  plus_code.compound_code
1  ChIJbT5i5AYKlVQRHZOtE8vGAz4 G8CG+PJ Portland, Oregon
2  ChIJ_wdrTQIKlVQRDcL-s6A0eDA G8F8+CX Portland, Oregon
3  ChIJSygYNgIKlVQRcuggCkRVdSI G8F9+G6 Portland, Oregon
4  ChIJ08SJUgcKlVQR1c8wx0aBbzY G8FH+G7 Portland, Oregon
5  ChIJo_InCAALlVQRdKfgYL6cqZo G8C9+5Q Portland, Oregon
6  ChIJG6gpPP0LlVQRHe3kcr-SPIQ G8FG+F3 Portland, Oregon
7  ChIJE3yYoQMKlVQRyA3ST6WwBK0 G8C9+R8 Portland, Oregon
8  ChIJqVreHAUKlVQRcoDiRzeZNhw G89C+J6 Portland, Oregon
9  ChIJXw2IQAQKlVQR40-X6BMUqls G8CF+PC Portland, Oregon
10 ChIJV9o1owUKlVQROhmtxXIr_ko G89F+F8 Portland, Oregon
11 ChIJqf0ZDAIKlVQRJNAvje7XR8g G8G8+3J Portland, Oregon
12 ChIJA5vStA8KlVQRSlVkevQDhI4 G88F+3J Portland, Oregon
13 ChIJ_3UiYwAKlVQROR4QxqDuNMY G8GG+84 Portland, Oregon
14 ChIJP2zmzQUKlVQRJ-381h7ZPSk G8CC+6F Portland, Oregon
15 ChIJa92lywQKlVQRXlkX4rXNbnM G899+J3 Portland, Oregon
16 ChIJU4tRdw8KlVQRmKqZNp2bgpg G88G+Q2 Portland, Oregon
17 ChIJQfk56AUKlVQRM-qmg4WNLaM G89G+H2 Portland, Oregon
18 ChIJW4DXCAQKlVQR9JXwnbYFpNM G8CC+MP Portland, Oregon
19 ChIJu7LimxoKlVQRZBl14KtaqgM G889+98 Portland, Oregon
20 ChIJi9ihzvgJlVQRpvyylnIqmmU G89F+MW Portland, Oregon
   plus_code.global_code price_level rating
1            84QVG8CG+PJ           2    4.4
2            84QVG8F8+CX           1    4.5
3            84QVG8F9+G6           2    4.3
4            84QVG8FH+G7           1    4.5
5            84QVG8C9+5Q          NA    4.7
6            84QVG8FG+F3          NA    4.8
7            84QVG8C9+R8           1    4.5
8            84QVG89C+J6           2    4.0
9            84QVG8CF+PC           2    4.1
10           84QVG89F+F8           2    3.9
11           84QVG8G8+3J           2    4.6
12           84QVG88F+3J           2    4.2
13           84QVG8GG+84           1    4.5
14           84QVG8CC+6F           1    4.6
15           84QVG899+J3           2    4.5
16           84QVG88G+Q2           1    4.8
17           84QVG89G+H2           1    4.7
18           84QVG8CC+MP           1    4.6
19           84QVG889+98           2    4.7
20           84QVG89F+MW           2    4.6
                     reference  scope
1  ChIJbT5i5AYKlVQRHZOtE8vGAz4 GOOGLE
2  ChIJ_wdrTQIKlVQRDcL-s6A0eDA GOOGLE
3  ChIJSygYNgIKlVQRcuggCkRVdSI GOOGLE
4  ChIJ08SJUgcKlVQR1c8wx0aBbzY GOOGLE
5  ChIJo_InCAALlVQRdKfgYL6cqZo GOOGLE
6  ChIJG6gpPP0LlVQRHe3kcr-SPIQ GOOGLE
7  ChIJE3yYoQMKlVQRyA3ST6WwBK0 GOOGLE
8  ChIJqVreHAUKlVQRcoDiRzeZNhw GOOGLE
9  ChIJXw2IQAQKlVQR40-X6BMUqls GOOGLE
10 ChIJV9o1owUKlVQROhmtxXIr_ko GOOGLE
11 ChIJqf0ZDAIKlVQRJNAvje7XR8g GOOGLE
12 ChIJA5vStA8KlVQRSlVkevQDhI4 GOOGLE
13 ChIJ_3UiYwAKlVQROR4QxqDuNMY GOOGLE
14 ChIJP2zmzQUKlVQRJ-381h7ZPSk GOOGLE
15 ChIJa92lywQKlVQRXlkX4rXNbnM GOOGLE
16 ChIJU4tRdw8KlVQRmKqZNp2bgpg GOOGLE
17 ChIJQfk56AUKlVQRM-qmg4WNLaM GOOGLE
18 ChIJW4DXCAQKlVQR9JXwnbYFpNM GOOGLE
19 ChIJu7LimxoKlVQRZBl14KtaqgM GOOGLE
20 ChIJi9ihzvgJlVQRpvyylnIqmmU GOOGLE
                                                                                 types
1                                  cafe, food, point_of_interest, store, establishment
2                                  cafe, food, point_of_interest, store, establishment
3                      cafe, restaurant, food, point_of_interest, store, establishment
4  meal_takeaway, cafe, bar, restaurant, food, point_of_interest, store, establishment
5                                         cafe, food, point_of_interest, establishment
6                                  cafe, food, point_of_interest, store, establishment
7                                  cafe, food, point_of_interest, store, establishment
8                      cafe, restaurant, food, point_of_interest, store, establishment
9                      cafe, restaurant, food, point_of_interest, store, establishment
10                     cafe, restaurant, food, point_of_interest, store, establishment
11                                 cafe, food, point_of_interest, store, establishment
12                     cafe, restaurant, food, point_of_interest, store, establishment
13                                 cafe, food, point_of_interest, store, establishment
14             bakery, cafe, restaurant, food, point_of_interest, store, establishment
15                                 cafe, food, point_of_interest, store, establishment
16                                 cafe, food, point_of_interest, store, establishment
17                                 cafe, food, point_of_interest, store, establishment
18                                 cafe, food, point_of_interest, store, establishment
19                                 cafe, food, point_of_interest, store, establishment
20                                 cafe, food, point_of_interest, store, establishment
   user_ratings_total                            vicinity
1                1448            128 SW 3rd Ave, Portland
2                 146          1114 NW Couch St, Portland
3                 388          1039 NW Couch St, Portland
4                 334           118 NW Couch St, Portland
5                 122           813 SW Alder St, Portland
6                 397 408 NW Couch St Suite 408, Portland
7                 694    1026 SW Harvey Milk St, Portland
8                 567           720 SW Broadway, Portland
9                 363             555 SW Oak St, Portland
10                445        401 SW Morrison St, Portland
11                415           303 NW 12th Ave, Portland
12                155            100 SW Main St, Portland
13                 75            327 NW 4th Ave, Portland
14                114           508 SW Broadway, Portland
15               1047           802 SW 10th Ave, Portland
16                173            824 SW 2nd Ave, Portland
17                127            536 SW 3rd Ave, Portland
18                 80           322 SW Broadway, Portland
19                268         710 SW Madison St, Portland
20                342       529 SW 3rd Ave #110, Portland

Place Details

Let’s say we found the place we want to have pizza – Apizza Scholls (one of the best pizza places in Portland/the USA) – we can get some more details about that place using the place identifier (ChIJoXPFk_OglVQR_FemZBo2wf0) listed in an above table. We can use the google_place_details() function to get more details for a given place ID.

apizza_res = google_place_details('ChIJoXPFk_OglVQR_FemZBo2wf0')

apizza_res
$html_attributions
list()

$result
$result$address_components
                      long_name        short_name
1                          4741              4741
2 Southeast Hawthorne Boulevard SE Hawthorne Blvd
3                     Sunnyside         Sunnyside
4                      Portland          Portland
5              Multnomah County  Multnomah County
6                        Oregon                OR
7                 United States                US
8                         97215             97215
9                          3249              3249
                                   types
1                          street_number
2                                  route
3                neighborhood, political
4                    locality, political
5 administrative_area_level_2, political
6 administrative_area_level_1, political
7                     country, political
8                            postal_code
9                     postal_code_suffix

$result$adr_address
[1] "<span class=\"street-address\">4741 SE Hawthorne Blvd</span>, <span class=\"locality\">Portland</span>, <span class=\"region\">OR</span> <span class=\"postal-code\">97215-3249</span>, <span class=\"country-name\">USA</span>"

$result$business_status
[1] "OPERATIONAL"

$result$formatted_address
[1] "4741 SE Hawthorne Blvd, Portland, OR 97215, USA"

$result$formatted_phone_number
[1] "(503) 233-1286"

$result$geometry
$result$geometry$location
$result$geometry$location$lat
[1] 45.51212

$result$geometry$location$lng
[1] -122.6131


$result$geometry$viewport
$result$geometry$viewport$northeast
$result$geometry$viewport$northeast$lat
[1] 45.51342

$result$geometry$viewport$northeast$lng
[1] -122.6118


$result$geometry$viewport$southwest
$result$geometry$viewport$southwest$lat
[1] 45.51073

$result$geometry$viewport$southwest$lng
[1] -122.6145




$result$icon
[1] "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/restaurant-71.png"

$result$icon_background_color
[1] "#FF9E67"

$result$icon_mask_base_uri
[1] "https://maps.gstatic.com/mapfiles/place_api/icons/v2/restaurant_pinlet"

$result$international_phone_number
[1] "+1 503-233-1286"

$result$name
[1] "Apizza Scholls"

$result$opening_hours
$result$opening_hours$open_now
[1] FALSE

$result$opening_hours$periods
  close.day close.time open.day open.time
1         0       2000        0      1600
2         1       2000        1      1600
3         2       2000        2      1600
4         3       2000        3      1600
5         4       2000        4      1600
6         5       2000        5      1600
7         6       2000        6      1600

$result$opening_hours$weekday_text
[1] "Monday: 4:00 – 8:00 PM"    "Tuesday: 4:00 – 8:00 PM"  
[3] "Wednesday: 4:00 – 8:00 PM" "Thursday: 4:00 – 8:00 PM" 
[5] "Friday: 4:00 – 8:00 PM"    "Saturday: 4:00 – 8:00 PM" 
[7] "Sunday: 4:00 – 8:00 PM"   


$result$photos
   height
1    3024
2    3024
3     465
4    3387
5    4032
6    3024
7    4608
8    3024
9     959
10   4032
                                                                           html_attributions
1    <a href="https://maps.google.com/maps/contrib/118109076427664300663">Michael Meotti</a>
2     <a href="https://maps.google.com/maps/contrib/108659835961229463250">Virginia Liao</a>
3    <a href="https://maps.google.com/maps/contrib/108089377385061356284">Apizza Scholls</a>
4      <a href="https://maps.google.com/maps/contrib/104735501186242989634">Bryan Strang</a>
5               <a href="https://maps.google.com/maps/contrib/112331013496070184090">B Z</a>
6     <a href="https://maps.google.com/maps/contrib/115820244047004726048">Kelsey Butler</a>
7        <a href="https://maps.google.com/maps/contrib/101897373080317773510">Alan Ochoa</a>
8  <a href="https://maps.google.com/maps/contrib/108742225061772383593">Dariem Hernandez</a>
9     <a href="https://maps.google.com/maps/contrib/113504707222039651681">Warren Draper</a>
10 <a href="https://maps.google.com/maps/contrib/113130960113440834679">Casey Darbyshire</a>
                                                                                                                                                                        photo_reference
1  Aap_uEBVCUin5Zaq8AqQbpW1ckzVnKutY9XC1ln20n2oOAL2Qu4Tl2DPR7KIKbIQyD_BNz7u-xICX5VX2_oo6NyKcWk8PsU61RaZkI8pM8NaLgrW0nHBtf8PX1uQnqQhp-DZ_m0bJ0X56Sfsubc-Ny6kILBdoAUiMbR46KT0sKD2DC5w4Zvv
2  Aap_uED-aQIxhAi2itSR2TKFkE46NcQnVrePZu83XjWmwzFzEPry33JzP_hX-BZMVhMOz5mfzj4CnkmioarKQQMJbLA0JAQcQbeQ7SjbMQFwBncb7zgKlLMkwPlgpp2tntZnf5wBKUKJACYeFCuc4m2X-mQe1TMsEHIq_Vu1EaK-ShbWeG8u
3  Aap_uECHyBmO82etp2pX3j--rW_lM2NliHK-1YxhjNqAUps7TMgOfVdMhHHfweO-QcddM6LZFhgOEaBViuVCZDN-2JauMD4nNlYS-SbEZzS2x99V1X91W_1GSPsNDb0sJweKR3DNwrLCMd3fDbNUn-oZ1ECOtHusT-TCIjZ0pNJRCVIcJA3f
4  Aap_uECO6zPhLpcNCu_bZ_qPKVv9-I9ugK2Rn0jTqTK3OapsNQzEzsOOWB8-s0UbmR0rDRFXONpYiG8KeeldNL5x4HnRxLAqCi3_kYQtzzCpjsKEO1pEyrNvIOnJkKq9G59PJ7K70EU3lCJ93iV51bCUDYrHERN2S1n5V2JUgVBy4P7_CJa8
5  Aap_uECJetg4E_FvBGFsBSBdPO_0D2e6Yl0dLmMDwZc22eWcHlzHr6Y4t8HDt5BLD5A-DfLKS5I7YDtD75yJWmNR_X66OoD_VEb51uSoP0I7tH1we8ttdY6VioEqlM3qLL0uSJj1up37nPUvyndTWYnzd4Jg1XIo7I4dDcLUmcAuLsKB-mEz
6  Aap_uECjNGCfl_Cod_rcPIdDjpwoOHxYq_TgADpvAn3IZCrS_gD9uAEdgQ_2ukiW8duzo220ayzHNLyXqO9bLV-wj_pLrYXIGsyejpX5-7cVXGSgwOZTpIQKf2ZLs5AWbSQjoAYOzl-Y_qQM9zkIlctO_AtwFY1P6KJZS3l8iC203k0w9Pan
7  Aap_uEA2oehoSbsIhiob9ABth_sZmh7uaxhE2o17MWsIn3wrOY6PHY81saiYeD5q_HXl0jYufKThgf6ysz-d1byh5AuceGjULI1s7wVgITIEb0RbtID6A8EBNbJzBoyLohgOaSSrz9XOd1vSJUIRihYab7CSargJfuBbgrZavGupTJ8UfDwU
8  Aap_uEAjy9P_-W24QrmhOrZKQW7IGMouEI9mm1a4st55KDP2WydzAtfOyfMNDzgj04V7Vy3HLBkjut4Y3X028NB3-ifIXVL9AFiGlIYEzEPsGB5N8WvlngXep_1JGMqYSHgDvE-nhXQlec7iV4pbd11IsxIqUoB-Ca4CnBLD7zlnQcVdb2jI
9  Aap_uEDb-cF2044v--MiVt5aSfY-HcJEcZuzOgGy54xHkYvZuWtlPHX51uQsFfc48g23lVghq0fcAV8-6r5xth-74-OEIc81VRfuN2bahnjrl230hOQaiIUET5K_RSv_y791oFhDX4j0a3v9lHbzFnkywGcn5VrESJh5o48AODWAPEjoJf-f
10 Aap_uECOD5A-2ImuvsvP8UyB2S57PcIuYDb36ghmDf697SMuv0zIlONhWamw8BhuTRGVIJPCHpMd1iF-0YZ1pJSbUTnabyEC5ikz3ai88ErCj2UtWHzl8Chl7prrrnulOmDlBiN7PXgxfRuog8Uqhe49RxwEwNVeDoaLhc7HkUSt_gUw5DQX
   width
1   4032
2   4032
3    592
4   3024
5   3024
6   4032
7   3456
8   4032
9    959
10  3024

$result$place_id
[1] "ChIJoXPFk_OglVQR_FemZBo2wf0"

$result$plus_code
$result$plus_code$compound_code
[1] "G96P+RP Portland, OR, USA"

$result$plus_code$global_code
[1] "84QVG96P+RP"


$result$price_level
[1] 2

$result$rating
[1] 4.6

$result$reference
[1] "ChIJoXPFk_OglVQR_FemZBo2wf0"

$result$reviews
    author_name
1 Chennault Fox
2 Hamala Makala
3  Peter Strnad
4    Corey King
5  Paige Prince
                                                         author_url
1 https://www.google.com/maps/contrib/104956121426713060631/reviews
2 https://www.google.com/maps/contrib/115673259899623382692/reviews
3 https://www.google.com/maps/contrib/101037240028037436920/reviews
4 https://www.google.com/maps/contrib/109044887366519031985/reviews
5 https://www.google.com/maps/contrib/104538158936870008963/reviews
  language
1       en
2       en
3       en
4       en
5       en
                                                                                                   profile_photo_url
1        https://lh3.googleusercontent.com/a-/AOh14GiQJgsWOUNWXCz1hpGK_1tJ8Zw7QBiCabeTeZ46=s128-c0x00000000-cc-rp-mo
2    https://lh3.googleusercontent.com/a-/AOh14Gi27BXFX6ba2JC5Eo68WzTwX-Gmo8To69flWw_c=s128-c0x00000000-cc-rp-mo-ba5
3     https://lh3.googleusercontent.com/a/AATXAJx4Lx95G2lRGzvy9FpNkFh7w5d4ihQlq6Cxu-_S=s128-c0x00000000-cc-rp-mo-ba3
4 https://lh3.googleusercontent.com/a-/AOh14Gj5lYPX1Cw1OzTdflD6taqhqMFaC5-UEs1eZTJupJs=s128-c0x00000000-cc-rp-mo-ba3
5    https://lh3.googleusercontent.com/a-/AOh14GhEul5sTDwtvTOvbQmMsIDtIc8S2mgmtizCcJPW=s128-c0x00000000-cc-rp-mo-ba3
  rating relative_time_description
1      5              2 months ago
2      5               3 weeks ago
3      3              4 months ago
4      5             11 months ago
5      5               3 weeks ago
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          text
1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       We love coming here. I bring my son in once a month or so and we get pizza and play arcade games. It is a classic pizza parlor that turns out delicious pies and top notch salads. I think it is the best pizza in town. We usually get the sausage and mama and are never disappointed. The service is speedy and everyone has been kind and helpful.
2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          When we came here we were surprised that Portland was actually known for pizza. This was one of the several recommended spots, and it was one of the closest to New York style pizza I have had on the west coast. Would highly recommend the truffle flavor. The pizzas are quite large as well, would recommend getting half and half to try all the topping combinations (they all taste great).
3 Good local pizza.  Portland, like most of the country doesn't have *great* pizza, that's okay.  And let’s not pretend it does.\n\nSome claimed this was the best New Haven style pizza outside New Haven.  I lived in New Haven for almost 4 years.  Nope. ** It isn't New Haven pizza, the owner never claimed this, but it appears they don’t correct media which assert this.  They should correct media if they aren’t “new Haven style” because it ain’t.\n\nThe pizza does stand out with crispy, chewy crust, even if it's not coal fired.  Impressive none the less.\n\nApizza Scholls, and most things in Portland or towns that get unnecessary hype like Portland, Austin etc... are fine local establishments, but please, stop with the excessive national recognition of decent local spots.\n\nApizza Scholls would be the best pizza in a typical Iowa or Arkansas or Oregon City.  That's what It is, excellent local pizza.  That's good enough for me. I'd eat it again, but I wouldn't sit in traffic or stand in line for an hour for it, 15 min? Sure.
4                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         We have always adored Apizza Schools.\n\nBut we could never of predicted the treatment they gave to us for our wedding. On oct 23 we had our fantastic downtown ceremony and our first task as a married couple was to pick up Apizza Scholls. Not only did they remind me day of to submit the order to ensure my plan was successful, they gave us a complimentary bottle of Rose and everyone knew exactly who we were and why we were there. They mad us feel special. Pizza Scholls is perfect.
5                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              My fiancé picked up a New York White Pie and a meatball & onion pie on his way home from work tonight (I’m having surgery in a few days and cooking just isn’t happening right now). The NY pizza was really good, if a little garlicky. The different cheeses were excellent. I had a bite of the meatball & onion pizza and it was really tasty, even though I don’t normally like meat on my pizza. I’d say Apizza Scholls would be in my top 4 of my all time pizza places.
        time
1 1629211987
2 1634514007
3 1625686273
4 1607046036
5 1634615654

$result$types
[1] "meal_takeaway"     "restaurant"        "food"             
[4] "point_of_interest" "establishment"    

$result$url
[1] "https://maps.google.com/?cid=18284955449086597116"

$result$user_ratings_total
[1] 1504

$result$utc_offset
[1] -480

$result$vicinity
[1] "4741 Southeast Hawthorne Boulevard, Portland"

$result$website
[1] "http://apizzascholls.com/"


$status
[1] "OK"

Directions

The Directions API is what you are you using when you query directions on your phone – we can do the same through R to extract routing information programatically. We’re going to demonstrate a simple query of origin/destination below using Nelson\Nygaard’s Portland Office and Apizza Scholls for all the modes Google allows – i.e. driving, transit, bicycling, and walking. There are many more parameters that can be set for this function – e.g. departure/arrival time, routing preferences, traffic model. Consider the documentation for the function (?google_directions) as well as the documentation for the API itself. There are more examples of the use of this API with more detailed parameters in another webinar presented in January 2021, available here.*

o_xy = geocoded_nn_office_locs[geocoded_nn_office_locs$City=="Portland",
                                                    c('geocode_lat','geocode_lng')] %>%
  as.numeric()
d_xy = apizza_res$result$geometry$location %>% unlist()

dir_results = tibble(
  mode = c('driving','transit','bicycling','walking')
) %>% mutate(dir_result = map(mode,~google_directions(o_xy,d_xy,mode=.x)))

Each direction result object is a list with a lot of different contents – let’s print one below to take a look at what is in inside of it.

print(dir_results$dir_result[[1]])
$geocoded_waypoints
  geocoder_status                    place_id
1              OK ChIJAQCs2PoJlVQRjFf6WT1JcOM
2              OK ChIJ-XLFk_OglVQRQaiWw9DDFAo
                                     types
1 establishment, health, point_of_interest
2                           street_address

$routes
  bounds.northeast.lat bounds.northeast.lng bounds.southwest.lat
1             45.53421            -122.6124             45.51203
  bounds.southwest.lng     copyrights
1            -122.6806 Map data ©2021
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              legs
1 9.1 km, 9078, 15 mins, 871, 4741 SE Hawthorne Blvd, Portland, OR 97215, USA, 45.5120297, -122.6130917, 610 SW Broadway #306, Portland, OR 97205, USA, 45.5192367, -122.6791333, 0.1 km, 75 m, 0.5 km, 0.5 km, 0.3 km, 1.1 km, 2.9 km, 0.3 km, 0.7 km, 0.8 km, 0.8 km, 0.8 km, 57 m, 120, 75, 505, 517, 338, 1103, 2918, 292, 692, 839, 816, 806, 57, 1 min, 1 min, 2 mins, 1 min, 1 min, 1 min, 2 mins, 1 min, 1 min, 2 mins, 2 mins, 2 mins, 1 min, 38, 32, 117, 39, 22, 55, 119, 25, 72, 108, 108, 122, 14, 45.5196228, 45.5202627, 45.5186757, 45.5173116, 45.5181872, 45.5257573, 45.5338439, 45.5328879, 45.5267023, 45.519288, 45.5192766, 45.5120313, 45.5120297, -122.6805713, -122.6802548, -122.6741795, -122.6678662, -122.6657199, -122.6601232, -122.6264494, -122.6229694, -122.6232231, -122.6230312, -122.6125564, -122.6123571, -122.6130917, Head <b>west</b> on <b>SW Morrison St</b> toward <b>SW Broadway</b>, Turn <b>right</b> onto <b>SW Park Ave</b>, Turn <b>right</b> at the 1st cross street onto <b>SW Alder St</b>, Slight <b>left</b> onto <b>SE Morrison Bridge</b>, Keep <b>left</b> at the fork, follow signs for <b>Airport</b>/<wbr/><b>I-5 N</b>/<wbr/><b>I-84 E</b>/<wbr/><b>Seattle</b>/<wbr/><b>The Dalles</b>, Keep <b>right</b> at the fork, follow signs for <b>Portland Arpt</b>, Continue onto <b>I-84 E</b>, Take exit <b>2</b> for <b>Cesar E Chavez Blvd</b>, Turn <b>right</b> onto <b>NE Cesar E Chavez Blvd</b>/<wbr/><b>César E. Chávez Blvd</b>, At the traffic circle, take the <b>2nd</b> exit onto <b>NE Cesar E Chavez Blvd</b>/<wbr/><b>SE Cesar Estrada Chavez Blvd</b>/<wbr/><b>César E. Chávez Blvd</b>, Turn <b>left</b> onto <b>SE Stark St</b>, Turn <b>right</b> onto <b>SE 49th Ave</b>, Turn <b>right</b> onto <b>SE Hawthorne Blvd</b>, gnytGpwwkVW~AI^CNKn@Mn@Kn@, spytGp`xkVcAa@a@OYM, stytGp~wkVZoBRuAr@_E@Ix@sE@Ip@{D`@yBTsAn@eE, wjytGrxvkVDq@B[@WBq@@C@SBi@?GBY@M@_@@GBYD_@@UF]?CBSBO?ATaBF_@?AF]DQJo@Lu@d@kCd@oCZiBZyADW@I@G, ebytGdqukV^qBF]Jo@TmADY@S@O@WCc@EYESGOIOGKGGYSKEKCKCU?SDOFMFQNQPKH]Z, ugytGvcukVa@PA@C@MFKBA?QBS?K?WGYKSGSI}@Yk@MmA[[G]IG?a@IUGKAm@KYCA?W?C?g@BgAA_B?_@@Y?e@A]?A?AA]?a@CG?SAi@EOCQCQEOGCCYKQMUOWUMQQWMWEKCCGMOa@Kc@?AKc@Ea@CUEe@CSGgAIcBMmAAI?EEa@CME]ACEUGW?CGUGSGU?AY}@CKCGC_@, _wztGv`tkV}@}BUi@Um@CEg@kAu@kBk@yAUm@Oq@w@cCkAcE?Au@kDCWUmA]qB?A?AAA?EA??C}@iFUuA_@aCQcAIk@[oBa@}BWgBAOEUMyAI_ACs@EcAA_@EyACgAAu@KsGA_@A_AAW?C?A?AAIAu@EcDEuBSiLGuCMoHCoAAs@A[AO?CCu@EwAAg@KkAIq@?CIe@CUG[Mk@]eA]u@e@}@g@s@a@i@kAiAoAeA_Aw@i@g@o@g@k@s@i@y@k@mA_@_AU_AYwAGg@Ga@C[A_@A]A[?_@?A@qADaAFaAFm@T}BBIFg@Fc@H], oi|tGhnmkVVw@FWHg@?AJi@DQ^}BHa@F[\\oBT}A?AHk@@EHi@@EBS, qc|tGpxlkVrA@b@?b@?lA?h@@vAAt@AN?r@@tA@nCBlCAlCAnC?^?|@l@, {|ztGbzlkVBHBBBDDBBBDBDBD@D?D@DAD?DADCBCBABEBCBEBC@Ex@k@@?d@?nC@hC?tC@bB@p@AjB?zA?N?lC?jCBh@AfA?vA?, qnytG|xlkV?oB?S?yB?yF?_B?eB?wI?cB@kF?wD?g@?w@?U?iC?uA?U?u@?S?yA, onytGnwjkVnCAlC?lC?nA@b@?VAH?f@@l@?jB?XAzAId@AlAAn@AbCEbBCXApAEj@AJA, eaxtGfvjkV?`A?L?`A, 45.5192367, 45.5196228, 45.5202627, 45.5186757, 45.5173116, 45.5181872, 45.5257573, 45.5338439, 45.5328879, 45.5267023, 45.519288, 45.5192766, 45.5120313, -122.6791333, -122.6805713, -122.6802548, -122.6741795, -122.6678662, -122.6657199, -122.6601232, -122.6264494, -122.6229694, -122.6232231, -122.6230312, -122.6125564, -122.6123571, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, NA, turn-right, turn-right, turn-slight-left, fork-left, fork-right, NA, ramp-right, turn-right, roundabout-right, turn-left, turn-right, turn-right
                                                                                                                                                                                                                                                                                                                                                                                                                                                            points
1 gnytGpwwkVq@~DY~AeBq@YMZoBfAuGnBcLv@mEn@eEDq@Ds@Du@H_BHoAl@_FzBsMtBmLZgBBc@A{@Km@Q_@OSe@YWGU?c@L_@V]Z]Za@PEBYJSB_@?q@Sg@QiBg@oCm@qB_@w@CoB@_C@_BAaAEuAKw@Uk@Ym@e@_@i@Sc@KQ[eAU}A[eFO}AQqAUgAi@iBGSC_@}@}Bk@wAk@qAaBeEe@_Bw@cCkAcEu@mDw@yECMeCeO_BaK_@_EQqFWoOy@ke@UiJU}BIi@Kq@k@qBcAsBiA}A{CoCiB_Bo@g@k@s@i@y@k@mA_@_AU_Aa@_CK}@C}@?oCLcC\\kD\\sBVw@P_Ap@{DdAkGT}ADYvB@rF?nE@nCBlCA|GA^?|@l@FLRPPDVAPOLSz@k@tD@tL@dJ?tI@?yb@@oW?iA?yAnCAzG?rB@vB?dCA`CKdJMbDK?pC
  summary warnings waypoint_order
1  I-84 E     NULL           NULL

$status
[1] "OK"
#The route itself is stored in the `legs` column of the `routes` table
#From here you can extract information about the entire route, or individual steps

print(dir_results$dir_result[[1]]$routes$legs)
[[1]]
  distance.text distance.value duration.text duration.value
1        9.1 km           9078       15 mins            871
                                      end_address end_location.lat
1 4741 SE Hawthorne Blvd, Portland, OR 97215, USA         45.51203
  end_location.lng                                 start_address
1        -122.6131 610 SW Broadway #306, Portland, OR 97205, USA
  start_location.lat start_location.lng
1           45.51924          -122.6791
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             steps
1 0.1 km, 75 m, 0.5 km, 0.5 km, 0.3 km, 1.1 km, 2.9 km, 0.3 km, 0.7 km, 0.8 km, 0.8 km, 0.8 km, 57 m, 120, 75, 505, 517, 338, 1103, 2918, 292, 692, 839, 816, 806, 57, 1 min, 1 min, 2 mins, 1 min, 1 min, 1 min, 2 mins, 1 min, 1 min, 2 mins, 2 mins, 2 mins, 1 min, 38, 32, 117, 39, 22, 55, 119, 25, 72, 108, 108, 122, 14, 45.5196228, 45.5202627, 45.5186757, 45.5173116, 45.5181872, 45.5257573, 45.5338439, 45.5328879, 45.5267023, 45.519288, 45.5192766, 45.5120313, 45.5120297, -122.6805713, -122.6802548, -122.6741795, -122.6678662, -122.6657199, -122.6601232, -122.6264494, -122.6229694, -122.6232231, -122.6230312, -122.6125564, -122.6123571, -122.6130917, Head <b>west</b> on <b>SW Morrison St</b> toward <b>SW Broadway</b>, Turn <b>right</b> onto <b>SW Park Ave</b>, Turn <b>right</b> at the 1st cross street onto <b>SW Alder St</b>, Slight <b>left</b> onto <b>SE Morrison Bridge</b>, Keep <b>left</b> at the fork, follow signs for <b>Airport</b>/<wbr/><b>I-5 N</b>/<wbr/><b>I-84 E</b>/<wbr/><b>Seattle</b>/<wbr/><b>The Dalles</b>, Keep <b>right</b> at the fork, follow signs for <b>Portland Arpt</b>, Continue onto <b>I-84 E</b>, Take exit <b>2</b> for <b>Cesar E Chavez Blvd</b>, Turn <b>right</b> onto <b>NE Cesar E Chavez Blvd</b>/<wbr/><b>César E. Chávez Blvd</b>, At the traffic circle, take the <b>2nd</b> exit onto <b>NE Cesar E Chavez Blvd</b>/<wbr/><b>SE Cesar Estrada Chavez Blvd</b>/<wbr/><b>César E. Chávez Blvd</b>, Turn <b>left</b> onto <b>SE Stark St</b>, Turn <b>right</b> onto <b>SE 49th Ave</b>, Turn <b>right</b> onto <b>SE Hawthorne Blvd</b>, gnytGpwwkVW~AI^CNKn@Mn@Kn@, spytGp`xkVcAa@a@OYM, stytGp~wkVZoBRuAr@_E@Ix@sE@Ip@{D`@yBTsAn@eE, wjytGrxvkVDq@B[@WBq@@C@SBi@?GBY@M@_@@GBYD_@@UF]?CBSBO?ATaBF_@?AF]DQJo@Lu@d@kCd@oCZiBZyADW@I@G, ebytGdqukV^qBF]Jo@TmADY@S@O@WCc@EYESGOIOGKGGYSKEKCKCU?SDOFMFQNQPKH]Z, ugytGvcukVa@PA@C@MFKBA?QBS?K?WGYKSGSI}@Yk@MmA[[G]IG?a@IUGKAm@KYCA?W?C?g@BgAA_B?_@@Y?e@A]?A?AA]?a@CG?SAi@EOCQCQEOGCCYKQMUOWUMQQWMWEKCCGMOa@Kc@?AKc@Ea@CUEe@CSGgAIcBMmAAI?EEa@CME]ACEUGW?CGUGSGU?AY}@CKCGC_@, _wztGv`tkV}@}BUi@Um@CEg@kAu@kBk@yAUm@Oq@w@cCkAcE?Au@kDCWUmA]qB?A?AAA?EA??C}@iFUuA_@aCQcAIk@[oBa@}BWgBAOEUMyAI_ACs@EcAA_@EyACgAAu@KsGA_@A_AAW?C?A?AAIAu@EcDEuBSiLGuCMoHCoAAs@A[AO?CCu@EwAAg@KkAIq@?CIe@CUG[Mk@]eA]u@e@}@g@s@a@i@kAiAoAeA_Aw@i@g@o@g@k@s@i@y@k@mA_@_AU_AYwAGg@Ga@C[A_@A]A[?_@?A@qADaAFaAFm@T}BBIFg@Fc@H], oi|tGhnmkVVw@FWHg@?AJi@DQ^}BHa@F[\\oBT}A?AHk@@EHi@@EBS, qc|tGpxlkVrA@b@?b@?lA?h@@vAAt@AN?r@@tA@nCBlCAlCAnC?^?|@l@, {|ztGbzlkVBHBBBDDBBBDBDBD@D?D@DAD?DADCBCBABEBCBEBC@Ex@k@@?d@?nC@hC?tC@bB@p@AjB?zA?N?lC?jCBh@AfA?vA?, qnytG|xlkV?oB?S?yB?yF?_B?eB?wI?cB@kF?wD?g@?w@?U?iC?uA?U?u@?S?yA, onytGnwjkVnCAlC?lC?nA@b@?VAH?f@@l@?jB?XAzAId@AlAAn@AbCEbBCXApAEj@AJA, eaxtGfvjkV?`A?L?`A, 45.5192367, 45.5196228, 45.5202627, 45.5186757, 45.5173116, 45.5181872, 45.5257573, 45.5338439, 45.5328879, 45.5267023, 45.519288, 45.5192766, 45.5120313, -122.6791333, -122.6805713, -122.6802548, -122.6741795, -122.6678662, -122.6657199, -122.6601232, -122.6264494, -122.6229694, -122.6232231, -122.6230312, -122.6125564, -122.6123571, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, DRIVING, NA, turn-right, turn-right, turn-slight-left, fork-left, fork-right, NA, ramp-right, turn-right, roundabout-right, turn-left, turn-right, turn-right
  traffic_speed_entry via_waypoint
1                NULL         NULL

The data used to draw the route on the map is the overview_polyline (in the routes table). This string represents a sequence of lat/lon pairs, encoded using a lossy compression algorithm (https://developers.google.com/maps/documentation/utilities/polylinealgorithm) that allows you to store the series of coordinates as a single string.

You can extract the polyline manually

pl <- dir_results$dir_result[[2]]$routes$overview_polyline$points

Or use the direction_polyline() accessor

pl <- direction_polyline(dir_results$dir_result[[1]])
pl
[1] "gnytGpwwkVq@~DY~AeBq@YMZoBfAuGnBcLv@mEn@eEDq@Ds@Du@H_BHoAl@_FzBsMtBmLZgBBc@A{@Km@Q_@OSe@YWGU?c@L_@V]Z]Za@PEBYJSB_@?q@Sg@QiBg@oCm@qB_@w@CoB@_C@_BAaAEuAKw@Uk@Ym@e@_@i@Sc@KQ[eAU}A[eFO}AQqAUgAi@iBGSC_@}@}Bk@wAk@qAaBeEe@_Bw@cCkAcEu@mDw@yECMeCeO_BaK_@_EQqFWoOy@ke@UiJU}BIi@Kq@k@qBcAsBiA}A{CoCiB_Bo@g@k@s@i@y@k@mA_@_AU_Aa@_CK}@C}@?oCLcC\\kD\\sBVw@P_Ap@{DdAkGT}ADYvB@rF?nE@nCBlCA|GA^?|@l@FLRPPDVAPOLSz@k@tD@tL@dJ?tI@?yb@@oW?iA?yAnCAzG?rB@vB?dCA`CKdJMbDK?pC"

Having retrieved the polyline, you can decode it into latitude and longitude coordinates using decode_pl().

polyline <- "gnytGpwwkVq@~DY~AeBq@YMZoBfAuGnBcLv@mEn@eEDq@HeBFaAFoALwAl@kErBqL~@eFRg@j@}Af@cBRq@PaAFm@BWDkCCgFDe@AkE?{F?wM@cN@eGA}E@k_@DiU@_Y@aDHsAIkB@_BAkEB_SEm@?cE?cP@y^@sNQqAEm@AaS@mj@vB?dCA`CKdJMbDK?pC"

df <- decode_pl(polyline)
head(df)
       lat       lon
1 45.51924 -122.6791
2 45.51949 -122.6801
3 45.51962 -122.6806
4 45.52013 -122.6803
5 45.52026 -122.6802
6 45.52012 -122.6797

And, of course, to encode a series of lat/lon coordinates you use encode_pl()

encode_pl(lat = df$lat, lon = df$lon)
[1] "enytGpwwkVq@|DY~AgBq@WMZoBdAuGpBcLv@mEl@eEDq@HeBHaADoANwAl@kErBqL~@eFRg@j@}Af@aBPs@R_AFo@BWDkCEgFDe@?kE?{F?wM?aNBgGC}EBk_@DgU?aYBaDHsAIkB@_BAkEB_SGm@?cE?cPBy^@sNQqAEm@AaS@mj@tB?fCA`CKdJMbDK?rC"

Let’s decode the polylines for the routes we generated before, and then map them using a leaflet map.

dir_tibble_geom = dir_results %>%
  mutate(poly = map(dir_result,~direction_polyline(.x) %>%
                      decode_pl() %>%
                      #Need to reverse because Google gives you in lat,lon, you need lon, lat (X,Y)
                      select(lon,lat) %>%
                      as.matrix() %>%
                      st_linestring())) %>%
  mutate(geometry = st_sfc(poly,crs=4326)) %>%
  st_as_sf()

leaflet() %>%
  addProviderTiles('CartoDB.Positron') %>%
  addPolylines(data = dir_tibble_geom,
               label=~mode,
               color = rainbow(4))

There is of course lots of other info you can extract from these – I would encourage you to dive into the hierarchy of the list objects and come to my office hours with questions if you get stuck!

Distance Matrix

If you are only interested in the high level information for origin-destination pairs – namely travel time and distance – you can use the Distance Matrix API instead of the Directions API to query that information with fewer API calls and less extraneous information. The Distance Matrix API can handle up to 25 origins or destinations per request. If you have more pairs than this, you can simply split them up into multiple queries. Or you can do the queries one at a time – the cost is equivalent. I often find with using purrr that doing them one at a time is easier as you do not run into the limit issue. Let’s consider one of the examples we looked at earlier – coffee shops within 1/2 mile of Nelson\Nygaard’s Portland office. We will consider walking distances/travel times to each.

#Let's make sure we have every single coffee place using the next page token (since each page will only return 20 results each)

pdx_nn_xy = geocoded_nn_office_locs[geocoded_nn_office_locs$City=="Portland",
                                                    c('geocode_lat','geocode_lng')] %>%
                       as.numeric()

# Use a while loop to gather an indeterminate number of results (until there is no next page)

prev_page_coffee_places = coffee_places

all_coffee_places_list = list()
all_coffee_places_list[[1]] = coffee_places$results

i = 2

while(!is.null(prev_page_coffee_places$next_page_token)){
  
  next_page_coffee_places = google_places(location = pdx_nn_xy,
                    keyword = "Coffee",
                    radius = 1609.344/2,
                    page_token = prev_page_coffee_places$next_page_token)
  
  all_coffee_places_list[[i]] = next_page_coffee_places$results
  
  prev_page_coffee_places = next_page_coffee_places
  
  print(i)
  i = i+1
  
}
[1] 2
[1] 3
all_coffee_places_tibble = bind_rows(all_coffee_places_list) 

coffee_places_simp = tibble(list_obj = all_coffee_places_list) %>%
  mutate(place_id = map(list_obj,~.x$place_id),
         name = map(list_obj,~.x$name),
         vicinity = map(list_obj,~.x$vicinity),
         location = map(list_obj,~.x$geometry$location)) %>%
  select(-list_obj) %>%
  unnest(everything()) %>%
  #My distance matrix query using `purrr`
  mutate(dist_matrix_result = map2(lng,lat,~google_distance(origins = pdx_nn_xy,
                                                           destinations = c(.y,.x),
                                                           mode = 'walking')))

coffee_places_map = coffee_places_simp %>%
  mutate(distance_feet = map_dbl(dist_matrix_result,~.x$rows$elements[[1]]$distance$value*3.28084),
         tt_minutes = map_dbl(dist_matrix_result,~.x$rows$elements[[1]]$duration$value/60)) %>%
  st_as_sf(coords = c('lng','lat'),crs=4326)

tt_pal = colorNumeric(
  palette = brewer_pal(palette = 'RdYlGn',direction = -1)(9),
  domain = coffee_places_map$tt_minutes
)

leaflet() %>%
  addProviderTiles('CartoDB.Positron') %>%
  addMarkers(lng = pdx_nn_xy[2],lat=pdx_nn_xy[1],
             label='NN PDX') %>%
  addCircleMarkers(data=coffee_places_map,
                   color='white',weight=2,radius = 10,
                   fillColor = ~tt_pal(tt_minutes),
                   fillOpacity = 0.6,
                   label=~paste0(name,' (',comma(tt_minutes,accuracy = 0.1),' minutes, ',vicinity,')'))

You might look at this map and say, wouldn’t it be cool if we could generate polygons that would indicate, without the use of coffee shops as a proxy, where someone could walk in 5 minutes, 10 minutes, 15 minutes, etc.? To do this, we would need to develop isochrones, which we can use the distance matrix API for in the following section.

Isochrones

Below I am going to demo the procedure for developing a single isochrone for a 10 minute walk – you could duplicate this for a 5 minute walk, a 15 minute walk, a 30 minute transit ride, etc. Give it a shot and come to my office hours with questions!

Isochrones are relatively laborious to develop, because there is no way to generate them without iteration. It comes down to a geometric procedure in which you generate points arrayed around your origin point starting in a circle, but then moving towards or away from your origin point along a constant bearing line until your travel time at each of those points matches the isochrone you are trying to draw. With more constant bearing lines around your origin point, you can generate a higher resolution isochrone. We are going to keep it relatively simple and use 16 constant bearing lines to generate our isochrone – this will result in a bearing line every 22.5 degrees (360/(16)) around the circle. Let’s also generate a first iteration distance (that will be updated with a while loop) based on a typical walking speed of 1.4 meters per second. Google will take care of handling how the Euclidean distance generated point deviates from actual walking time based on the street network, crossings, etc.

o_xy = rev(pdx_nn_xy)

target_tt_minutes = 10
tolerance = 10 #seconds

init_dist_meters = (target_tt_minutes*60)/1.4 #600 seconds divided by 1.4 meters per second

init_azi_ray_tibble = tibble(
  ray_id = 1:16,
  azimuth = seq(0,359,22.5)
) %>%
  mutate(bearing = ifelse(azimuth>180,azimuth-360,azimuth),
         guess_distance = init_dist_meters) %>%
  # We are going to be relying on the `destPoint` function to generate our probe points
  mutate(current_point = map2(bearing,guess_distance,~destPoint(o_xy,.x,.y))) %>%
  mutate(dist_matrix_result = map(current_point,~google_distance(rev(o_xy),rev(.x),
                                                                 mode = 'walking'))) %>%
  mutate(current_tt_minutes = map_dbl(dist_matrix_result,~.x$rows$elements[[1]]$duration$value/60)) %>%
  mutate(ray_done = ifelse(abs(target_tt_minutes* 60 - current_tt_minutes*60)>5,FALSE,TRUE))

rays_left = nrow(init_azi_ray_tibble) - sum(as.numeric(init_azi_ray_tibble$ray_done))

# Right now, all of these travel times are less than 10 minutes, so that speed from wikipedia must have been slower than Google assumes.

iter_azi_ray_tibble = init_azi_ray_tibble

x = 1

while(rays_left>0){
  
  curr_azi_ray_tibble = iter_azi_ray_tibble %>%
    mutate(scale_factor = (((target_tt_minutes-current_tt_minutes)/2)+current_tt_minutes)/current_tt_minutes) %>%
    mutate(guess_distance = ifelse(ray_done==FALSE,guess_distance*scale_factor,guess_distance)) %>%
    mutate(current_point = ifelse(ray_done==FALSE,map2(bearing,guess_distance,~destPoint(o_xy,.x,.y)),current_point)) %>%
    mutate(dist_matrix_result = ifelse(ray_done == FALSE, map(current_point,~google_distance(rev(o_xy),rev(.x),
                                                                 mode = 'walking')),
                                     dist_matrix_result)) %>%
    mutate(current_tt_minutes = map_dbl(dist_matrix_result,~.x$rows$elements[[1]]$duration$value/60)) %>%
    mutate(ray_done = ifelse(abs(target_tt_minutes* 60 - current_tt_minutes*60)>tolerance,FALSE,TRUE))
  
  iter_azi_ray_tibble = curr_azi_ray_tibble
  print(x)
  x=x+1
  rays_left = nrow(init_azi_ray_tibble) - sum(as.numeric(iter_azi_ray_tibble$ray_done))
  
  #I am not going to let it go longer than 30 iterations
  if(x>30){
    rays_left=0
  }
  
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[1] 11
[1] 12
[1] 13
[1] 14
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20
[1] 21
[1] 22
[1] 23
[1] 24
[1] 25
[1] 26
[1] 27
[1] 28
[1] 29
[1] 30
# As we will see, because there is a water body within a 10 minute walk of our origin point, our isochrone was artificially cut off.
# If I had not cut the algorithm off after 30 iterations, it would have gone on infinitely. We will get close.

poly_points = iter_azi_ray_tibble %>%
  select(current_point) %>%
  mutate(lng = map_dbl(current_point,~.x[1]),
         lat = map_dbl(current_point,~.x[2])) %>%
  select(-current_point) 

isochrone_polygon = bind_rows(
  poly_points,
  poly_points %>% slice(1) # Need to repeat last point to close polygon
) %>%
  as.matrix() %>%
  list() %>%
  st_polygon() %>%
  st_sfc(crs = 4326)


leaflet() %>%
  addProviderTiles('CartoDB.Positron') %>%
  addMarkers(lng = pdx_nn_xy[2],lat=pdx_nn_xy[1],
             label='NN PDX') %>%
  addPolygons(data = isochrone_polygon,
              label = '10 minute walking isochrone/walkshed') %>%
  addCircleMarkers(data=coffee_places_map,
                   color='white',weight=2,radius = 10,
                   fillColor = ~tt_pal(tt_minutes),
                   fillOpacity = 0.6,
                   label=~paste0(name,' (',comma(tt_minutes,accuracy = 0.1),' minutes, ',vicinity,')'))

Shiny app usage

I also wanted to demonstrate the use of some Google APIs (distance matrix, geocoding) with Shiny – I developed this toy application to fetch travel times between (fuzzed for privacy) home locations of PDX NNers and our local (Portland) parks to figure out what the most convenient parks were for everyone. The code is here and I will show the application and step through some highlights in the code.