<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/dreaming-of-a-white-christmas-with-ggmap-in-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.statworx.com/de/blog/dreaming-of-a-white-christmas-with-ggmap-in-r/"> r-bloggers – STATWORX</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>With the holidays approaching, one of the most discussed questions at <a rel="nofollow" href="https://www.statworx.com/de/" target="_blank">STATWORX</a> was whether we’ll have a white Christmas or not. And what better way to get our hopes up, than by taking a look at the <a rel="nofollow" href="https://www.dwd.de/DE/klimaumwelt/cdc/cdc_node.html" target="_blank">DWD Climate Data Center’s</a> historic data on the snow depth on the past ten Christmas Eves?</p>
<p>But how to best visualize spatial data? Other than most data types, spatial data usually calls for a very particular visualization, namely data points overlaying a map. In this way, areal data is automatically contextualized by the geographic information intuitively conveyed by a map.</p>
<p>The basic functionality of <code>ggplot2</code> dosen’t offer the possibility to do so, but there is a package akin to <code>ggplot2</code> that allows to do so: <code>ggmap</code>. <code>ggmap</code> was written by David Kahle and Hadley Wickham and combines the building blocks of <code>ggplot2</code>, the grammar of graphics as well as the static maps of Google Maps, OpenStreetMap, Stamen Maps or CloudMade Maps. And with all that, <code>ggmap</code> allows us to make really fancy visualizations: </p>
<div class="wp-caption"><img alt="Above-average snow depth on Christmas Eve (2008-2017)" src="https://i0.wp.com/www.statworx.com/wp-content/uploads/ggimage.png?w=450&ssl=1" class="wp-image-16643" data-recalc-dims="1">
<p class="wp-caption-text">Above-average snow depth on Christmas Eve (2008-2017)</p>
</div>
<p>The original functionalities of ggmap used to be somewhat more general, broad and “barrier-free”, but since those good old days – aka 2013 – some of the map suppliers changed the terms of use as well as mechanics of their APIs. At the moment, the service of Stamen Maps seems to be the most stable, while also being easily accessible – e.g. without registering for an API that requires one to provide some payment information. Therefore, we’re going to focus on Stamen Maps.</p>
<p> </p>
<h2>First things first: the map</h2>
<p>Conveniently, <code>ggmap</code> employs the same theoretical framework and general syntax as <code>ggplot2</code>. However, <code>ggmap</code> requires one additional step: Before we can start plotting, we have to download a map as backdrop for our visualization. This is done with <code>get_stamenmap()</code>, <code>get_cloudmademap()</code>, <code>get_googlemap()</code> or <code>get_openstreetmap()</code> or the more general <code>get_map()</code>. We’re going to use <code>get_stamenmap()</code>. </p>
<p>To determine the depicted map cutout, the left, bottom, right and top coordinates of a bounding box, have to be supplied to the argument <code>bbox</code>.<br>
Conveniently, there is no need to know the exact latitudes and longitudes of each and every bounding box of interest. The function <code>geocode_OSM()</code> from the package <code>tmaptools</code>, returns whenever possible the coordinates of a search query consisting of an address, zip code and/or name of a city or country. </p>
<pre><code lang="python">library(scales)
library(tidyverse)
library(tmaptools)
library(ggimage)
library(ggmap)

# get the bounding box 
geocode_OSM(&quot;Germany&quot;)$bbox
</code></pre>
<pre><code lang="r">     xmin      ymin      xmax      ymax 
 5.866315 47.270111 15.041932 55.099161
