<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/drawing-beautiful-maps-programmatically-with-r-sf-and-ggplot2-part-3-layouts/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.r-spatial.org//r/2018/10/25/ggplot2-sf-3.html"> r-spatial</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><a rel="nofollow" href="https://raw.githubusercontent.com//r-spatial/r-spatial.org/gh-pages/_rmd/2018-10-04-ggplot2-sf-3.Rmd" target="_blank">view raw Rmd</a></p>
<p>This tutorial is the third part in a series of three:</p>
<ul>
<li><a rel="nofollow" href="https://www.r-spatial.org//r/2018/10/25/ggplot2-sf.html" target="_blank">General concepts illustrated with the world map</a></li>
<li><a rel="nofollow" href="https://www.r-spatial.org//r/2018/10/25/ggplot2-sf-2.html" target="_blank">Adding additional layers: an example with points and polygons</a></li>
<li>Positioning and layout for complex maps (this document)</li>
</ul>
<p>After the presentation of the basic map concepts, and the flexible<br>
approach in layer implemented in <code>ggplot2</code>, this part illustrates how to<br>
achieve complex layouts, for instance with map insets, or several maps<br>
combined. Depending on the visual information that needs to be<br>
displayed, maps and their corresponding data might need to be arranged<br>
to create easy to read graphical representations. This tutorial will<br>
provide different approaches to arranges maps in the plot, in order to<br>
make the information portrayed more aesthetically appealing, and most<br>
importantly, convey the information better.</p>
<h2>Getting started</h2>
<p>Many R packages are available from <a rel="nofollow" href="https://cran.r-project.org/" target="_blank">CRAN</a>,<br>
the Comprehensive R Archive Network, which is the primary repository of<br>
R packages. The full list of packages necessary for this series of<br>
tutorials can be installed with:</p>
<div>
<div>
<pre><code>install.packages(c(&quot;cowplot&quot;, &quot;googleway&quot;, &quot;ggplot2&quot;, &quot;ggrepel&quot;, 
    &quot;ggspatial&quot;, &quot;libwgeom&quot;, &quot;sf&quot;, &quot;rworldmap&quot;, &quot;rworldxtra&quot;))
</code></pre>
</div>
</div>
<p>We start by loading the basic packages necessary for all maps, i.e.<br>
<code>ggplot2</code> and <code>sf</code>. We also suggest to use the classic dark-on-light<br>
theme for <code>ggplot2</code> (<code>theme_bw</code>), which is more appropriate for maps:</p>
<div>
<div>
<pre><code>library(&quot;ggplot2&quot;)
theme_set(theme_bw())
library(&quot;sf&quot;)
</code></pre>
</div>
</div>
<p>The package <code>rworldmap</code> provides a map of countries of the entire world;<br>
a map with higher resolution is available in the package <code>rworldxtra</code>.<br>
We use the function <code>getMap</code> to extract the world map (the resolution<br>
can be set to <code>&quot;low&quot;</code>, if preferred):</p>
<div>
<div>
<pre><code>library(&quot;rworldmap&quot;)
library(&quot;rworldxtra&quot;)
world &lt;- getMap(resolution = &quot;high&quot;)
class(world)

## [1] &quot;SpatialPolygonsDataFrame&quot;
## attr(,&quot;package&quot;)
## [1] &quot;sp&quot;
</code></pre>
</div>
</div>
<p>The world map is available as a <code>SpatialPolygonsDataFrame</code> from the<br>
package <code>sp</code>; we thus convert it to a simple feature using <code>st_as_sf</code><br>
from package <code>sf</code>:</p>
<div>
<div>
<pre><code>world &lt;- st_as_sf(world)
class(world)

