如何对跨越国际日期变更线的路径使用R进行补救 [英] How to remedy a path that crosses the international dateline with R

查看:20
本文介绍了如何对跨越国际日期变更线的路径使用R进行补救的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好!我正在尝试使用R和一系列纬度/经度点在世界地图上绘制多艘船的路线。

在船穿过国际日期变更线(-180/180)之前,一切都很好,当路径跳过地图时。

我尝试在R中应用st_rapp_dateline()函数,但它似乎只对具有两个点(起始和结束坐标)的数据集有效。

我的R代码在下面,还有一张所生成的绘图的屏幕截图-任何帮助都非常感谢!

# Download background Blue Marble Globe image
download.file("https://www.researchvessels.org/images/nasa_base_v2.png", "nasa_base_v2.png", mode="wb")
# Download ship lat/lon data
download.file("https://www.researchvessels.org/images/shipdata.RDATA", "shipdata.RDATA", mode="wb")
load("shipdata.RDATA", envir = parent.frame(), verbose=TRUE)

# Ensure that the required packages are installed
list.of.packages <- c("ggplot2", "sf", "dplyr", "png", "grid")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)>0) {install.packages(new.packages)}


library(ggplot2)
library(sf)
library(dplyr)
library(png)
library(grid)

bluemarble_bg <- png::readPNG("nasa_base_v2.png")

xlim = c(-180.0,180.0)
ylim = c(-90.0,90.0)

shiptracks$Date.Time <- as.POSIXct(shiptracks$Date.Time, tz="GMT", origin="1970-01-01")

pal <- c("ShipA" = "#488f31", 
         "ShipB" = "#FF00FF", 
         "ShipC" = "#fff1a9",
         "ShipD" = "#f19d61", 
         "ShipE" = "#de425b")

shiptracks %>% group_by(Vessels.Name)

shiptracks <- st_as_sf(shiptracks, coords=c("Lon", "Lat")) %>% st_set_crs(4326)

shiptracks <- cbind(shiptracks, st_coordinates(shiptracks)) 

shiptracks <- shiptracks %>%
  st_sf() %>%
  st_wrap_dateline(options = c("WRAPDATELINE=YES", "DATELINEOFFSET=180"),
                   quiet = FALSE) %>%
  sf::st_sf(crs = 4326)

shipmap <- ggplot(shiptracks, aes(x=X, y=Y, group = Vessels.Name)) +
  coord_sf(xlim = xlim, ylim = ylim, expand = FALSE, 
           crs = 4326,
           datum = sf::st_crs(4326), label_graticule = waiver(),
           label_axes = waiver(), ndiscr = 100, default = FALSE,
           clip = "on") +
  annotation_custom(rasterGrob(bluemarble_bg, 
                               width = unit(1,"npc"), 
                               height = unit(1,"npc")), 
                    -Inf, Inf, -Inf, Inf) +
  geom_path(data = shiptracks, group = shiptracks$Vessels.Name, color=pal[shiptracks$Vessels.Name],
            aes(x=X, y=Y), cex=1, show.legend = TRUE) +
  geom_point(data = shiptracks, group = shiptracks$Vessels.Name, color=pal[shiptracks$Vessels.Name], aes(x=X, y=Y), cex=1, show.legend = TRUE) +
    theme(axis.line = element_blank(),
        axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        panel.background = element_blank(),
        panel.border = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        plot.background = element_blank(),
        plot.margin = unit(c(0, 0, 0, 0), "mm"),
        panel.spacing = unit(0, "mm"),
        legend.position = c(-120, -20),
        legend.title = element_text(size = 7), 
        legend.text = element_text(size = 5), 
        legend.key.size = unit(0.01, "npc"))

shipmap

推荐答案

在您运行st_wrap_dateline时,您有一个POINT几何的数据框。点不能跨越日期线,因此没有任何更改。

您需要通过分组和构造来创建LINESTRINGMULTILINESTRING几何的数据框,因此最终每个船舶轨迹一行,而不是具有分组变量的每个船舶位置一行。

st_wrap_dateline将日期行上的对象拆分为MULTILINESTRING个对象。

然后,您可以在ggplot调用中使用geom_sf绘制线条,这些线条将在日期线上拆分为多个部分。

第一步,从曲目创建线:

tracks = shiptracks %>% group_by(Vessels.Name) %>% 
    summarise(do_union=FALSE) %>% st_cast("LINESTRING")

ggplot() + geom_sf(data=tracks,aes(col=Vessels.Name))

现在包装并绘制:

tracks = st_wrap_dateline(tracks)
ggplot() + geom_sf(data=tracks,aes(col=Vessels.Name)) 

(提示:请尽量将您的代码保持在最低限度-我在这方面的第一次尝试失败了,因为您使用的一定是比我已有的更新版本更高的版本,而且您的绘图中众多选项中的一个(我认为是waiver())无法识别。简化每件事有时也会揭示问题所在,或者至少可以更快地找到问题所在。它还鼓励人们回答。当我第一次看到这个代码和它的60行代码时,我不愿意再看下去。)

这篇关于如何对跨越国际日期变更线的路径使用R进行补救的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