</code></pre>
<p>The zoom level can be set via the zoom argument and can range between 0 (least detailed) and 18 (most detailed, quick disclaimer: this can take a very long time). The zoom level determines the resolution of the image as well as the amount of displayed annotations. </p>
<p>Depending on whether we want to highlight roads, political or administrative boundaries or bodies of water and land different styles of maps excel. The <code>maptype</code> argument allows to choose from different ready-made styles: <code>&quot;terrain&quot;</code>, <code>&quot;terrain-background&quot;</code>, <code>&quot;terrain-labels&quot;</code>, <code>&quot;terrain-lines&quot;</code>, <code>&quot;toner&quot;</code>, <code>&quot;toner-2010&quot;</code>, <code>&quot;toner-2011&quot;</code>, <code>&quot;toner-background&quot;</code>, <code>&quot;toner-hybrid&quot;</code>, <code>&quot;toner-labels&quot;</code>, <code>&quot;toner-lines&quot;</code>, <code>&quot;toner-lite&quot;</code> or <code>&quot;watercolor&quot;</code>. </p>
<p>Some further, very handy arguments of <code>get_stamenmap()</code> are <code>crop</code>, <code>force</code> and <code>color</code>:<br>
As implied by the name, <code>color</code> defines whether a map should be in black-and-white (<code>&quot;bw&quot;</code>) or when possible in color (<code>&quot;color&quot;</code>).</p>
<p>Under the hood <code>get_stamenmap()</code> downloads map tiles, which are joined to the complete map. If the map tiles should be cropped so as to only depict the specified bounding box, the <code>crop</code> argument can be set to <code>TRUE</code>.</p>
<p>Unless the <code>force</code> argument is set to <code>TRUE</code>, even when arguments changing the style of a map have been altered, once a map of a given location has been downloaded it will not be downloaded again. </p>
<p>When we’ve obtained the map of the right location and style, we can store the “map image” in an object or simply pass it along to <code>ggmap()</code> to plot it. <a rel="nofollow" href="https://www.statworx.com/blog/using-themes-in-ggplot2/" target="_blank">The labels, ticks etc. of axes can be controlled as usual</a>.</p>
<pre><code lang="python"># getting map
plot_map_z7 &lt;- get_stamenmap(as.numeric(geocode_OSM(&quot;Germany&quot;)$bbox), 
                          zoom = 7, 
                          force = TRUE, 
                          maptype = &quot;terrain&quot;)

# saving plotted map alone
plot1 &lt;- ggmap(plot_map_z7) +
  theme(axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank())

# getting map
plot_map_z5 &lt;- get_stamenmap(as.numeric(geocode_OSM(&quot;Germany&quot;)$bbox), 
                             zoom = 5, 
                             force = TRUE, 
                             maptype = &quot;terrain&quot;)

# saving plotted map alone
plot2 &lt;- ggmap(plot_map_z5) +
  theme(axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank())

# plotting maps together
plot &lt;- gridExtra::grid.arrange(plot1, plot2, nrow = 1)
</code></pre>
<div class="wp-caption"><img src="https://i1.wp.com/www.statworx.com/wp-content/uploads/zoom.png?w=450&ssl=1" alt="Example for maptype = " class="wp-image-16646" data-recalc-dims="1">
<p class="wp-caption-text">Example for maptype = „terrain“ with zoom = 7 (left) vs. zoom = 5 (right).</p>
</div>
<h2>Business as usual: layering geoms on top</h2>
<p>We then can layer any <code>ggplot2</code> geom we’d like on top of that map, with the only requirement being that the variables mapped to the axes are within the same numeric range as the latitudes and longitudes of the depicted map. We also can use many extension packages building on <code>ggplot2</code>. For example, we can use the very handy package <code>ggimage</code> by Guangchuang Yu to make our plots extra festive:</p>
<pre><code lang="python"># aggregating data per coordinate
df_snow_agg &lt;- df_snow %>%
  dplyr::mutate(LATITUDE = plyr::round_any(LATITUDE, accuracy = 1),
                LONGITUDE = plyr::round_any(LONGITUDE, accuracy = 1)) %>%
  dplyr::group_by(LATITUDE, LONGITUDE) %>%
  dplyr::summarise(WERT = mean(WERT, na.rm = TRUE))

# cutting into equal intervals          
df_snow_agg$snow &lt;- as.numeric(cut(df_snow_agg$WERT, 12))

# setting below average snow depths to 0                   
df_snow_agg &lt;- df_snow_agg %>%
  mutate(snow = ifelse(WERT &lt;= mean(df_snow_agg$WERT), 0, snow)) 

