R ggmap - How to Visualize Spatial Data in R

Estimated time:

<strong>Spatial data</strong> is always tougher to <strong>visualize</strong> than it seems at first. Well, not anymore. <strong>R ggmap</strong> is an amazing package you can start using almost instantly, after some light configuration. It won't take you more than a couple of minutes to configure everything and have your first map ready. Today you'll learn how to use the <code>ggmap</code> package to do almost everything <strong>geodata-related</strong>. We'll kick things off by <strong>plotting</strong> basic maps, markers, and paths, and then dive into changing map themes. Once that's under our belt, we'll focus on advanced topics, including<strong> geocoding</strong>, <strong>reverse geocoding</strong>, <strong>drawing routes</strong>, and <strong>calculating distance</strong> between locations. <blockquote>Want to build interactive Google Maps? <a href="https://appsilon.com/interactive-google-maps-with-r-shiny/" target="_blank" rel="noopener">Here's a complete guide for interactive Google Maps in Shiny</a>.</blockquote> Table of contents: <ul><li><a href="#introduction">Introduction to R ggmap Package</a></li><li><a href="#points-and-paths">Plot Points and Paths with R ggmap</a></li><li><a href="#map-type">How to Change the Map Type</a></li><li><a href="#advanced-1">Advanced #1 - Geocoding and Reverse Geocoding with ggmap</a></li><li><a href="#advanced-2">Advanced #2 - Drawing Routes with ggmap</a></li><li><a href="#advanced-3">Advanced #3 - Calculating Distances Between Locations</a></li><li><a href="#summary">Summary of R ggmap</a></li></ul> <hr /> <h2 id="introduction">Introduction to R ggmap Package</h2> First things first, there's a bit of setup we have to go over. <code>ggmap</code> uses Google Maps behind the scenes, so you'll need an active <a href="https://cloud.google.com/" target="_blank" rel="nofollow noopener">Google Cloud Platform</a> account. You'll also have to set up billing, as it's required for their mapping APIs. Don't worry, GCP won't charge you a penny without your knowledge. Is the account ready? Great, now enable the following APIs under <i>APIs &amp; Services - Library</i>: <ul><li>Maps JavaScript API</li><li>Maps Static API</li><li>Geocoding API</li></ul> These are required to establish a connection between R and Google Maps. The final step is to create a new API key. Go under <i>Credentials</i> and click on <i>+ Create credentials</i> to get a new API key. Ours looks like this: <img class="size-full wp-image-14456" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d302384a76e5dec87de4_5be573b7_1-2.webp" alt="Image 1 - Google Cloud Platform Maps API key" width="1814" height="270" /> Image 1 - Google Cloud Platform Maps API key That's all you need from GCP. Now head over to RStudio and install <code>ggmap</code> with the following command: <pre><code class="language-r">install.packages("ggmap")</code></pre> The last step in the configuration process is to connect R and Google Maps. That's done with the API key you've just created. Make sure to specify <code>write = TRUE</code> so you don't have to call this function ever again: <pre><code class="language-r">ggmap::register_google(key = "&lt;your-api-key&gt;", write = TRUE)</code></pre> <img class="size-full wp-image-14458" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d302842ddef80cb6bc3a_0e65e769_2-2.webp" alt="Image 2 - Registering R ggmap with GCP" width="1402" height="82" /> Image 2 - Registering R ggmap with GCP That's it! Let's verify the configuration succeeded. The following code snippet uses the <code>get_googlemap()</code> function to draw a map at a specific location. No latitude/longitude pairs are required (but you can use them), just specify the location string: <pre><code class="language-r">library(ggmap) <br>get_googlemap(center = "New York") %&gt;% ggmap()</code></pre> The map looks familiar, at least if you've used Google Maps in the past: <img class="size-full wp-image-14460" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d30498512f0e5202df9d_03efc7f3_3-1.webp" alt="Image 3 - Basic ggmap map of New York City" width="1670" height="1622" /> Image 3 - Basic ggmap map of New York City To get a satellite view instead, add an additional <code>maptype</code> argument and set it to <code>satellite</code>: <pre><code class="language-r">get_googlemap("New York", zoom = 12, maptype = "satellite") %&gt;% ggmap()</code></pre> <img class="size-full wp-image-14462" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d304a6541c6fef53275a_1645a2ce_4-2.webp" alt="Image 4 - Satellite map of New York City" width="1526" height="1472" /> Image 4 - Satellite map of New York City There's also a <code>hybrid</code> option available, which will show a satellite view with roads, labels, and points of interest. You have to admit - drawing a basic map was pretty easy. Let's complicate things slightly next. <h2 id="points-and-paths">Plot Points and Paths with R ggmap</h2> Most of the time, you want to display markers or paths on your spatial visualizations. Maybe you want to map out school locations in a specific city or draw a line from one point to the other. Whatever the case might be, this section has you covered. <blockquote>Working with GPX files? <a href="https://appsilon.com/r-gpx-files/" target="_blank" rel="noopener">Learn how to read and visualize GPX files in R.</a></blockquote> To avoid downloading any datasets, we'll create a <code>data.frame</code> of 50 points scattered around (-74, 40.74) geolocation, which should be right around NYC. That's done by combining <code>jitter()</code> and <code>rep()</code> functions: <pre><code class="language-r">set.seed(42) <br>point_df &lt;- round(data.frame(  x = jitter(rep(-74, 50), amount = 0.05),  y = jitter(rep(40.74, 50), amount = 0.05) ), digits = 2) head(point_df)</code></pre> Here's what the dataset looks like: <img class="size-full wp-image-14464" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d305c51a64697dafc1dd_00b82bc4_5-2.webp" alt="Image 5 - Creating a data.frame of random data points" width="286" height="300" /> Image 5 - Creating a data.frame of random data points Those are the coordinates at which we'll draw markers first. To do so, simply add another argument in a call to <code>get_googlemap()</code> - <code>markers</code>, and pass the dataset as a value. It will automatically infer what's what, so you don't have to lift a finger: <pre><code class="language-r">get_googlemap(center = "New York", zoom = 12, markers = point_df, scale = 2) %&gt;% ggmap()</code></pre> <img class="size-full wp-image-14466" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d30675b180b12ad3cc41_d63f372b_6-2.webp" alt="Image 6 - Random data points as markers on the map" width="1742" height="1686" /> Image 6 - Random data points as markers on the map The story is similar if you want to draw lines (path). For simplicity's sake, let's connect all the points instead of showing markers. Swap the <code>markers</code> attribute for <code>path</code>: <pre><code class="language-r">get_googlemap(center = "New York", zoom = 12, path = point_df, scale = 2) %&gt;% ggmap()</code></pre> <img class="size-full wp-image-14468" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d307fb3d70e0efa0002e_1fb8e972_7-1.webp" alt="Image 7 - Random data points as a path on the map" width="1584" height="1530" /> Image 7 - Random data points as a path on the map The resulting map is messy, but you get the point. You can also use both <code>markers</code> and <code>path</code> in a single function call if you want to display both markers and lines. With the basics out of the way, let's see how we can spice the looks of the map. <h2 id="map-type">How to Change the Map Type</h2> The default map options (terrain, satellite, hybrid) aren't the best fit for every use case. R and <code>ggmap</code> allow you to use several options for free. These are: <ul><li><code>stamen.toner</code></li><li><code>stamen.watercolor</code></li><li><code>stamen.terrain-background</code></li><li><code>stamen.toner-lite</code></li></ul> We'll show you what the first two look like. You have to use a different function this time - <code>qmap()</code> - it serves as a wrapper for <code>ggmap</code> and <code>get_map</code>. Two new parameters are needed, <code>source</code> and <code>maptype</code>. These represent the values shown in the above list. Here's an example of a map that uses <code>stamen.toner</code> map type: <pre><code class="language-r">qmap("New York", zoom = 12, scale = 2, source = "stamen", maptype = "toner")</code></pre> <img class="size-full wp-image-14470" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d308565df43d4869491f_663774bf_8-1.webp" alt="Image 8 - Stamen Toner map type" width="1424" height="1396" /> Image 8 - Stamen Toner map type It's a neat black-and-white theme that definitely has its place on some reports and dashboards. If you're more interested in colorful options, look no further than <code>stamen.watercolor</code>: <pre><code class="language-r">qmap("New York", zoom = 12, scale = 2, source = "stamen", maptype = "watercolor")</code></pre> <img class="size-full wp-image-14472" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d3090e70c8a308d384ea_7b302365_9.webp" alt="Image 9 - Stamen Watercolor map type" width="1290" height="1270" /> Image 9 - Stamen Watercolor map type This one's best used when there's a lot of water on a map because it colors it with a beautiful shade of blue. As for the other two options - feel free to explore them on your own. <h2 id="advanced-1">Advanced #1 - Geocoding and Reverse Geocoding with ggmap</h2> Let's dive into more advanced use cases of the R ggmap package. The first one isn't at all tied to data visualization, but can come in handy in the right circumstances. We'll show you how you can use <code>ggmap</code> for <b>geocoding</b> and <code>reverse geocoding</code> operations. Put simply, geocoding returns geolocation (latitude and longitude) when given an address. Reverse geocoding goes from geolocation to an address. In R, it boils down to a single function call: <ul><li><code>ggmap::geocode()</code> will convert an address into a latitude and longitude pair.</li><li><code>ggmap::revgeocode()</code> will convert a vector of latitude and longitude values into one or multiple addresses, depending on how many decimal places you specify.</li></ul> Let's take a look at a geocoding example first: <pre><code class="language-r">geocode("20 W 34th St., New York")</code></pre> <img class="size-full wp-image-14474" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d30bff233005820f57d8_be2d807a_10.webp" alt="Image 10 - Geocoding - from address to latitude and longitude" width="644" height="240" /> Image 10 - Geocoding - from address to latitude and longitude Both latitude and longitude are returned but aren't precise. These coordinates point to NYC, but without more decimal places you won't be able to pinpoint the address. As for reverse geocoding, <code>ggmap</code> tends to return multiple values when many objects of interest are nearby: <pre><code class="language-r">revgeocode(c(lon = -73.985428, lat = 40.748817))</code></pre> <img class="size-full wp-image-14476" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d30b5b4ea85830a3175a_616f9d03_11.webp" alt="Image 11 - Reverse geocoding - from latitude and longitude to address" width="820" height="680" /> Image 11 - Reverse geocoding - from latitude and longitude to address The address of the Empire State Building should have been returned if you're wondering. <h2 id="advanced-2">Advanced #2 - Drawing Routes with ggmap</h2> The second advanced <code>ggmap</code> use case has to do with drawing routes. What this package does for you is amazing - you can specify starting and ending points as strings, and use the <code>trek()</code> function to construct a route data frame. It will contain data points that when plotted will show an optimal driving route from one place to the other. To start, we'll create a route from Miami, FL to Austin, TX: <pre><code class="language-r">trek_df &lt;- trek("miami, florida", "austin, texas", structure = "route") head(trek_df)</code></pre> Here's what it looks like: <img class="size-full wp-image-14478" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b7d30cbfa3743c384a0647_5b9443d9_12.webp" alt="Image 12 - Creating a route dataset" width="374" height="378" /> Image 12 - Creating a route dataset To draw a route, we'll use the <code>geom_path()</code> function that acts just like any familiar method from <code>2</code> package. After all, <code>ggmap</code> was built on top of that package. Here's the entire code: <pre><code class="language-r">qmap(zoom = 4) +  geom_path(    aes(x = lon, y = lat), color = "blue", size = 1, data = trek_df  )</code></pre> <img class="size-full wp-image-14480" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b2ac124650ea006d9569a3_13.webp" alt="Image 13 - Plotting a route with ggmap" width="1670" height="1638" /> Image 13 - Plotting a route with ggmap And there you have it - routing doesn't get much easier. <h2 id="advanced-3">Advanced #3 - Calculating Distances Between Locations</h2> For the final advanced use case, we'll take a look at distance calculation. The <code>ggmap</code> package has a <code>mapdist()</code> function which accepts at least two parameters: <ul><li><code>from</code> - a vector of strings, where each string represents a location (e.g., "miami, florida").</li><li><code>to</code>- a string that represents the destination (same format as above).</li></ul> We'll use this function to calculate distances from three locations to Austin, TX: <pre><code class="language-r">mapdist(c("miami, florida", "los angeles, california", "boulder, colorado"), "austin, texas")</code></pre> The function returns a data frame that looks as follows: <img class="size-full wp-image-14482" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b2ac12b3557a66d6747196_14.webp" alt="Image 14 - Calculating distances between locations with ggmap" width="1434" height="232" /> Image 14 - Calculating distances between locations with ggmap You get absolutely everything you could ask for and more with this function - from meters, kilometers, and miles, to even estimated time of driving. <blockquote>Starting to get a feel for R? Be sure you know these<a href="https://appsilon.com/r-for-programmers/" target="_blank" rel="noopener"> 7 essential R packages</a>.</blockquote> We've explored a lot of functionalities <code>ggmap</code> has to offer, so let's make a short recap next. <hr /> <h2 id="summary">Summary of R ggmap</h2> In short, <code>ggmap</code> can easily become a central place for anything mapping related in R. It has everything you could ask for and more - from visualization options to geocoding, reverse geocoding, routing, and distance calculation. The only gotcha is that you need an active GCP account with billing enabled. You won't get charged to a certain point, but Google APIs are nowhere near free for heavy usage. For personal projects, you should be able to manage in the free tier. <blockquote>Ready to take your remote sensing game to the next level? <a href="https://appsilon.com/using-ai-to-detect-solar-panels-part-1/" target="_blank" rel="noopener">Build your own solar panel detection app using AI and streamlit</a>.</blockquote> What's your favorite <code>ggmap</code> feature that we haven't covered? Is it your default mapping package, or have you opted for something else? Please let us know in the comment section below. <blockquote>Want to visualize spatial data without a GCP account? <a href="https://appsilon.com/leaflet-geomaps/" target="_blank" rel="noopener">Try Leaflet with our complete guide</a>.</blockquote>

Contact us!
Damian's Avatar
Iwona Matyjaszek
Head of Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Have questions or insights?
Engage with experts, share ideas and take your data journey to the next level!
Join Slack

Sign up for ShinyWeekly

Join 4,2k explorers and get the Shiny Weekly Newsletter into your mailbox
for the latest in R/Shiny and Data Science.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Explore Possibilities

Take Your Business Further with Custom Data Solutions

Unlock the full potential of your enterprise with our data services, tailored to the unique needs of Fortune 500 companies. Elevate your strategy -connect with us today!

Talk to our Experts