## [1] &quot;sf&quot;         &quot;data.frame&quot;
</code></pre>
</div>
</div>
<h1>General concepts</h1>
<p>There are 2 solutions to combine sub-maps:</p>
<ul>
<li>using Grobs (graphic objects, allow plots only in plot region, based<br>
on coordinates), which directly use <code>ggplot2</code></li>
<li>using <code>ggdraw</code> (allows plots anywhere, including outer margins,<br>
based on relative position) from package <code>cowplot</code></li>
</ul>
<p>Example illustrating the difference between the two, and their use:</p>
<div>
<div>
<pre><code>(g1  &lt;- qplot(0:10, 0:10))
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-example-qplot-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<div>
<div>
<pre><code>(g1_void &lt;- g1 + theme_void() + theme(panel.border = element_rect(colour = &quot;black&quot;, 
    fill = NA)))
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-example-qplot-void-1.png?w=35%25&ssl=1" data-recalc-dims="1"></p>
<p>Graphs from <code>ggplot2</code> can be saved, like any other R object. They can<br>
then be reused later in other functions.</p>
<p>Using grobs, and <code>annotation_custom</code>:</p>
<div>
<div>
<pre><code>g1 +
    annotation_custom(
        grob = ggplotGrob(g1_void),
        xmin = 0,
        xmax = 3,
        ymin = 5,
        ymax = 10
    ) +
    annotation_custom(
        grob = ggplotGrob(g1_void),
        xmin = 5,
        xmax = 10,
        ymin = 0,
        ymax = 3
    )
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-example-grobs-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<p>Using <code>ggdraw</code> (note: used to build on top of initial plot; could be<br>
left empty to arrange subplots on a grid; plots are “filled” with their<br>
plots, unless the plot itself has a constrained ratio, like a map):</p>
<div>
<div>
<pre><code>ggdraw(g1) +
    draw_plot(g1_void, width = 0.25, height = 0.5, x = 0.02, y = 0.48) +
    draw_plot(g1_void, width = 0.5, height = 0.25, x = 0.75, y = 0.09)
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-example-ggdraw-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<h1>Several maps side by side or on a grid</h1>
<p>Having a way show in a visualization, a specific area can be very<br>
useful. Many scientists usually create maps for each specific area<br>
individually. This is fine, but there are simpler ways to display what<br>
is needed for a report, or publication.</p>
<p>This exmaple is using two maps side by side, including the legend of the<br>
first one. It illustrates how to use a custom grid, which can be made a<br>
lot more complex with different elements.</p>
<p>First, simplify <code>REGION</code> for the legend:</p>
<div>
<div>
<pre><code>levels(world$REGION)[7] &lt;- &quot;South America&quot;
</code></pre>
</div>
</div>
<p>Prepare the subplots, #1 world map:</p>
<div>
<div>
<pre><code>(gworld &lt;- ggplot(data = world) +
     geom_sf(aes(fill = REGION)) +
     geom_rect(xmin = -102.15, xmax = -74.12, ymin = 7.65, ymax = 33.97, 
         fill = NA, colour = &quot;black&quot;, size = 1.5) +
     scale_fill_viridis_d(option = &quot;plasma&quot;) +
     theme(panel.background = element_rect(fill = &quot;azure&quot;),
         panel.border = element_rect(fill = NA)))
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/grid-world-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>And #2 Gulf map :</p>
<div>
<div>
<pre><code>(ggulf &lt;- ggplot(data = world) +
     geom_sf(aes(fill = REGION)) +
     annotate(geom = &quot;text&quot;, x = -90, y = 26, label = &quot;Gulf of Mexico&quot;, 
         fontface = &quot;italic&quot;, color = &quot;grey22&quot;, size = 6) +
     coord_sf(xlim = c(-102.15, -74.12), ylim = c(7.65, 33.97), expand = FALSE) +
     scale_fill_viridis_d(option = &quot;plasma&quot;) +
     theme(legend.position = &quot;none&quot;, axis.title.x = element_blank(), 
         axis.title.y = element_blank(), panel.background = element_rect(fill = &quot;azure&quot;), 
         panel.border = element_rect(fill = NA)))
