Flight connection map with R

Flight connection Map wit R

Hey folks,

I was recently asked how to visualize flight connections with R, so I decided to make a blog post with a short tutorial on this topic: The aim is to map all possible flight connections from the NYC JFK Airport to other major airports in the US. For this we will be using the following packages:

  • nycflights13: Dataset with flights departing from NYC in 2013.
  • dplyr: package for manipulating datasets.
  • maps: package for mapping.
  • geosphere: package for spherical trigonometry.

Make sure to install and load these beforehand using the install.packages() and library() functions.


Lets get  a quick overview on the dataset first. Once you loaded the package nycflights13 you have access to the dataset airports:

Source: local data frame [1,397 x 7]

   faa                           name      lat        lon  alt tz dst
1  04G              Lansdowne Airport 41.13047  -80.61958 1044 -5   A
2  06A  Moton Field Municipal Airport 32.46057  -85.68003  264 -5   A
3  06C            Schaumburg Regional 41.98934  -88.10124  801 -6   A
4  06N                Randall Airport 41.43191  -74.39156  523 -5   A
5  09J          Jekyll Island Airport 31.07447  -81.42778   11 -4   A
6  0A9 Elizabethton Municipal Airport 36.37122  -82.17342 1593 -4   A
7  0G6        Williams County Airport 41.46731  -84.50678  730 -5   A
8  0G7  Finger Lakes Regional Airport 42.88356  -76.78123  492 -5   A
9  0P2   Shoestring Aviation Airfield 39.79482  -76.64719 1000 -5   U
10 0S9          Jefferson County Intl 48.05381 -122.81064  108 -8   A
.. ...                            ...      ...        ...  ... .. ...

The dataset contains useful metadata on airports. For our map however we only want airports that are located in the US. Therefore we will make a couple of data filtering steps using the dplyr package. We will select only those airports which have a latitude < 48.5 and a longitude > -130. Then we will exclude the JFK airport from this dataset and create a new dataframe just containing the JFK airport:

usairports <- filter(airports, lat < 48.5)
usairports <- filter(usairports, lon > -130)
usairports <- filter(usairports, faa!="JFK") #filter out jfk
jfk <- filter(airports, faa=="JFK") #separate df for jfk

Create flight connection map:

The data is now prepared for our final flight connection map. The first step will be to create a basemap for the US using the maps package:

#create basemap
map("world", regions=c("usa"), fill=T, col="grey8", bg="grey15", ylim=c(21.0,50.0), xlim=c(-130.0,-65.0))
#overlay airports
points(usairports$lon,usairports$lat, pch=3, cex=0.1, col="chocolate1")

The map should now look like this:

US aiports

The next and final step is to add the flight connectins from NYC to all other airports using the gesophere package and the gcIntermediate() function.

for (i in (1:dim(usairports)[1])) { 
inter <- gcIntermediate(c(jfk$lon[1], jfk$lat[1]), c(usairports$lon[i], usairports$lat[i]), n=200)
lines(inter, lwd=0.1, col="turquoise2")    

The gcIntermediate() function takes two points and creates a circular connection between them. With the lines() function you add this circle to the plot. In this example this is done for all airports in the dataframe with a for loop. The final map can be seen below:


Enjoy the final result! If you have any questions related to dplyr or the gesophere package, feel free to ask.



About This Author

Martin was born in Czech Republic and studied at the University of Natural Resources and Life Sciences, Vienna. He is currently working at GeoVille - an Earth Observation Company based in Austria, specialised in Land Monitoring. His main interests are: Open-source applications like R, (geospatial) statistics and data-management, web-mapping and visualization. He loves travelling, geocaching, photography and sports.


You can post comments in this post.

  • Wow, that’s a pretty nice visual result with just a couple lines of code. Can you also load rasters using one of those modules?

    Kuba Konczyk 4 years ago Reply

    • You can plot raster images with the package called “raster”. First you have to load your raster into R and then you can plot it with the plot() function. If you want to overlay points or lines, you have to be carful that both coordinate systems match. You can find a basic introduction into the raster package here: R {raster}: Introduction and basic plotting

      Martin 4 years ago Reply

  • Thanks for such a great and succinct post on this! I came across your blog from the question in stackoverflow. Love the colors in your visualization as well.

    Nistara Randhawa 3 years ago Reply

    • Thanks for the positive feedback.

      Martin 3 years ago Reply

  • Hey Martin!

    Great job on the visualization, it looks awesome!
    How did you manage to create such thin lines, and make the lines look sort of transparant ?

    Enzo 3 years ago Reply

  • Hey Martin!

    Great job on the visualization, it looks awesome!
    How did you manage to create such thin lines, and make the lines look sort of transparant?

    Enzo 3 years ago Reply

    • Hey Enzo! Actually the lines only appear to be transparent but its an illusion because they are really thin. So when two lines overlap and intersect they create a broader line which appears to be darker.
      Its all done by setting the lwd paramater of the lines() function to 0.1 and by selecting a bright color compared to the background:

      lines(inter, lwd=0.1, col=”turquoise2″)

      Martin 3 years ago Reply

  • The visualization looks great, thank you for sharing Martin! I would like to do a somewhat similar map but for Eurasia (including EU, Russia and countries in between), do you know if it is possible with the steps you have described?

    Anastasia 2 years ago Reply

    • It’s definitely possible but you need a comparable datasets on flights in Eurasia or atleast airport coordinates so you can simualte such a dataset. The vizualisation steps are then the same.

      Martin 2 years ago Reply

  • Martin,

    Thanks for the great visualization. I started using the code to plot livestock movements in the US and looks awesome. I am trying to weight my movements based on the # of shipments from county-to-county or # of animals shipped in each shipment. In simple words, those county-to-county movements with more # of shipments every year will be represented in my flow map with thicker lines. Do you think is that possible within your code?

    Aurelio 1 year ago Reply

    • Hey Aurelio,
      happy to hear! yes! you need to change the lwd (linewidth) paramater for each shipment individually.
      Now it looks like this – with a fixed width of 0.1:
      lines(inter, lwd=0.1, col=”turquoise2″)

      Hope this helps!

      Martin 1 year ago Reply

Post A Reply