Построение графика вокруг линии дат +/- 180 с использованием sf и ggplot2

Я использую sf для построения серии шейп-файлов и точечных данных. Эти данные охватывают линию дат на = / - 180 долготы.

sf::st_shift_longitude() обрабатывает эту ситуацию и отображает точки, как и ожидалось. Однако ggplot ведет себя странно при назначении отметок долготы. В приведенном ниже коде представлен один пример с двумя точками на одной стороне шкалы дат - примечание ggplot добавляет логические метки для долготы. Во втором примере точки охватывают линию дат.

Изменить: добавлен третий случай с расширенными вручную пределами x. Когда они станут достаточно большими, сетка будет отображаться должным образом. Однако я нашел «достаточно большой» только экспериментально с xlim.

library(sf)
library(rnaturalearth)
library(ggplot2)

#get basic world map 
world = ne_coastline(scale = "medium", returnclass = "sf")

#example 1: without dateline
#minimal data- two points on one side of dateline
sites = data.frame(longitude = c(-173.9793, -177.7405), latitude = c(52.21415, 51.98994))

#convert to sf object
sites = st_as_sf(sites, coords = c("longitude", "latitude"), crs = 4326)

#plot with ggplot
ggplot()+
  geom_sf(data = world, fill = 'transparent')+
  geom_sf(data = sites)+
  #set the limits for the plot
  coord_sf(crs = 4326,
           xlim = c(min(st_coordinates(sites)[,1]) -1, max(st_coordinates(sites)[,1])+1),
           ylim = c(min(st_coordinates(sites)[,2]) -1, max(st_coordinates(sites)[,2])+1))+
  labs(title = 'data on one side of dateline only- looks good')+
  theme_bw()


#example 2: with dateline
#deal with dateline using st_shift_longitude 
world_2 = st_shift_longitude(world)

#minimal data- a point on each side of dateline
sites_2 = data.frame(longitude = c(-173.9793, 177.7405), latitude = c(52.21415, 51.98994))

#convert to sf object
sites_2 = st_as_sf(sites_2, coords = c("longitude", "latitude"), crs = 4326)
#and deal with dateline using st_shift_longitude 
sites_2 = st_shift_longitude(sites_2)

#plot with ggplot
ggplot()+
  geom_sf(data = world_2, fill = 'transparent')+
  geom_sf(data = sites_2)+
  #set the limits for the plot
  coord_sf(crs = 4326,
           xlim = c(min(st_coordinates(sites_2)[,1]) -1, max(st_coordinates(sites_2)[,1])+1),
           ylim = c(min(st_coordinates(sites_2)[,2]) -1, max(st_coordinates(sites_2)[,2])+1))+
  labs(title = 'data on both sides of dateline - grid wrong')+
  theme_bw()

#plot with manually expanded limits- graticule works
ggplot()+
  geom_sf(data = world_2, fill = 'transparent')+
  geom_sf(data = sites_2)+
  #set the limits for the plot
  coord_sf(crs = 4326,
           xlim = c(175, 195),
           ylim = c(min(st_coordinates(sites_2)[,2]) -1, max(st_coordinates(sites_2)[,2])+1))+
  labs(title = 'data on both sides of dateline - manually expand x lims')+
  theme_bw()



введите здесь описание изображения  введите описание изображения здесь  введите описание изображения здесь

Есть ли у вас какие-либо идеи, как обойти шкалу дат, чтобы избежать такого поведения при построении графика с помощью ggplot?

Спасибо!


person MLevine    schedule 27.03.2020    source источник


Ответы (1)


Я не знаю достаточно ggplot, но я предполагаю, что внутренняя сетка ограничена -180,180, и событие, хотя вы сдвинули объект sf, ggplot не распознает это при создании оси и сетки.

Я создал пример с базой plot, которая, похоже, работает так, как вы ожидаете. Сетка создается с помощью graphics::grid()



library(sf)
#> Warning: package 'sf' was built under R version 3.5.3
#> Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(rnaturalearth)
#> Warning: package 'rnaturalearth' was built under R version 3.5.3

#get basic world map
world = ne_coastline(scale = "medium", returnclass = "sf")

#example 1: without dateline
#minimal data- two points on one side of dateline
sites = data.frame(
  longitude = c(-173.9793,-177.7405),
  latitude = c(52.21415, 51.98994)
)

#convert to sf object
sites = st_as_sf(sites,
                 coords = c("longitude", "latitude"),
                 crs = 4326)

#deal with dateline using st_shift_longitude
world_2 = st_shift_longitude(world)

#minimal data- a point on each side of dateline
sites_2 = data.frame(
  longitude = c(-173.9793, 177.7405),
  latitude = c(52.21415, 51.98994)
)

#convert to sf object
sites_2 = st_as_sf(sites_2,
                   coords = c("longitude", "latitude"),
                   crs = 4326)
#and deal with dateline using st_shift_longitude
sites_2 = st_shift_longitude(sites_2)

#Plot
plot(
  st_geometry(world_2),
  axes = TRUE,
  xlim = c(min(st_coordinates(sites_2)[, 1]) - 1, max(st_coordinates(sites_2)[, 1]) +
             1),
  ylim = c(min(st_coordinates(sites_2)[, 2]) - 1, max(st_coordinates(sites_2)[, 2]) +
             1)
)
grid()
plot(st_geometry(sites_2), pch = 20, add = TRUE)

Создано 28 марта 2020 г. пакетом REPEX (v0.3.0)

person dieghernan    schedule 28.03.2020
comment
Спасибо, диегернан. Я не уверен, вызывает ли это ограничение сетки в ggplot2, но я не уверен, что это такое. Я отредактировал, чтобы продемонстрировать, что ручное расширение пределов оси X позволяет строить сетку должным образом. - person MLevine; 01.04.2020