</code></pre>
</div>
</div>
<p><img src="https://i0.wp.com/www.r-spatial.org/images/figure-markdown_mmd/grid-gulf-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<p>The command <code>ggplotGrob</code> signals to <code>ggplot</code> to take each created map,<br>
and how to arrange each map. The argument <code>coord_equal</code> can specify the<br>
length, <code>ylim</code>, and width, <code>xlim</code>, for the entire plotting area. Where<br>
as in <code>annotation_custom</code>, each maps’ <code>xmin</code>, <code>xmax</code>, <code>ymin</code>, and <code>ymax</code><br>
can be specified to allow for complete customization.</p>
<div>
<div>
<pre><code>#Creating a faux empty data frame
df &lt;- data.frame()
plot1&lt;-ggplot(df) + geom_point() + xlim(0, 10) + ylim(0, 10)
plot2&lt;-ggplot(df) + geom_point() + xlim(0, 10) + ylim(0, 10)


ggplot() +
  coord_equal(xlim = c(0, 3.3), ylim = c(0, 1), expand = FALSE) +
  annotation_custom(ggplotGrob(plot1), xmin = 0, xmax = 1.5, ymin = 0, 
                    ymax = 1) +
  annotation_custom(ggplotGrob(plot2), xmin = 1.5, xmax = 3, ymin = 0, 
                    ymax = 1) +
  theme_void()
</code></pre>
</div>
</div>
<p><img src="https://i0.wp.com/www.r-spatial.org/images/figure-markdown_mmd/empty-grobs-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>Below is the final map, using the same methodology as the exmaple plot<br>
above. Using <code>ggplot</code> to arrange maps, allows for easy and quick<br>
plotting in one function of R code.</p>
<div>
<div>
<pre><code>ggplot() +
    coord_equal(xlim = c(0, 3.3), ylim = c(0, 1), expand = FALSE) +
    annotation_custom(ggplotGrob(gworld), xmin = 0, xmax = 2.3, ymin = 0, 
        ymax = 1) +
    annotation_custom(ggplotGrob(ggulf), xmin = 2.3, xmax = 3.3, ymin = 0, 
        ymax = 1) +
    theme_void()
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/grid-grobs-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>In the second approach, using <code>cowplot::plot_grid</code> to arrange <code>ggplot</code><br>
figures, is quite versatile. Any <code>ggplot</code> figure can be arranged just<br>
like the figure above. There are many commands that allow for the map to<br>
have different placements, such as <code>nrow=1</code> means that the figure will<br>
only occupy one row and multiple columns, and <code>ncol=1</code> means the figure<br>
will be plotted on one column and multiple rows. The command<br>
<code>rel_widths</code> establishes the width of each map, meaning that the first<br>
map <code>gworld</code> will have a relative width of <code>2.3</code>, and the map <code>ggulf</code><br>
has the relative width of <code>1</code>.</p>
<div>
<div>
<pre><code>library(&quot;cowplot&quot;)
theme_set(theme_bw())

