I have a specific map to which I'd like to add lines between countries, and later on, also line weights. The code below runs, but nothing shows up on the map. Note that df is created with ne_countries(), but I st_transform the map to Robinson projection, so I'm not sure the coordinates of df are correct.
I know there are many ways of drawing lines on a map, and I'm not sure geom_segment is the best so I'm open to other solutions. I'm fine with adding points and then lines, which I've seen but also couldn't make work.
library(ggplot2)
library(sf)
library(rnaturalearth)
library(dplyr)
library(rgdal)
#creating the map:
# Download countries polygons
shp <- ne_countries(type = "countries",
scale = "medium",
returnclass = "sf") |>
# transform to desired projection
st_transform("ESRI:54030")
shp <- subset(shp, select = -c(1:17, 19:63))
# Creating df with long and lat
countries <- ne_countries()
countries$longitude <- coordinates(countries)[,1]
countries$latitude <- coordinates(countries)[,2]
countries_xy <- countries@data %>%
select(admin, longitude, latitude)
# Joining long and lat to origin & destination
df1 <- tibble(origins = sample(c('Australia'),
size = 1, replace = TRUE),
destinations = sample(c('Fiji', 'Papua New Guinea', 'Sweden'),
size = 3, replace = FALSE))
df2 <- df1 %>%
left_join(countries_xy, by = c('origins' = 'admin')) %>%
left_join(countries_xy, by = c('destinations' = 'admin'))
df2$longitude.y <- as.numeric(as.character(df3$longitude.y))
df2$latitude.y <- as.numeric(as.character(df3$latitude.y))
# Merging shp and df
shp <- merge(shp,df2, by = "name", all.x = TRUE)
# Drawing the lines on the map (note that I also color the map with a discrete variable, but I don't think that is important here)
shp |>
ggplot() +
geom_sf(aes(fill = discrete_var)) +
geom_segment(aes(x = latitude.x,
y = latitude.y,
xend = longitude.x,
yend = longitude.y),
color = "white") +
scale_fill_brewer(palette = 'Purples', direction=-1, na.value="grey", drop = FALSE) +
coord_sf(expand = FALSE)
I know there are many other ways of drawing lines on a map, and I'm not sure geom_segment is the best so I'm open to other solutions.
It is way easier to plot and analyse spatial data if they are all spatial objects (sf, sfc, SpatRaster etc.). So here's a method to create your lines as an sf object.
It was not clear from your code where you wanted the lines to terminate so I have arbitrarily used country centroids for this example. It is possible to use
st_nearest_points()if you want, but I believe centroids are a better choice visually for what you are mapping. Comment below if you want the lines to terminate in a different location.Also, you do not need to explicitly load the
rgdallibrary assfbinds to itGDALby default. Further,rgdalwas deprecated last year and it's functions are being passed tosf. For example, functions likecoordinates()can be handled bysfasst_coordinates().EDIT: Based on OP's comments, if you have previously installed
rgdal, you may need to remove all traces of it from your library directory. That includes the versions ofGDAL,GEOS, andPROJthatrgdalbinds to. The answer was also updated as the OP requested a curved geom, hence the inclusion of the x1, x2, y1, and y2 columns.