rggplot2geospatialrgeo

adding point data to globe perspective in R


I have duplicated the solution to creating a 3-dimensional plot of the earth provided by @jindra-lacko (plot geodata on the globe perspective in R). All I want to be able to do is to plot data points on this map. However, no matter what approach I try I end up with only a single point right in the middle of the plot.

As a simple example, here I am trying to create two points from the dataframe 'closures'. However, only a single point is created in the middle of the plot. I have not been able to create more than one point and not able to change the position of that point. Feels like there should be an easy solution but I am stumped. Thanks.

library(sf)
library(giscoR) # for the countries dataset only
library(ggplot2)

# projection string used for the polygons & ocean background
crs_string <- "+proj=ortho +lon_0=-30 +lat_0=50"

# background for the globe - center buffered by earth radius
ocean <- st_point(x = c(0,0)) %>%
  st_buffer(dist = 6371000) %>%
  st_sfc(crs = crs_string)

# country polygons, cut to size
world <- gisco_countries %>% 
  st_intersection(ocean %>% st_transform(4326)) %>% # select visible area only
  st_transform(crs = crs_string) # reproject to ortho

# one of the visible ones red (don't really matter which one :)
world$fill_color <- ifelse(world$ISO3_CODE == "DEU", "interesting", "dull")

closures <- data.frame(
  x = c(-30,-40),
  y = c(40,50),
  label = c("1","2")
)

closures <- sf::st_as_sf(closures, 
                       coords = c("x", "y"),
                       crs = crs_string)


# now the action!
ggplot(data = world) +
  geom_sf(data = ocean, fill = "aliceblue", color = NA) + # background first
  geom_sf(aes(fill = fill_color), lwd = .1) + # now land over the oceans
  scale_fill_manual(values = c("interesting" = "lightyellow", #change colour here to highlight a specific country
                               "dull" = "lightyellow"),
                    guide = "none") +
  geom_sf(data = closures,
          aes(geometry = geometry),
          size = 7,
          shape = 21,
          color = "white",
          fill="red") +
  theme_void()

Solution

  • The issue is that you are telling sf that your lon lat coordinates are in the "+proj=ortho +lon_0=-30 +lat_0=50" projection, but they haven't been projected quite yet. First, you should set the crs as WGS 1984 (epsg:4326) then you can transform/project them into "+proj=ortho +lon_0=-30 +lat_0=50".

    library(sf)
    #> Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
    library(giscoR) # for the countries dataset only
    #> Warning: package 'giscoR' was built under R version 4.4.1
    library(ggplot2)
    
    crs_string <- "+proj=ortho +lon_0=-30 +lat_0=50"
    
    ocean <- st_point(x = c(0,0)) %>%
      st_buffer(dist = 6371000) %>%
      st_sfc(crs = crs_string)
    
    world <- gisco_countries %>% 
      st_intersection(ocean %>% st_transform(4326)) %>%
      st_transform(crs = crs_string)
    #> Warning: attribute variables are assumed to be spatially constant throughout
    #> all geometries
    
    world$fill_color <- ifelse(world$ISO3_CODE == "DEU", "interesting", "dull")
       
    closures <- data.frame(
      x = c(-30,-50),
      y = c(40,50),
      label = c("1","2")
    )
    
    closures <- sf::st_as_sf(closures, 
                           coords = c("x", "y"),
                           crs = 4326) %>% # read into WGS 1984
      st_transform(crs = crs_string) # transform into projection
    
    ggplot(data = world) +
      geom_sf(data = ocean, fill = "aliceblue", color = NA) +
      geom_sf(fill = "lightyellow", lwd = .1) +
      geom_sf(data = closures,
              size = 7,
              shape = 21,
              color = "white",
              fill="red")
    

    Created on 2024-07-11 with reprex v2.1.0