<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/not-mustard-exploring-mcdonalds-reviews-on-yelp-with-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://jasdumas.github.io/2017-10-26-not-mustard-web-app/"> Jasmine Dumas' R Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>	Leveraging tidyverse packages httr, stringr &amp; purrr – </p>
<h2>Introduction</h2>
<p>McDonald’s is a nostalgic component of America <img alt="🇺🇸" src="https://s.w.org/images/core/emoji/2.3/72x72/1f1fa-1f1f8.png" class="wp-smiley"> and a pioneer of fast food operations and real estate ventures, as depicted in the 2016 film, <a rel="nofollow" href="https://www.rottentomatoes.com/m/the_founder/" target="_blank"><em>The Founder</em></a>, about Ray Kroc. As a kid I traveled to different McDonald’s across the east coast and noticed a difference in the <a rel="nofollow" href="https://www.mcdonalds.com/us/en-us/full-menu/burgers.html" target="_blank">classic hamburger</a> preparation for adding mustard (i.e. in Maryland and not in Upstate New York). After some Google research, I noticed others had documented the <a rel="nofollow" href="http://aht.seriouseats.com/2010/03/dear-aht-differences-in-regional-mustard-use-on-mcdonalds-hamburgers.html" target="_blank">regional differences</a> in the use of mustard and but no aggregated data set existed detailing which McDonald’s added mustard to their hamburgers.</p>
<p><img alt="" src="https://i2.wp.com/media.giphy.com/media/37NQLccUA0lmo/giphy.gif?w=456&ssl=1" data-recalc-dims="1"></p>
<p>I hypothesized that these deviations in food prep could be identified from <a rel="nofollow" href="https://www.yelp.com/" target="_blank">yelp.com</a> reviews. The process below explains the approaches I took to gather data from the web with the yelp API and the development of a <code>shiny</code> web application which detects string patterns in reviews for the keyword ‘mustard’ for a specific McDonald’s.</p>
<h2>API Process</h2>
<p>This script highly references Jenny Bryan’s <a rel="nofollow" href="https://github.com/jennybc/yelpr" target="_blank"><code>yelpr</code></a> example!</p>
<div>
<div>
<pre><code><span>library</span><span>(</span><span>yelpr</span><span>)</span><span> </span><span># devtools::install_github(&quot;jennybc/ryelp&quot;)</span><span>
</span><span>library</span><span>(</span><span>httr</span><span>)</span><span>
</span><span>library</span><span>(</span><span>stringr</span><span>)</span><span>
</span><span>library</span><span>(</span><span>purrr</span><span>)</span><span>
</span><span># 1. Create an application on the [Yelp developers site](https://www.yelp.com/developers/v3/manage_app) and agree to the Terms and aggreements</span><span>
</span><span>## Set your credentials as environment variables. </span><span>
</span><span>Sys.setenv</span><span>(</span><span>YELP_CLIENT_ID</span><span>=</span><span>'**************'</span><span>)</span><span>
</span><span>Sys.setenv</span><span>(</span><span>YELP_SECRET</span><span>=</span><span>'*****************************'</span><span>)</span><span>
</span><span># 2. search for businesses by creating an app</span><span>
</span><span>yelp_app</span><span> </span><span>&lt;-</span><span> </span><span>oauth_app</span><span>(</span><span>&quot;yelp&quot;</span><span>,</span><span> </span><span>key</span><span> </span><span>=</span><span> </span><span>Sys.getenv</span><span>(</span><span>&quot;YELP_CLIENT_ID&quot;</span><span>),</span><span>
</span><span>secret</span><span> </span><span>=</span><span> </span><span>Sys.getenv</span><span>(</span><span>&quot;YELP_SECRET&quot;</span><span>))</span><span>
</span><span># authenticate an endpoint</span><span>
</span><span>## https://www.yelp.com/developers/documentation/v3/authentication</span><span>
</span><span>yelp_endpoint</span><span> </span><span>&lt;-</span><span> </span><span>oauth_endpoint</span><span>(</span><span>NULL</span><span>,</span><span>
</span><span>authorize</span><span> </span><span>=</span><span> </span><span>&quot;https://api.yelp.com/oauth2/token&quot;</span><span>,</span><span>
</span><span>access</span><span> </span><span>=</span><span> </span><span>&quot;https://api.yelp.com/oauth2/token&quot;</span><span>)</span><span>
</span><span># 3. Get an access token: Just enter anything for the authorization code when prompted in the Console of RStudio</span><span>
</span><span>token</span><span> </span><span>&lt;-</span><span> </span><span>oauth2.0_token</span><span>(</span><span>yelp_endpoint</span><span>,</span><span> </span><span>yelp_app</span><span>,</span><span>
</span><span>user_params</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>grant_type</span><span> </span><span>=</span><span> </span><span>&quot;client_credentials&quot;</span><span>),</span><span>
</span><span>use_oob</span><span> </span><span>=</span><span> </span><span>T</span><span>)</span><span> </span><span># make this arg TRUE when interactive</span><span>
</span><span># 4. Create a url to make calls to the business search endpoint: The parts of the url include the endpoint and the query search parameters after the **?**</span><span>
</span><span>(</span><span>url</span><span> </span><span>&lt;-</span><span>
</span><span>modify_url</span><span>(</span><span>&quot;https://api.yelp.com&quot;</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;v3&quot;</span><span>,</span><span> </span><span>&quot;businesses&quot;</span><span>,</span><span> </span><span>&quot;search&quot;</span><span>),</span><span>
</span><span>query</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>term</span><span> </span><span>=</span><span> </span><span>&quot;McDonalds&quot;</span><span>,</span><span>
</span><span>location</span><span> </span><span>=</span><span> </span><span>&quot;Hartford, CT&quot;</span><span>,</span><span> </span><span>limit</span><span> </span><span>=</span><span> </span><span>10</span><span>)))</span><span>
</span><span># 5. Retrieve info from the server with the `GET` verb: HTTP response verbs enable the client to send us back data on: status, headers, and body/content. Available verbs include **`GET`ting** data from the server, **`POST`ing** new data to the server, **`PUT`** new data to update a partial record and **`DELETE`ing** data.</span><span>
</span><span>response1</span><span> </span><span>&lt;-</span><span> </span><span>GET</span><span>(</span><span>url</span><span>,</span><span> </span><span>config</span><span>(</span><span>token</span><span> </span><span>=</span><span> </span><span>token</span><span>))</span><span>
</span><span># was this api request successful?</span><span>
</span><span>## HTTP status codes consist of 3 digit numeric codes for status (1xx is information, 2xx is success, 3xx is redirection, 4xx is client error, 5xx server error).</span><span>
</span><span>http_status</span><span>(</span><span>response1</span><span>)</span><span>
</span><span># what type of format does the data come back with?</span><span>
</span><span>response1</span><span>$</span><span>headers</span><span>$</span><span>`content-type`</span><span>
</span><span># 6. Return some content with geolocation data, business info &amp; categories</span><span>
</span><span>ct2</span><span> </span><span>&lt;-</span><span> </span><span>content</span><span>(</span><span>response1</span><span>)</span><span>
</span><span>## create an object with resturant name and id for further calls</span><span>
</span><span>biz_info</span><span> </span><span>&lt;-</span><span> </span><span>ct2</span><span>$</span><span>businesses</span><span> </span><span>%>%</span><span> </span><span>map_df</span><span>(</span><span>`[`</span><span>,</span><span> </span><span>c</span><span>(</span><span>&quot;name&quot;</span><span>,</span><span> </span><span>&quot;id&quot;</span><span>,</span><span> </span><span>&quot;phone&quot;</span><span>,</span><span> </span><span>&quot;review_count&quot;</span><span>))</span><span> </span><span>biz_info</span><span> </span><span>%>%</span><span> </span><span>knitr</span><span>::</span><span>kable</span><span>()</span><span>
</span><span># 7. Get business reviews: After getting a specific McDonald's `id` restructure the url as an individual value and secondly creating a function to create a data.frame with urls for each business from the search endpoint.</span><span>
</span><span>url_id</span><span> </span><span>&lt;-</span><span> </span><span>modify_url</span><span>(</span><span>&quot;https://api.yelp.com&quot;</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;v3&quot;</span><span>,</span><span> </span><span>&quot;businesses&quot;</span><span>,</span><span>&quot;mcdonalds-glastonbury&quot;</span><span>,</span><span> </span><span>&quot;reviews&quot;</span><span>),</span><span>
</span><span>query</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span> </span><span>locale</span><span> </span><span>=</span><span> </span><span>&quot;en_US&quot;</span><span>))</span><span>
</span><span># 8. Retrieve response data on up to 3 reviews for the specific McDonald's</span><span>
</span><span>response2</span><span> </span><span>&lt;-</span><span> </span><span>GET</span><span>(</span><span>url_id</span><span>,</span><span> </span><span>config</span><span>(</span><span>token</span><span> </span><span>=</span><span> </span><span>token</span><span>))</span><span>
</span><span>content2</span><span> </span><span>&lt;-</span><span> </span><span>content</span><span>(</span><span>response2</span><span>)</span><span>
</span><span># Detect for string of 'mustard'</span><span>
</span><span>content2</span><span>$</span><span>reviews</span><span> </span><span>%>%</span><span> </span><span>map_df</span><span>(</span><span>`[`</span><span>,</span><span> </span><span>c</span><span>(</span><span>&quot;text&quot;</span><span>))</span><span> </span><span>%>%</span><span> </span><span>str_detect</span><span>(</span><span>&quot;mustard&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<p>The <code>purrr</code> version to check multiple restaurant text reviews for the string ‘mustard’.</p>
<div>
<div>
<pre><code><span># create a function to structure the urls with the business id</span><span>
</span><span>url_id_f</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>id</span><span>)</span><span> </span><span>{</span><span>
</span><span>modify_url</span><span>(</span><span>&quot;https://api.yelp.com&quot;</span><span>,</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;v3&quot;</span><span>,</span><span> </span><span>&quot;businesses&quot;</span><span>,</span><span> </span><span>id</span><span>,</span><span> </span><span>&quot;reviews&quot;</span><span>),</span><span>
</span><span>query</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span> </span><span>locale</span><span> </span><span>=</span><span> </span><span>&quot;en_US&quot;</span><span>))</span><span>
</span><span>}</span><span>
</span><span># create a df which maps the url function of all the restaurants</span><span>
</span><span>biz_reviews</span><span> </span><span>&lt;-</span><span> </span><span>data.frame</span><span>()</span><span>
</span><span>biz_reviews</span><span> </span><span>&lt;-</span><span> </span><span>map_chr</span><span>(</span><span>biz_info</span><span>$</span><span>id</span><span>,</span><span> </span><span>url_id_f</span><span>)</span><span> </span><span>%>%</span><span> </span><span>data.frame</span><span>(</span><span>url</span><span> </span><span>=</span><span> </span><span>.</span><span>)</span><span>
</span><span>biz_reviews</span><span>$</span><span>url</span><span> </span><span>&lt;-</span><span> </span><span>as.character</span><span>(</span><span>biz_reviews</span><span>$</span><span>url</span><span>)</span><span>
</span><span># Get each url for the request</span><span>
</span><span>response3</span><span> </span><span>&lt;-</span><span> </span><span>map</span><span>(</span><span>biz_reviews</span><span>$</span><span>url</span><span>,</span><span> </span><span>GET</span><span>,</span><span> </span><span>config</span><span>(</span><span>token</span><span> </span><span>=</span><span> </span><span>token</span><span>))</span><span>
</span><span>response3</span><span> </span><span>%>%</span><span> </span><span>map_df</span><span>(</span><span>`[`</span><span>,</span><span> </span><span>&quot;status_code&quot;</span><span>)</span><span> </span><span>==</span><span> </span><span>200</span><span>
</span><span># loop through each restaurant's 3 reviews and extract the text and detect the presence of the string 'mustard'</span><span>
</span><span>for</span><span> </span><span>(</span><span>idx</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>length</span><span>(</span><span>response3</span><span>))</span><span> </span><span>{</span><span>
</span><span>mcd</span><span> </span><span>&lt;-</span><span> </span><span>response3</span><span>[[</span><span>idx</span><span>]]</span><span>
</span><span>ct</span><span> </span><span>&lt;-</span><span> </span><span>content</span><span>(</span><span>mcd</span><span>)</span><span>
</span><span>print</span><span>(</span><span>ct</span><span>)</span><span>
</span><span>result</span><span> </span><span>&lt;-</span><span> </span><span>ct</span><span>$</span><span>reviews</span><span> </span><span>%>%</span><span> </span><span>map_df</span><span>(</span><span>`[`</span><span>,</span><span> </span><span>c</span><span>(</span><span>&quot;text&quot;</span><span>))</span><span> </span><span>%>%</span><span> </span><span>str_detect</span><span>(</span><span>&quot;mustard&quot;</span><span>)</span><span>
</span><span>print</span><span>(</span><span>result</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
</div>
<h2>Learnings &amp; Gotchas</h2>
<p>The non-premium API access only includes up to 3 reviews and only a sample of the full text, leaving obvious gaps when trying to detect the keyword ‘mustard’ and contingent on enough reviews which details <img alt="🍔" src="https://s.w.org/images/core/emoji/2.3/72x72/1f354.png" class="wp-smiley"> preparation.</p>
<p>In trying to create and publish a <code>shiny</code> application that wraps this code, I came up with errors given that OAuth2.0 grants access to users <img alt="👩" src="https://s.w.org/images/core/emoji/2.3/72x72/1f469.png" class="wp-smiley"> and not applications <img alt="💻" src="https://s.w.org/images/core/emoji/2.3/72x72/1f4bb.png" class="wp-smiley">. However here is a screenshot of the script above developed into an interactive <code>shiny</code> application to search for any [city, state] and the <a rel="nofollow" href="https://gist.github.com/jasdumas/2c756e781a101d727eb7c881d38e0ad8" target="_blank">gist of the code</a> if your interested in running a local version.</p>
<p><img alt="" src="https://i0.wp.com/jasdumas.github.io/post_data/not_hotdog.jpeg?w=456" data-recalc-dims="1"></p>
<p>The name of this <code>shiny</code> app is a nod to Silicon Valley’s <a rel="nofollow" href="https://www.theverge.com/2017/6/26/15876006/hot-dog-app-android-silicon-valley" target="_blank">Not Hotdog</a> application.</p>
<hr>
<p>Image source: https://www.mcdonalds.com/us/en-us/about-us.html</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://jasdumas.github.io/2017-10-26-not-mustard-web-app/"> Jasmine Dumas' R Blog</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/ZWWZfAq0cv0" height="1"></a></div>