# adding directory of image to use
df_snow_agg$image &lt;- &quot;Snowflake_white.png&quot;

# getting map
plot_map &lt;- get_stamenmap(as.numeric(geocode_OSM(&quot;Germany&quot;)$bbox),
                          zoom = 7,
                          force = TRUE,
                          maptype = &quot;terrain&quot;)

# plotting map + aggregated snow data with ggimage
plot &lt;- ggmap(plot_map) +
  geom_image(data = df_snow_agg, 
             aes(x = LONGITUDE, 
                 y = LATITUDE, 
                 image = image, 
                 size = I(snow/20))) + # rescaling to get valid size values
  theme(axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank())
</code></pre>
<div class="wp-caption"><img alt="Above-average snow depth on Christmas Eve (2008-2017)" src="https://i0.wp.com/www.statworx.com/wp-content/uploads/ggimage.png?w=450&ssl=1" class="wp-image-16643" data-recalc-dims="1">
<p class="wp-caption-text">Above-average snow depth on Christmas Eve (2008-2017)</p>
</div>
<p>We can get creative, playing with all sorts of geoms and map styles. Especially visualization strategies to prevent <a rel="nofollow" href="https://www.statworx.com/blog/how-not-to-overplot/" target="_blank">overplotting</a> can be quite handy:</p>
<p>For example, a facetted scatter plot with alpha blending:</p>
<pre><code lang="python"># getting map
plot_map &lt;- get_stamenmap(as.numeric(geocode_OSM(&quot;Germany&quot;)$bbox),
                          zoom = 7,
                          force = TRUE,
                          maptype = &quot;watercolor&quot;)

# facets per year, scatter plot with alpha blending 
plot &lt;- ggmap(plot_map) +
  geom_point(data = df_snow, 
             aes(x = LONGITUDE,
                 y = LATITUDE,
                 alpha = WERT,
                 size = WERT),
             color = &quot;white&quot;) +
  facet_wrap(. ~ DATE, nrow = 2) +
  scale_alpha_continuous(range = c(0.0, 0.9)) +
  theme(axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank(), 
        legend.position = &quot;none&quot;,
        strip.background = element_rect(fill = &quot;white&quot;))
</code></pre>
<div class="wp-caption"><img alt="Snow depth on Christmas Eve per year (2008-2017)" src="https://i0.wp.com/www.statworx.com/wp-content/uploads/facets.png?w=450&ssl=1" class="wp-image-16640" data-recalc-dims="1">
<p class="wp-caption-text">Snow depth on Christmas Eve per year (2008-2017)</p>
</div>
<p>Or density plots with either <code>geom_line()</code> or <code>geom_polygon()</code>:</p>
<pre><code lang="python"># getting map
plot_map &lt;- get_stamenmap(as.numeric(geocode_OSM(&quot;Germany&quot;)$bbox),
                          zoom = 7,
                          crop = FALSE,
                          force = TRUE,
                          maptype = &quot;toner-background&quot;)
# density plot: lines
plot1 &lt;- ggmap(plot_map) +
  geom_density2d(data = df_snow_dens, 
                 aes(x = LONGITUDE, 
                     y = LATITUDE, 
                     color = ..level..), 
                 size = 0.7) +
  scale_color_continuous(low = &quot;#17775A&quot;, high = &quot;white&quot;,
                         name = &quot;&quot;,
                         breaks = c(0.01, 0.06),
                         labels = c(&quot;little snow&quot;, &quot;much snow&quot;)) +
  theme(axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank(),
        legend.position = &quot;left&quot;) 

# density plot: polygon
plot2 &lt;- ggmap(plot_map) +
  stat_density_2d(data = df_snow_dens, 
                  aes(x = LONGITUDE, y = LATITUDE, 
                      alpha = ..level..), 
                  fill = &quot;#CFECFF&quot;,
                  geom = &quot;polygon&quot;) +
  scale_alpha(name = &quot;&quot;,
              breaks = c(0.012, 0.024, 0.036, 0.048, 0.06),
              labels = c(&quot;little snow&quot;, &quot;&quot;,&quot;&quot;, &quot;&quot;, &quot;much snow&quot;))  +
  theme(axis.title = element_blank(),
        axis.ticks = element_blank(),
        axis.text = element_blank()) 
  
