A demo of several useful Google APIs
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.
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.
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:
google_directions()
function. Addresses and place names need to be geocoded prior to evaluation.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>')
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)
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.
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()
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
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"
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!
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.
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,')'))
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.