In todays post, we are going to learn how to draw a beautiful map using
Julia. For a long time, I have used a combination of
R to draw all my maps. I have tried on a few occassions to port my mapping over to
Julia, but the maps I have been able to draw, so far, have been terrible. Until now...
So, we are going to go over the following processes towards drawing a good map:
Import a shapefile of a geographic region to plot for our map
Import GPS records for a focal species from a .csv file
Plot the GPS records over the shapefile we imported
Some basic editing of the map appearance to make it look beautiful
As always, the first thing we need to do is download and load the required packages to perform these operations.
# Download required packages, if necessary (remove # to evaluate code) # Pkg.add(["GBIF", "Shapefile", "CairoMakie", "AlgebraOfGraphics", "DataFrames", "CSV]) # Load required packages into current session using Shapefile # Import and manipulate raster data (e.g. .shp files) using CairoMakie # Plotting utilities using AlgebraOfGraphics # Plotting utilities using DataFrames # Create and manipulate DataFrame objects using CSV # Import and process .csv files using GBIF # Plotting using SimpleSDMLayers # Plotting using Colors # Plotting
The next step is to load the GPS data we want to plot. We are going to import our own file containing GPS data (e.g. a .csv file). Alternatively, we could download data straight from online repositories (e.g. GBIF).
# Import .csv file containing GPS data df = DataFrames.DataFrame(CSV.File(".\\_assets\\data\\001_drawing_maps\\senecio_gps.csv")); # Show just the first 10 rows of GPS data first(df, 10)
10×3 DataFrame Row │ scientific longitude latitude │ String31 Float64 Float64 ─────┼─────────────────────────────────────────────── 1 │ Senecio madagascariensis 30.6458 -29.8125 2 │ Senecio madagascariensis 30.2292 -29.5208 3 │ Senecio madagascariensis 31.2292 -25.5208 4 │ Senecio madagascariensis 30.1875 -29.5208 5 │ Senecio madagascariensis 30.6458 -29.7292 6 │ Senecio madagascariensis 30.9792 -29.6458 7 │ Senecio madagascariensis 31.0625 -29.7292 8 │ Senecio madagascariensis 30.3542 -30.3125 9 │ Senecio madagascariensis 30.6042 -29.7708 10 │ Senecio madagascariensis 30.6875 -29.7292
Voila - We now have 136 GPS records to work with.
We are now going to load a shapefile containing a map of the countries of Africa using
Shapefile.jl. This map is going to be our base layer.
# Import the .shp file using Shapefile.jl # Downloaded from: https://geoportal.icpac.net/layers/geonode%3Aafr_g2014_2013_0 table = Shapefile.Table(".\\_assets\\data\\001_drawing_maps\\shapefiles\\afr_g2014_2013_0.shp");
The Africa map is currently stored as a Shapefile.Table, not a map. In the next section, we will need to convert the Shapefile.Table into a map to visualise the map.
Before we do anything else, we are going to change the theme/appearance of the map that we are going to make. This is just my personal preference, so feel free to remove or edit, to your preference.
# Set map theme for AlgebraOfGraphics.jl set_aog_theme!() update_theme!( Axis = ( topspinevisible = true, rightspinevisible = true, bottomspinecolor = :black, leftspinecolor = :black, xtickcolor =:black, ytickcolor =:black ) );
Now we are going to build our map layer-by-layer. This process is similar to how
ggplot2 makes figures in
R, as we are going to effectively stack different layers of information over one another to make a map. The first layer we are doing to make is the base layer containing the map of Africa.
# Step 1: Create a raster layer with the African shapefile (.shp) layer_map = geodata(table) * mapping( :geometry ) * visual( Poly, strokecolor = :black, strokewidth = 1, linestyle = :solid, color = "white" ); # Print Africa map draw(layer_map);
The next step is to create a layer containing the GPS points that we want to plot over the Africa map. We need to pass the
DataFrame containing the latitude and longitudes for each GPS point and a column containing a text identified with the species/taxon name to plot in the legend.
# Step 2: Create a layer with points for the GPS data layer_gps = data(df) * mapping( :longitude, :latitude, # Changes the legend name color = :scientific => "Species" ) * visual( Scatter, marker = :circle, markersize = 12.5, );
The last step is to plot the two layers of information to make our final map.
# Set all points labelled as Senecio madagascariensis to black colour colors = ["Senecio madagascariensis" => colorant"#000000"] # Step 3: Combine layers to make map map_final = draw( # Pass layer containing base layer shapefile layer_map + # Pass layer containing GPS points layer_gps, # Define x and y axis limits, axis tick range and axis labels axis = ( limits = ((-20, 55), (-38, 40)), xticks = -20:10:55, yticks = -38:10:40, aspect = 1, xlabel = "Longitude", ylabel = "Latitude", ), figure = ( resolution = (750, 750), ), # Place the legend on top of the figure (position = :top) legend = (position = :top, titleposition = :left, ), palettes = (color = colors, ) );