plot &lt;- gridExtra::grid.arrange(plot1, plot2, nrow = 1)


ggsave(plot = plot, filename = &quot;density.png&quot;,  width = 5.5, height = 3)
</code></pre>
<div class="wp-caption"><img alt="Average snow depth on Christmas Eve (2008-2017)" src="https://i2.wp.com/www.statworx.com/wp-content/uploads/density.png?w=450&ssl=1" class="wp-image-16637" data-recalc-dims="1">
<p class="wp-caption-text">Average snow depth on Christmas Eve (2008-2017)</p>
</div>
<p>Our plots give a first taste of what can be done with <code>ggmap.</code> However, based on the historic data, there won’t be a white Christmas for the most of us… Against all odds, I still hope that outside there’s a winter wonderland waiting for you just now.</p>
<p>From everybody here at STATWORX happy holidays and a happy new year!</p>
<h2>References</h2>
<ul>
<li>D. Kahle and H. Wickham. ggmap: Spatial Visualization with ggplot2. The R Journal, 5(1), 144-161. <a rel="nofollow" href="http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf" target="_blank">http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf</a>
</li>
<li>DWD Climate Data Center (CDC): Tägliche Stationsmessungen Schneehöhe in cm für Deutschland, Version v18.3 &amp; recent, abgerufen am 16.12.2018.
</li>
<li>Map tiles by <a rel="nofollow" href="https://stamen.com/" target="_blank">Stamen Design</a>, under <a rel="nofollow" href="https://creativecommons.org/licenses/by/3.0/" target="_blank">CC BY 3.0.</a> Data by <a rel="nofollow" href="https://www.statworx.com/de/blog/dreaming-of-a-white-christmas-with-ggmap-in-r/" target="_blank">OpenStreetMap</a>, under <a rel="nofollow" href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank">CC BY SA</a> respectively under <a rel="nofollow" href="https://www.openstreetmap.org/copyright" target="_blank">ODbL</a>.
</li>
</ul>
<div>
<h6>Über den Autor</h6>
<p><img src="https://i0.wp.com/www.statworx.com/wp-content/uploads/statworx-avatar-female-300x300.png?resize=180%2C180&ssl=1" width="180" alt="Lea Waniek" class="wp-user-avatar wp-user-avatar-180" data-recalc-dims="1" height="180"></p>
<div>
<h4>Lea Waniek</h4>
<p>I am data scientist at <a rel="nofollow" href="https://www.statworx.com/" target="_blank">STATWORX</a>, apart from machine learning, I love to play around with RMarkdown and ggplot2, making data science beautiful inside and out.</p>
</div>
</div>
<div>
<div>
<div>
<div>
<div>
<div>
<div>
<h1>ABOUT US</h1>
</div>
</div>
</div>
<hr>
<div>
<p><span><span>STATWORX</span><br></span><span>is a consulting company for data science, statistics, machine learning and artificial intelligence </span><span>located in Frankfurt, Zurich and Vienna. Sign up for our NEWSLETTER and receive reads and treats from the world of data science and AI.</span> </p>
</div>
<p><a data-x-toggle="1" tabindex="0" data-x-toggleable="e15819-7">
<p> <span>
<p><span>
<p><i data-x-icon-o=""></i></p>
<p> <span><span>Sign Up Now!</span></span> </p></span>
<p>




<p>Der Beitrag <a rel="nofollow" href="https://www.statworx.com/de/blog/dreaming-of-a-white-christmas-with-ggmap-in-r/" target="_blank">Dreaming of a white Christmas – with ggmap in R</a> erschien zuerst auf <a rel="nofollow" href="https://www.statworx.com/de/" target="_blank">STATWORX</a>.</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="https://www.statworx.com/de/blog/dreaming-of-a-white-christmas-with-ggmap-in-r/"> r-bloggers – STATWORX</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/pkmFgXreEn8" height="1"></a></div></span></a></div></div></div></div>