<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/how-to-draw-connecting-routes-on-map-with-r-and-great-circles/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://www.r-graph-gallery.com/2017/06/14/how-to-draw-connecting-routes-on-map-with-r-and-great-circles/"> Blog – The R graph Gallery</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i2.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_7.png?w=450" alt="" class="wp-image-3545" data-recalc-dims="1">This post explains how to draw <strong>connection lines</strong> between several localizations on a map, using <strong>R</strong>. The method proposed here relies on the use of the <strong>gcIntermediate</strong> function from the <a rel="nofollow" href="https://cran.r-project.org/web/packages/geosphere/vignettes/geosphere.pdf" target="_blank">geosphere</a> package. Instead of making straight lines, it offers to draw the shortest routes, using <a rel="nofollow" href="https://en.wikipedia.org/wiki/Great_circle" target="_blank">great circles</a>. A special care is given for situations where cities are very far from each other and where the shortest connection thus passes behind the map.</p>
<p>First we need to load 3 libraries. <a rel="nofollow" href="https://cran.rstudio.com/web/packages/maps/maps.pdf" target="_blank">Maps</a> allows to draw the background map, and <a rel="nofollow" href="https://cran.r-project.org/web/packages/geosphere/vignettes/geosphere.pdf" target="_blank">geosphere</a> provides the gcintermediate function.</p>
<pre>library(tidyverse)
library(maps)
library(geosphere)</pre>
<p> </p>
<p><strong><span>1- Draw an empty map</span></strong></p>
<hr>
<p>This is easily done using the<strong> ‘maps’</strong> package. You can see plenty of other maps made with R in the <a rel="nofollow" href="http://www.r-graph-gallery.com/portfolio/maps/" target="_blank">map section</a> of the <a rel="nofollow" href="http://www.r-graph-gallery.com/" target="_blank">R graph gallery</a>.</p>
<pre>par(mar=c(0,0,0,0))
map('world',col=&quot;#f2f2f2&quot;, fill=TRUE, bg=&quot;white&quot;, lwd=0.05,mar=rep(0,4),border=0, ylim=c(-80,80) )</pre>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i2.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_1.png?w=450" alt="" class="wp-image-3539" data-recalc-dims="1"></p>
<p><strong><span>2- Add 3 cities</span></strong></p>
<hr>
<p>First we create a data frame with the coordinates of Buenos Aires, Melbourne and Paris</p>
<pre>Buenos_aires=c(-58,-34)
Paris=c(2,49)
Melbourne=c(145,-38)
data=rbind(Buenos_aires, Paris, Melbourne) %>% as.data.frame()
colnames(data)=c(&quot;long&quot;,&quot;lat&quot;)</pre>
<p>Then add it to the map using the ‘points’ function:</p>
<pre>points(x=data$long, y=data$lat, col=&quot;slateblue&quot;, cex=3, pch=20)</pre>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i2.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_2.png?w=450" alt="" class="wp-image-3540" data-recalc-dims="1"></p>
<p><strong><span>4- Show connection between them</span></strong></p>
<hr>
<p>Now we can connect cities drawing the shortest route between them. This is done using great circles, what gives a better visualization than using straight lines. This technique has been proposed by Nathan Yau on <a rel="nofollow" href="https://flowingdata.com/2011/05/11/how-to-map-connections-with-great-circles/" target="_blank">FlowingData</a></p>
<pre># Connection between Buenos Aires and Paris
inter &lt;- gcIntermediate(Paris,  Buenos_aires, n=50, addStartEnd=TRUE, breakAtDateLine=F)             
lines(inter, col=&quot;slateblue&quot;, lwd=2)

# Between Paris and Melbourne
inter &lt;- gcIntermediate(Melbourne,  Paris, n=50, addStartEnd=TRUE, breakAtDateLine=F)             
lines(inter, col=&quot;slateblue&quot;, lwd=2)</pre>
<p><a rel="nofollow" href="http://www.r-graph-gallery.com/2017/06/14/how-to-draw-connecting-routes-on-map-with-r-and-great-circles/connection_lines_3/" target="_blank"><img sizes="(max-width: 764px) 100vw, 764px" src="https://i0.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_3.png?w=450" alt="" data-recalc-dims="1"></a><br>
<a rel="nofollow" href="http://www.r-graph-gallery.com/2017/06/14/how-to-draw-connecting-routes-on-map-with-r-and-great-circles/connection_lines_4/" target="_blank"><img sizes="(max-width: 764px) 100vw, 764px" src="https://i1.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_4.png?w=450" alt="" data-recalc-dims="1"></a>
</p>
<p><strong><span>5 – Correcting gcIntermediate</span></strong></p>
<hr>
<p>If we use the same method between Melbourne and Buenos Aires, we get this disappointing result:</p>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i0.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_5.png?w=450" alt="" class="wp-image-3543" data-recalc-dims="1"></p>
<p>What happens is that gcintermediate follows the shortest path, which means it will go East from Australia until the date line, break the line and come back heading East from the pacific to South America. Because we do not want to see the horizontal line, we need to plot this connection in 2 times.</p>
<p>To do so we can use the following function, which breaks the line in 2 sections when the distance between 2 points is longer than 180 degrees.</p>
<pre>plot_my_connection=function( dep_lon, dep_lat, arr_lon, arr_lat, ...){
	inter &lt;- gcIntermediate(c(dep_lon, dep_lat), c(arr_lon, arr_lat), n=50, addStartEnd=TRUE, breakAtDateLine=F)             
	inter=data.frame(inter)
	diff_of_lon=abs(dep_lon) + abs(arr_lon)
	if(diff_of_lon > 180){
		lines(subset(inter, lon>=0), ...)
		lines(subset(inter, lon&lt;0), ...)
	}else{
		lines(inter, ...)
		}
	}</pre>
<p>Let’s try it!</p>
<pre>map('world',col=&quot;#f2f2f2&quot;, fill=TRUE, bg=&quot;white&quot;, lwd=0.05,mar=rep(0,4),border=0, ylim=c(-80,80) )
points(x=data$long, y=data$lat, col=&quot;slateblue&quot;, cex=3, pch=20)

plot_my_connection(Paris[1], Paris[2], Melbourne[1], Melbourne[2], col=&quot;slateblue&quot;, lwd=2)
plot_my_connection(Buenos_aires[1], Buenos_aires[2], Melbourne[1], Melbourne[2], col=&quot;slateblue&quot;, lwd=2)
plot_my_connection(Buenos_aires[1], Buenos_aires[2], Paris[1], Paris[2], col=&quot;slateblue&quot;, lwd=2)</pre>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i2.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_6.png?w=450" alt="" class="wp-image-3544" data-recalc-dims="1"></p>
<p><strong><span>6 – Apply it to several pairs of cities</span></strong></p>
<hr>
<p>Let’s consider 8 cities:</p>
<pre>data=rbind(
	Buenos_aires=c(-58,-34),
	Paris=c(2,49),
	Melbourne=c(145,-38),
	Saint.Petersburg=c(30.32, 59.93),
	Abidjan=c(-4.03, 5.33),
	Montreal=c(-73.57, 45.52),
	Nairobi=c(36.82, -1.29),
	Salvador=c(-38.5, -12.97)
	)  %>% as.data.frame()
colnames(data)=c(&quot;long&quot;,&quot;lat&quot;)</pre>
<p>We can generate all pairs of coordinates</p>
<pre>all_pairs=cbind(t(combn(data$long, 2)), t(combn(data$lat, 2))) %>% as.data.frame()
colnames(all_pairs)=c(&quot;long1&quot;,&quot;long2&quot;,&quot;lat1&quot;,&quot;lat2&quot;)</pre>
<p>And plot every connections:</p>
<pre># background map
par(mar=c(0,0,0,0))
map('world',col=&quot;#f2f2f2&quot;, fill=TRUE, bg=&quot;white&quot;, lwd=0.05,mar=rep(0,4),border=0, ylim=c(-80,80) )

# add every connections:
for(i in 1:nrow(all_pairs)){
	plot_my_connection(all_pairs$long1[i], all_pairs$lat1[i], all_pairs$long2[i], all_pairs$lat2[i], col=&quot;skyblue&quot;, lwd=1)
	}

# add points and names of cities
points(x=data$long, y=data$lat, col=&quot;slateblue&quot;, cex=2, pch=20)
text(rownames(data), x=data$long, y=data$lat,  col=&quot;slateblue&quot;, cex=1, pos=4)</pre>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i2.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_7.png?w=450" alt="" class="wp-image-3545" data-recalc-dims="1"></p>
<p><strong><span>7 – An alternative using the greatCircle function</span></strong></p>
<hr>
<p>This is the method proposed by the <a rel="nofollow" href="http://simplystatistics.tumblr.com/post/14568185310/an-r-function-to-map-your-twitter-followers" target="_blank">Simply Statistics</a> Blog to draw a twitter connection map. The idea is to calculate the whole great circle, and keep only the part that stays in front of the map, never going behind it.</p>
<pre># A function that keeps the good part of the great circle, by Jeff Leek:
getGreatCircle = function(userLL,relationLL){
  tmpCircle = greatCircle(userLL,relationLL, n=200)
  start = which.min(abs(tmpCircle[,1] - data.frame(userLL)[1,1]))
  end = which.min(abs(tmpCircle[,1] - relationLL[1]))
  greatC = tmpCircle[start:end,]
  return(greatC)
}

# map 3 connections:
map('world',col=&quot;#f2f2f2&quot;, fill=TRUE, bg=&quot;white&quot;, lwd=0.05,mar=rep(0,4),border=0, ylim=c(-80,80) )
great=getGreatCircle(Paris, Melbourne)
lines(great, col=&quot;skyblue&quot;, lwd=2)
great=getGreatCircle(Buenos_aires, Melbourne)
lines(great, col=&quot;skyblue&quot;, lwd=2)
great=getGreatCircle(Paris, Buenos_aires)
lines(great, col=&quot;skyblue&quot;, lwd=2)
points(x=data$long, y=data$lat, col=&quot;slateblue&quot;, cex=3, pch=20)
text(rownames(data), x=data$long, y=data$lat,  col=&quot;slateblue&quot;, cex=1, pos=4)</pre>
<p><img sizes="(max-width: 980px) 100vw, 980px" src="https://i2.wp.com/www.r-graph-gallery.com/wp-content/uploads/2017/06/Connection_lines_8.png?w=450" alt="" class="wp-image-3546" data-recalc-dims="1"></p>
<p>Note that the <a rel="nofollow" href="http://www.r-graph-gallery.com/" target="_blank">R graph gallery</a> proposes lot of other examples of <a rel="nofollow" href="http://www.r-graph-gallery.com/portfolio/maps/" target="_blank">maps made with R</a>. You can follow the gallery on <a rel="nofollow" href="https://twitter.com/R_Graph_Gallery" target="_blank">Twitter</a> or on <a rel="nofollow" href="https://www.facebook.com/RGraphGallery/" target="_blank">Facebook</a> to be aware or recent updates.</p>
<p><a rel="nofollow" href="http://www.r-graph-gallery.com/2017/06/14/how-to-draw-connecting-routes-on-map-with-r-and-great-circles/#" title="Recommend this" target="_blank"><span>1</span> <span></span></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="http://www.r-graph-gallery.com/2017/06/14/how-to-draw-connecting-routes-on-map-with-r-and-great-circles/"> Blog – The R graph Gallery</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/1l1q-uquCPA" height="1"></a></div>