<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/moving-parts-of-a-country-over-a-map/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://rmhogervorst.nl/cleancode/blog/2018/01/29/moving-parts-of-a-map-in-a-gif.html"> Clean Code</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>I love making maps, I also love making gifs.<br>
In this short post I make an animated gif of parts of a map moving. In this case the parts of the map only move in the xy direction, but <a rel="nofollow" href="https://r-spatial.github.io/sf/articles/sf3.html#affine-transformations" target="_blank">you can also turn them, and make them bigger or smaller</a>.<br>
Today I show you how I made a part of the Netherlands ‘float away’. It is part of a larger nonsense project (I have many silly projects), and mostly just to document my path to learning about spatial analytics.</p>
<p>End result :</p>
<p><img alt=" " src="https://i2.wp.com/cdn.rawgit.com/RMHogervorst/floating_friesland/44f7adfd/friesland.gif?w=456&ssl=1" data-recalc-dims="1"></p>
<h2>General principles</h2>
<ul>
<li>make small functions that do one thing well (not that small in this case)</li>
<li>combine those</li>
<li>make imagemagick canvas</li>
<li>write to the canvas</li>
<li>animate the canvas</li>
</ul>
<h3>loading libraries and data</h3>
<div>
<div>
<pre><code><span>suppressMessages</span><span>(</span><span>library</span><span>(</span><span>tidyverse</span><span>))</span><span> </span><span># ggplot2, dplyr, purrr, etc.</span><span>
</span><span>library</span><span>(</span><span>magick</span><span>)</span><span>
</span><span>library</span><span>(</span><span>sf</span><span>)</span><span>
</span><span>library</span><span>(</span><span>paletti</span><span>)</span><span> </span><span># thanks @edwinthoen</span><span>
</span><span># colorscheme</span><span>
</span><span>dutchmasters_fill</span><span> </span><span>&lt;-</span><span> </span><span>get_scale_fill</span><span>(</span><span>get_pal</span><span>(</span><span>dutchmasters</span><span>))</span><span>
</span><span># the data</span><span>
</span><span>NLD</span><span> </span><span>&lt;-</span><span> </span><span>read_sf</span><span>(</span><span>&quot;data/NLD_adm1.shp&quot;</span><span>)</span><span> </span><span># I cannot redistribute the data from GADM, but you can download and use it for your projects</span><span>
</span></code></pre>
</div>
</div>
<h3>basic functions</h3>
<p>I created a function that takes a name, uses that to filter the data and apply a transformation on that part only. (a mutate_if() could also work, but I didn’t know how). And also one that uses that function to plot. The final function takes a matrix of xy values and sequentially applies every row to the plotting function.</p>
<ul>
<li>modify data</li>
<li>plot a single ggplot version</li>
<li>loop or apply over range</li>
</ul>
<div>
<div>
<pre><code><span># basic function that moves an a province</span><span>
</span><span>move_province</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>provincename</span><span>,</span><span> </span><span>movement</span><span>){</span><span>
</span><span>mov</span><span> </span><span>&lt;-</span><span> </span><span>quo</span><span>(</span><span>movement</span><span>)</span><span>
</span><span>rest</span><span> </span><span>&lt;-</span><span> </span><span>NLD</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>NAME_1</span><span> </span><span>!=</span><span> </span><span>!!</span><span>provincename</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>TYPE_1</span><span> </span><span>!=</span><span> </span><span>&quot;Water body&quot;</span><span>)</span><span>
</span><span>#rest %>% st_centroid() %>% st_as_text()</span><span>
</span><span>province</span><span> </span><span>&lt;-</span><span> </span><span>NLD</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>NAME_1</span><span> </span><span>==</span><span> </span><span>!!</span><span>provincename</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>geometry</span><span> </span><span>=</span><span> </span><span>geometry</span><span> </span><span>+</span><span> </span><span>!!</span><span>mov</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>st_set_crs</span><span>(</span><span>&quot;+proj=longlat +datum=WGS84 +no_defs&quot;</span><span>)</span><span>
</span><span>data1</span><span> </span><span>&lt;-</span><span>
</span><span>rbind</span><span>(</span><span>province</span><span>,</span><span> </span><span>rest</span><span>)</span><span>
</span><span>centroids</span><span> </span><span>&lt;-</span><span>
</span><span>data1</span><span> </span><span>%>%</span><span> </span><span>st_centroid</span><span>()</span><span> </span><span>%>%</span><span> </span><span>st_coordinates</span><span>()</span><span>
</span><span>cbind</span><span>(</span><span>data1</span><span>,</span><span> </span><span>centroids</span><span>)</span><span>
</span><span>}</span><span>
</span><span># make function to create plot</span><span>
</span><span># using the previous function to move the province</span><span>
</span><span>plot_netherlands</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>province</span><span>,</span><span> </span><span>movement</span><span>){</span><span>
</span><span>plotunit</span><span> </span><span>&lt;-</span><span> </span><span>move_province</span><span>(</span><span>provincename</span><span> </span><span>=</span><span> </span><span>province</span><span>,</span><span> </span><span>movement</span><span> </span><span>=</span><span> </span><span>movement</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>ggplot</span><span>()</span><span>+</span><span>
</span><span>geom_sf</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span> </span><span>=</span><span> </span><span>NAME_1</span><span>),</span><span>color</span><span> </span><span>=</span><span> </span><span>&quot;grey50&quot;</span><span>,</span><span> </span><span>alpha</span><span> </span><span>=</span><span> </span><span>3</span><span>/</span><span>4</span><span>)</span><span>+</span><span>
</span><span>geom_text</span><span>(</span><span>aes</span><span>(</span><span>X</span><span>,</span><span>Y</span><span>,</span><span> </span><span>label</span><span> </span><span>=</span><span> </span><span>NAME_1</span><span>),</span><span> </span><span>size</span><span> </span><span>=</span><span> </span><span>6</span><span>)</span><span>+</span><span>
</span><span>lims</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>3.2</span><span>,</span><span>7.1</span><span>),</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>50.8</span><span>,</span><span>55</span><span>))</span><span>+</span><span>
</span><span>labs</span><span>(</span><span>x</span><span>=</span><span>&quot;&quot;</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>&quot;&quot;</span><span>,</span><span> </span><span>caption</span><span> </span><span>=</span><span> </span><span>&quot;shapefiles from www.gadm.org&quot;</span><span>,</span><span> </span><span>title</span><span> </span><span>=</span><span> </span><span>&quot;Floating Friesland&quot;</span><span>)</span><span>+</span><span>
</span><span>dutchmasters_fill</span><span>(</span><span>&quot;little_street&quot;</span><span>)</span><span>+</span><span>
</span><span>theme</span><span>(</span><span> </span><span>legend.position</span><span> </span><span>=</span><span> </span><span>&quot;empty&quot;</span><span>,</span><span> </span><span># we already labeled the provinces</span><span>
</span><span>panel.grid.major</span><span> </span><span>=</span><span> </span><span>element_line</span><span>(</span><span>colour</span><span> </span><span>=</span><span> </span><span>&quot;grey80&quot;</span><span>))</span><span>
</span><span>print</span><span>(</span><span>plotunit</span><span>)</span><span> </span><span># you have to explicitly tell it to print so the image is captured</span><span>
</span><span>}</span><span>
</span><span># go over every frame and print</span><span>
</span><span>plot_province_over_range</span><span> </span><span>&lt;-</span><span>
</span><span>function</span><span>(</span><span>offset_matrix</span><span>,</span><span> </span><span>province</span><span> </span><span>=</span><span> </span><span>&quot;Friesland&quot;</span><span>,</span><span> </span><span>debug</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>){</span><span>
</span><span>if</span><span>(</span><span>any</span><span>(</span><span>is.na</span><span>(</span><span>offset_matrix</span><span>))){</span><span>stop</span><span>(</span><span>&quot;I cannot handle empty movements, there are NA's in movement_matrix&quot;</span><span>)}</span><span>
</span><span>if</span><span>(</span><span>NCOL</span><span>(</span><span>offset_matrix</span><span>)</span><span> </span><span>!=</span><span> </span><span>2</span><span>)</span><span> </span><span>stop</span><span>(</span><span>&quot;movement_matrix needs to have exactly 2 columns&quot;</span><span>)</span><span>
</span><span>actionsframe</span><span> </span><span>&lt;-</span><span> </span><span>data_frame</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>offset_matrix</span><span>[,</span><span>1</span><span>],</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>offset_matrix</span><span>[,</span><span>2</span><span>])</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>rownumber</span><span> </span><span>=</span><span> </span><span>row_number</span><span>())</span><span>
</span><span>actionsframe</span><span>$</span><span>name</span><span> </span><span>&lt;-</span><span> </span><span>paste0</span><span>(</span><span>formatC</span><span>(</span><span>actionsframe</span><span>$</span><span>rownumber</span><span>,</span><span> </span><span>flag</span><span> </span><span>=</span><span> </span><span>0</span><span>,</span><span>width</span><span> </span><span>=</span><span> </span><span>4</span><span>))</span><span>
</span><span>pb</span><span> </span><span>&lt;-</span><span> </span><span>progress_estimated</span><span>(</span><span>NROW</span><span>(</span><span>actionsframe</span><span>))</span><span>
</span><span>walk</span><span>(</span><span>actionsframe</span><span>$</span><span>name</span><span>,</span><span> </span><span>~</span><span>{</span><span>
</span><span>pb</span><span>$</span><span>tick</span><span>()</span><span>$</span><span>print</span><span>()</span><span>
</span><span>vars</span><span> </span><span>&lt;-</span><span> </span><span>filter</span><span>(</span><span>actionsframe</span><span>,</span><span> </span><span>name</span><span> </span><span>==</span><span> </span><span>.x</span><span>)</span><span>
</span><span>if</span><span>(</span><span>debug</span><span>){</span><span>
</span><span>message</span><span>(</span><span>&quot;using values from: &quot;</span><span>,</span><span>vars</span><span>)</span><span>
</span><span>}</span><span>
</span><span>plot_netherlands</span><span>(</span><span>province</span><span> </span><span>=</span><span> </span><span>province</span><span>,</span><span>movement</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>vars</span><span>$</span><span>x</span><span>[[</span><span>1</span><span>]],</span><span> </span><span>vars</span><span>$</span><span>y</span><span>[[</span><span>1</span><span>]]))</span><span>
</span><span>})</span><span> </span><span># ends the walk action</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
</div>
<h3>The plotting and saving</h3>
<p>Nothing happened before the next step (except loading data). All the action and calculation happens here.</p>
<div>
<div>
<pre><code><span>## then the creation starts with the movement</span><span>
</span><span>Friesland_moves</span><span> </span><span>&lt;-</span><span> </span><span>rbind</span><span>(</span><span>
</span><span>matrix</span><span>(</span><span>c</span><span>(</span><span>c</span><span>(</span><span>0</span><span>,</span><span>-.1</span><span>,</span><span>-.2</span><span>,</span><span>-.2</span><span>,</span><span>-.3</span><span>),</span><span> </span><span>c</span><span>(</span><span>0</span><span>,</span><span>.03</span><span>,</span><span>.05</span><span>,</span><span>.1</span><span>,</span><span>.15</span><span>))</span><span> </span><span>,</span><span>ncol</span><span> </span><span>=</span><span> </span><span>2</span><span>),</span><span>
</span><span>matrix</span><span>(</span><span>c</span><span>(</span><span>seq</span><span>(</span><span>from</span><span> </span><span>=</span><span> </span><span>-.3</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>-.1</span><span>,</span><span> </span><span>length.out</span><span> </span><span>=</span><span> </span><span>14</span><span>),</span><span>seq</span><span>(</span><span>from</span><span> </span><span>=</span><span> </span><span>.2</span><span>,</span><span> </span><span>by</span><span> </span><span>=</span><span> </span><span>.1</span><span>,</span><span> </span><span>length.out</span><span> </span><span>=</span><span> </span><span>14</span><span>)),</span><span> </span><span>ncol</span><span> </span><span>=</span><span> </span><span>2</span><span>)</span><span>
</span><span>)</span><span>
</span><span># set up print location</span><span>
</span><span>frames</span><span> </span><span>&lt;-</span><span> </span><span>image_graph</span><span>(</span><span>width</span><span> </span><span>=</span><span> </span><span>1500</span><span>,</span><span> </span><span>height</span><span> </span><span>=</span><span> </span><span>2500</span><span>,</span><span> </span><span>res</span><span> </span><span>=</span><span> </span><span>300</span><span>,</span><span> </span><span>pointsize</span><span> </span><span>=</span><span> </span><span>5</span><span>)</span><span>
</span><span>plot_province_over_range</span><span>(</span><span>offset_matrix</span><span> </span><span>=</span><span> </span><span>Friesland_moves</span><span>,</span><span> </span><span>province</span><span> </span><span>=</span><span> </span><span>&quot;Friesland&quot;</span><span>)</span><span>
</span><span># animate</span><span>
</span><span>image_animate</span><span>(</span><span>frames</span><span>,</span><span> </span><span>1</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>image_write</span><span>(</span><span>path</span><span> </span><span>=</span><span> </span><span>&quot;friesland.gif&quot;</span><span>)</span><span>
</span></code></pre>
</div>
</div>
<h3>Notes</h3>
<ul>
<li><a rel="nofollow" href="https://github.com/RMHogervorst/floating_friesland/blob/master/R/directly_to_imagemagick.R" target="_blank">code for gif 2 imagemagick</a></li>
<li><a rel="nofollow" href="https://github.com/RMHogervorst/floating_friesland/" target="_blank">larger githubproject – floating friesland</a></li>
<li><a rel="nofollow" href="https://stackoverflow.com/questions/48344609/pipe-ggplot2-result-into-1-magick-object" target="_blank">stackoverflow answer that helped me make the gif </a></li>
<li><a rel="nofollow" href="https://edwinth.github.io/blog/paletti" target="_blank">palleti package: making your own color pallete</a></li>
</ul>
<p>I tried to edit this post on github on my mobile phone, boy, that does not work at all!</p>
<p><a rel="nofollow" href="http://rmhogervorst.nl/cleancode/blog/2018/01/29/moving-parts-of-a-map-in-a-gif.html" target="_blank">Moving parts of a country over a map</a> was originally published by at <a rel="nofollow" href="http://rmhogervorst.nl/cleancode" target="_blank">Clean Code</a> on January 29, 2018.</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://rmhogervorst.nl/cleancode/blog/2018/01/29/moving-parts-of-a-map-in-a-gif.html"> Clean Code</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/gNhBo-jImQQ" height="1"></a></div>