ggplot 创建带箭头的地图

ggplot create map with arrows

我有这样一个数据框

id    lon    lat
1  A -69.5 -58.5
2  A -69.5 -58.5
3  A -69.5 -57.5
4  A -68.5 -57.5
5  A -68.5 -57.5
6  A -68.5 -57.5
7  A -66.5 -57.5
8  A -68.5 -56.5
9  A -68.5 -56.5
10 A -67.5 -56.5
11 A -65.5 -56.5
12 A -65.5 -56.5
13 A -65.5 -55.5
14 A -62.5 -54.5
15 B -177 -52.5
16 B -178 -50.5
17 B -179 -48.5
18 B 179 -47.5
19 B 178 -46.5
20 B 177 -46.5

我想制作一张 A 和 B 位置的地图,由定向线连接。然而,当 ids 穿过太平洋时(lon=-180 -> lon=+180),我得到一个穿过整个图形的箭头,如下所示。

这是我正在使用的代码

worldmap = map_data("world")

ggplot(test, aes(x = lon, y=lat, colour = factor(id))) +
  geom_polygon(data=worldmap,center=180,aes(x=long, y=lat, group=group), fill="black",colour="black") +
  xlab("") +ylab("")+theme(axis.text=element_blank(),axis.ticks=element_blank())+ theme(panel.background = element_rect(fill = 'white', colour = 'black')  ,panel.grid.major = element_blank(),panel.grid.minor = element_blank())+
  geom_path(size =2,arrow = arrow(angle=30,length = unit(0.6, "inches")))

我该如何解决?

谢谢

我想这取决于您认为 "right" 想做什么。我决定通过在地图边缘添加点,然后创建一个 "sequence" 指示器,以便 ggplot 知道要连接哪些线,将穿过 glob 的路径分成两段。这是您的示例数据的转换

test2 <- do.call(rbind, lapply(split(test, test$id), function(x) {
    cp <- cumsum(c(FALSE, diff(x$lon)>250))
    xx<-split(x, cp)
    xx<-Map(cbind, xx, seq=seq_along(xx))
        Reduce(function(a,b) {
            lasta<-a[nrow(a),]
            firstb<-b[1,]
            lasta$lon <- 180*sign(lasta$lon)
            firstb$lon <- 180*sign(firstb$lon)
            lasta$lat <- mean(lasta$lat, firstb$lat)
            firstb$lat <- lasta$lat
            rbind(a,lasta, firstb,b)        
        }, xx)
}))

tail(test2)
#       id  lon   lat seq
# B.17   B -179 -48.5   1
# B.171  B -180 -48.5   1
# B.18   B  180 -48.5   2
# B.181  B  179 -47.5   2
# B.19   B  178 -46.5   2
# B.20   B  177 -46.5   2

在这里您可以看到我们将 B 行分成了两个序列。那如果我们用组审美

geom_path(aes(group=interaction(id, seq)), ...)

那么 R 将只连接属于同一 id/seq 组的那些点。这将防止线路越过海洋。但是,因为我们为该组绘制了两条线而不是一条线,所以无法只为其中一个线段转动箭头。您可能想找到另一种方式来指示 start/end.