How to adjust projection and remove 'streak' across raster map in ggplot

49 Views Asked by At

I'm creating a world map of elevation in R.

When I plot the raster of elevations around the world there are two problems

  1. I want to change the projection and the prime meridian (the centre point of the map)
  2. When I plot the raster, there is a 'streak' across the map where Russia crosses the map edge and runs across to the opposite map edge

How can I adjust the projection, meridian and remove the streak.

Repro example

pacman::p_load(
  char =  c(
    "tidyverse",
    "rnaturalearth", # For map data
    "tmaptools",     # For geo-coding city's lat/lon
    "elevatr",       # For elevation data
    "rgeoboundaries",
    "sf",
    "raster",
    "ggstar"         # For hexagons in geom_point
    )
  )

devtools::install_github(
  quiet = TRUE,
  repo = c(
    "ropensci/rnaturalearthhires", 
    "ropensci/rnaturalearthdata"
    )
  )

conflicted::conflict_prefer_all("dplyr", quiet = TRUE)
df_world <- 
  rnaturalearth::ne_countries(
    type = "countries",
    scale = "large",
    returnclass = "sf"
    ) %>% 
  sf::st_make_valid()
df_elevation <- 
  elevatr::get_elev_raster(
    locations = df_world, 
    z = 1, # Important, this is the resolution of the elevation data
    clip = "locations") %>%  
  as.data.frame(xy = TRUE) %>% 
  rename(elevation = 3) %>% 
  filter(
    !is.na(elevation),
    elevation > 0)
ggplot() +
  geom_raster(
    data = df_elevation, 
    aes(
      x = x, 
      fill = elevation, 
      y = y
      )
    ) +
  coord_sf()

enter image description here

And here's a solution I've created for sf objects. However, I don't know how to adapt this solution for raster images...

trim_sf_edge <- function(df, projection = "robin", prime_meridian = 10) {
  df %>%
  sf::st_difference(
    sf::st_polygon(
      x = list(
        rbind(
          c(-0.0001 - (180 - prime_meridian), 90),
          c(0.0000 - (180 - prime_meridian), 90),
          c(0.0000 - (180 - prime_meridian), -90),
          c(-0.0001 - (180 - prime_meridian), -90),
          c(-0.0001 - (180 - prime_meridian), 90)
          )
        )
      ) %>%
      sf::st_sfc() %>%
      sf::st_set_crs(4326)
    ) %>%
  sf::st_transform(
    crs = sf::st_crs(
      paste0(
        paste0("+proj=", projection, " "),
        "+lon_0=0 ",
        "+x_0=0 ",
        "+y_0=0 ",
        "+datum=WGS84 ",
        "+units=m ",
        paste0("+pm=", prime_meridian, " "), # Prime meridian
        "+no_defs"
        )
      )
    ) %>% 
    return()
}
df_world <- df_world %>% 
  sf::st_union() %>% 
  trim_sf_edge(
    prime_meridian = 10, 
    projection = "robin")

And do the same for elevation

df_elevation <- df_elevation %>% 
  trim_sf_edge(
    prime_meridian = 10, 
    projection = "robin")

But the last piece of code gives the error: Error in UseMethod("st_difference") : no applicable method for 'st_difference' applied to an object of class "data.frame"

0

There are 0 best solutions below