plot_grid(gworld, ggulf, nrow = 1, rel_widths = c(2.3, 1))
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/grid-plot-grid-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>Some other commands can adjust the position of the figures such as<br>
adding <code>align=v</code> to align vertically, and <code>align=h</code> to align<br>
horiztonally.</p>
<p>Note also the existence of <code>get_legend</code> (<code>cowplot</code>), and that the legend<br>
can be used as any object.</p>
<p>This map can be save using,<code>ggsave</code>:</p>
<div>
<div>
<pre><code>ggsave(&quot;grid.pdf&quot;, width = 15, height =  5)
</code></pre>
</div>
</div>
<hr>
<h1>Map insets</h1>
<p>For map insets directly on the background map, both solutions are viable<br>
(and one might prefer one or the other depending on relative or absolute<br>
coordinates).</p>
<p>Map example using map of the 50 states of the US, including Alaska and<br>
Hawaii (note: not to scale for the latter), using reference projections<br>
for US maps. First map (continental states) use a 10/6 figure:</p>
<div>
<div>
<pre><code>usa &lt;- subset(world, ADMIN == &quot;United States of America&quot;)
## US National Atlas Equal Area (2163)
## http://spatialreference.org/ref/epsg/us-national-atlas-equal-area/
(mainland &lt;- ggplot(data = usa) +
     geom_sf(fill = &quot;cornsilk&quot;) +
     coord_sf(crs = st_crs(2163), xlim = c(-2500000, 2500000), ylim = c(-2300000, 
         730000)))
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-usa-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>Alaska map (note: <code>datum = NA</code> removes graticules and coordinates):</p>
<div>
<div>
<pre><code>## Alaska: NAD83(NSRS2007) / Alaska Albers (3467)
## http://www.spatialreference.org/ref/epsg/3467/
(alaska &lt;- ggplot(data = usa) +
     geom_sf(fill = &quot;cornsilk&quot;) +
     coord_sf(crs = st_crs(3467), xlim = c(-2400000, 1600000), ylim = c(200000, 
         2500000), expand = FALSE, datum = NA))
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-alaska-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<p>Hawaii map:</p>
<div>
<div>
<pre><code>## Hawaii: Old Hawaiian (4135)
## http://www.spatialreference.org/ref/epsg/4135/
(hawaii  &lt;- ggplot(data = usa) +
     geom_sf(fill = &quot;cornsilk&quot;) +
     coord_sf(crs = st_crs(4135), xlim = c(-161, -154), ylim = c(18, 
         23), expand = FALSE, datum = NA))
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-hawaii-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<p>Using <code>ggdraw</code> from <code>cowplot</code> (tricky to define exact positions; note<br>
the use of the ratios of the inset, combined with the ratio of the<br>
plot):</p>
<div>
<div>
<pre><code>(ratioAlaska &lt;- (2500000 - 200000) / (1600000 - (-2400000)))

## [1] 0.575

(ratioHawaii  &lt;- (23 - 18) / (-154 - (-161)))

## [1] 0.7142857

ggdraw(mainland) +
    draw_plot(alaska, width = 0.26, height = 0.26 * 10/6 * ratioAlaska, 
        x = 0.05, y = 0.05) +
    draw_plot(hawaii, width = 0.15, height = 0.15 * 10/6 * ratioHawaii, 
        x = 0.3, y = 0.05)
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-ggdraw-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>This plot can be saved using <code>ggsave</code>:</p>
<div>
<div>
<pre><code>ggsave(&quot;map-us-ggdraw.pdf&quot;, width = 10, height = 6)
</code></pre>
</div>
</div>
<p>The same kind of plot can be created using grobs, with <code>ggplotGrob</code>,<br>
(note the use of xdiff/ydiff and arbitrary ratios):</p>
<div>
<div>
<pre><code>mainland +
    annotation_custom(
        grob = ggplotGrob(alaska),
        xmin = -2750000,
        xmax = -2750000 + (1600000 - (-2400000))/2.5,
        ymin = -2450000,
        ymax = -2450000 + (2500000 - 200000)/2.5
    ) +
    annotation_custom(
        grob = ggplotGrob(hawaii),
        xmin = -1250000,
        xmax = -1250000 + (-154 - (-161))*120000,
        ymin = -2450000,
        ymax = -2450000 + (23 - 18)*120000
    )
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/inset-grobs-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>This plot can be saved using <code>ggsave</code>:</p>
<div>
<div>
<pre><code>ggsave(&quot;map-inset-grobs.pdf&quot;, width = 10, height = 6)
</code></pre>
</div>
</div>
<hr>
<p>The <code>print</code> command can also be used place multiple maps in one plotting<br>
area.</p>
<p>To specify where each plot is displayed with the <code>print</code> function, the<br>
argument <code>viewport</code> needs to include the maximum width and height of<br>
each map, and the minimum x and y coordinates of where the maps are<br>
located in the plotting area. The argument <code>just</code> will make a position<br>
on how the secondary maps will be displayed. All maps are defaulted the<br>
same size, until the sizes are adjusted with <code>width</code> and <code>height</code>.</p>
<div>
<div>
<pre><code>vp &lt;- viewport(width = 0.37, height = 0.10, x = 0.20, y =0.25, just = c(&quot;bottom&quot;)) 
vp1&lt;- viewport(width = 0.37, height = 0.10, x = 0.35, y =0.25, just = c(&quot;bottom&quot;)) 
</code></pre>
</div>
</div>
<p>The<code>print</code> function uses the previous specifications that were listed in<br>
each plots’ respective <code>viewport</code>, with <code>vp=</code>.</p>
<div>
<div>
<pre><code>print(mainland)
print(alaska, vp=vp)
print(hawaii, vp=vp1)
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/print_finalmap-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<h1>Several maps connected with arrows</h1>
<p>To bring about a more lively map arrangement, arrows can be used to<br>
bring the viewers eyes to specific areas in the plot. The next example<br>
will create a map with zoomed in areas, pointed to by arrows.</p>
<p>Firstly, we will create our main map, and then our zoomed in areas.</p>
<p>Site coordinates, same as Tutorial #1:</p>
<div>
<div>
<pre><code>sites &lt;- st_as_sf(data.frame(longitude = c(-80.15, -80.1), latitude = c(26.5, 
    26.8)), coords = c(&quot;longitude&quot;, &quot;latitude&quot;), crs = 4326, 
    agr = &quot;constant&quot;)
</code></pre>
</div>
</div>
<p>Mainlaind map of Florida, #1:</p>
<div>
<div>
<pre><code>(florida &lt;- ggplot(data = world) +
     geom_sf(fill = &quot;antiquewhite1&quot;) +
     geom_sf(data = sites, size = 4, shape = 23, fill = &quot;darkred&quot;) +
     annotate(geom = &quot;text&quot;, x = -85.5, y = 27.5, label = &quot;Gulf of Mexico&quot;, 
         color = &quot;grey22&quot;, size = 4.5) +
     coord_sf(xlim = c(-87.35, -79.5), ylim = c(24.1, 30.8)) +
     xlab(&quot;Longitude&quot;)+ ylab(&quot;Latitude&quot;)+
     theme(panel.grid.major = element_line(colour = gray(0.5), linetype = &quot;dashed&quot;, 
         size = 0.5), panel.background = element_rect(fill = &quot;aliceblue&quot;), 
         panel.border = element_rect(fill = NA)))
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/map-arrows-florida-1.png?w=65%25&ssl=1" data-recalc-dims="1"></p>
<p>A map for site A is created by layering the map and points we created<br>
earlier. <code>ggplot</code> layers <code>geom_sf</code> objects and plot them spatially.</p>
<div>
<div>
<pre><code>(siteA &lt;- ggplot(data = world) +
     geom_sf(fill = &quot;antiquewhite1&quot;) +
     geom_sf(data = sites, size = 4, shape = 23, fill = &quot;darkred&quot;) +
     coord_sf(xlim = c(-80.25, -79.95), ylim = c(26.65, 26.95), expand = FALSE) + 
     annotate(&quot;text&quot;, x = -80.18, y = 26.92, label= &quot;Site A&quot;, size = 6) + 
     theme_void() + 
     theme(panel.grid.major = element_line(colour = gray(0.5), linetype = &quot;dashed&quot;, 
         size = 0.5), panel.background = element_rect(fill = &quot;aliceblue&quot;), 
         panel.border = element_rect(fill = NA)))
</code></pre>
</div>
</div>
<p><img src="https://i1.wp.com/www.r-spatial.org/images/figure-markdown_mmd/map-arrows-sitea-1.png?w=35%25&ssl=1" data-recalc-dims="1"></p>
<p>A map for site B:</p>
<div>
<div>
<pre><code>(siteB &lt;- ggplot(data = world) + 
     geom_sf(fill = &quot;antiquewhite1&quot;) +
     geom_sf(data = sites, size = 4, shape = 23, fill = &quot;darkred&quot;) +
     coord_sf(xlim = c(-80.3, -80), ylim = c(26.35, 26.65), expand = FALSE) +
     annotate(&quot;text&quot;, x = -80.23, y = 26.62, label= &quot;Site B&quot;, size = 6) + 
     theme_void() +
     theme(panel.grid.major = element_line(colour = gray(0.5), linetype = &quot;dashed&quot;, 
         size = 0.5), panel.background = element_rect(fill = &quot;aliceblue&quot;), 
         panel.border = element_rect(fill = NA)))
</code></pre>
</div>
</div>
<p><img src="https://i0.wp.com/www.r-spatial.org/images/figure-markdown_mmd/map-arrows-siteb-1.png?w=35%25&ssl=1" data-recalc-dims="1"></p>
<p>Coordinates of the two arrows will need to be specified before plotting.<br>
The argumemnts <code>x1</code>, and <code>x2</code> will plot the arrow line from a specific<br>
starting x-axis location,<code>x1</code>, and ending in a specific x-axis,<code>x2</code>. The<br>
same applies for <code>y1</code> and <code>y2</code>, with the y-axis respectively:</p>
<div>
<div>
<pre><code>arrowA &lt;- data.frame(x1 = 18.5, x2 = 23, y1 = 9.5, y2 = 14.5)
arrowB &lt;- data.frame(x1 = 18.5, x2 = 23, y1 = 8.5, y2 = 6.5)
</code></pre>
</div>
</div>
<p>Final map using (<code>ggplot</code> only). The argument <code>geom_segment</code>, will be<br>
the coordinates created in the previous script, to plot line segments<br>
ending with an arrow using <code>arrow=arrow()</code>:</p>
<div>
<div>
<pre><code>ggplot() +
    coord_equal(xlim = c(0, 28), ylim = c(0, 20), expand = FALSE) +
    annotation_custom(ggplotGrob(florida), xmin = 0, xmax = 20, ymin = 0, 
        ymax = 20) +
    annotation_custom(ggplotGrob(siteA), xmin = 20, xmax = 28, ymin = 11.25, 
        ymax = 19) +
    annotation_custom(ggplotGrob(siteB), xmin = 20, xmax = 28, ymin = 2.5, 
        ymax = 10.25) +
    geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2), data = arrowA, 
        arrow = arrow(), lineend = &quot;round&quot;) +
    geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2), data = arrowB, 
        arrow = arrow(), lineend = &quot;round&quot;) +
    theme_void()
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/map-arrows-plot-1.png?w=90%25&ssl=1" data-recalc-dims="1"></p>
<p>This plot can be saved using <code>ggsave</code>:</p>
<div>
<div>
<pre><code>ggsave(&quot;florida-sites.pdf&quot;, width = 10, height = 7)
</code></pre>
</div>
</div>
<p><code>ggdraw</code> could also be used for a similar result, with the argument<br>
<code>draw_plot</code>:</p>
<div>
<div>
<pre><code>ggdraw(xlim = c(0, 28), ylim = c(0, 20)) +
    draw_plot(florida, x = 0, y = 0, width = 20, height = 20) +
    draw_plot(siteA, x = 20, y = 11.25, width = 8, height = 8) +
    draw_plot(siteB, x = 20, y = 2.5, width = 8, height = 8) +
    geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2), data = arrowA, 
        arrow = arrow(), lineend = &quot;round&quot;) +
    geom_segment(aes(x = x1, y = y1, xend = x2, yend = y2), data = arrowB, 
        arrow = arrow(), lineend = &quot;round&quot;)
</code></pre>
</div>
</div>
<p><img src="https://i2.wp.com/www.r-spatial.org/images/figure-markdown_mmd/map-arrows-ggdraw-1.png?w=90%25&ssl=1" data-recalc-dims="1"></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.r-spatial.org//r/2018/10/25/ggplot2-sf-3.html"> r-spatial</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/cdYtLMaD9Aw" height="1"></a></div>