You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言跨反子午线绘图方案咨询:替代手动拼接的工具需求

跨反子午线轨迹绘图的R包解决方案

问题说明

需绘制跨180°反子午线的位置轨迹(覆盖东经172°至西经172°范围),当前采用ggplot2+ggOceanMaps时需拆分数据手动拼接,存在对齐误差且操作繁琐,寻求可直接实现该需求的R包及方法。

现有拆分绘图代码

# 创建左半部分经度
m_track$Lon_daily_east <- ifelse(m_track$Lon_daily_new < 0, 
                                 m_track$Lon_daily_new + 360, 
                                 m_track$Lon_daily_new)

# 创建右半部分经度
m_track$Lon_daily_west <- ifelse(m_track$Lon_daily_new > 0, 
                                 m_track$Lon_daily_new - 360, 
                                 m_track$Lon_daily_new)

left <- basemap(limits = c(172.0, 180, -40.0, -15.0), bathymetry = TRUE, legends = FALSE) +
  geom_point(data= m_track, aes(x = Lon_daily_east, y= Lat_daily_new, colour = tf), group = 1, size = 1.4) +
  geom_path(data = m_track, aes(x = Lon_daily_east, y= Lat_daily_new, colour = tf), group = 1, linewidth = 1.2)+
  theme_bw() +
  xlab("Longitude")+ 
  ylab("Latitude")+ 
  labs(colour = "Days Elapsed")+ 
  coord_sf(xlim = c(172.0, 180), ylim = c(-40.0, -15.0), expand = FALSE)+
  theme(legend.position = "NULL",
    plot.margin = margin(t = 25.5, r = 0, b = 25.5, l = 0, unit = "pt")
    )

right <- basemap(limits = c(-180.00, -172, -40.0, -15.0), bathymetry = TRUE, legends = FALSE) +
  geom_point(data= m_track, aes(x = Lon_daily_west, y= Lat_daily_new, colour = tf), group = 1, size = 1.4) +
  geom_path(data = m_track, aes(x = Lon_daily_west, y= Lat_daily_new, colour = tf), group = 1, linewidth = 1.2)+
  theme_bw() +
  xlab("Longitude")+ 
  ylab("Latitude")+ 
  labs(colour = "Days Elapsed")+ 
  theme(
    legend.text = element_text(size = 7),             # 图例文本
    legend.title = element_text(size = 7),
    legend.justification = c("right","bottom"),
    legend.position = c(.52, .05),
    plot.margin = margin(t = 25.5, r = 0, b = 25.5, l = 0, unit = "pt")
  )

示例数据

Date Lon_daily_new Lat_daily_new tf month_d data_group Lon_daily_east Lon_daily_west
34 2019-04-08       177.950       -26.625 34   April          1        177.950       -182.050
35 2019-04-09       178.325       -26.175 35   April          1        178.325       -181.675
36 2019-04-10       178.675       -25.850 36   April          1        178.675       -181.325
37 2019-04-11       179.075       -25.550 37   April          1        179.075       -180.925
38 2019-04-12       179.350       -25.250 38   April          1        179.350       -180.650
39 2019-04-13      -179.925       -24.825 39   April          1        180.075       -179.925
40 2019-04-14      -179.425       -24.275 40   April          1        180.575       -179.425
41 2019-04-15      -179.425       -23.700 41   April          1        180.575       -179.425
42 2019-04-16      -179.375       -23.125 42   April          1        180.625       -179.375
43 2019-04-17      -179.200       -22.750 43   April          1        180.800       -179.200

手动拼接效果

跨反子午线手动拼接绘图示例


可行的解决方案

1. 优化ggOceanMaps+sf:无需拆分数据

利用sf的坐标变换功能处理反子午线,直接在单张图中绘制:

library(sf)
library(ggplot2)
library(ggOceanMaps)

# 将数据转为sf对象,用lon_wrap=180处理跨反子午线问题
m_track_sf <- st_as_sf(m_track, coords = c("Lon_daily_new", "Lat_daily_new"), crs = 4326) %>%
  st_transform(crs = "+proj=longlat +datum=WGS84 +lon_wrap=180")

# 绘制完整轨迹图
basemap(limits = c(172, -172, -40, -15), bathymetry = TRUE, legends = FALSE) +
  geom_sf(data = m_track_sf, aes(colour = tf), size = 1.4) +
  geom_path(data = m_track_sf %>% st_coordinates() %>% as.data.frame() %>% cbind(m_track),
            aes(x = X, y = Y, colour = tf), group = 1, linewidth = 1.2) +
  theme_bw() +
  labs(x = "Longitude", y = "Latitude", colour = "Days Elapsed") +
  coord_sf(xlim = c(172, -172), ylim = c(-40, -15), expand = FALSE) +
  theme(
    legend.text = element_text(size = 7),
    legend.title = element_text(size = 7),
    legend.justification = c("right","bottom"),
    legend.position = c(.52, .05)
  )

2. 使用oce包:原生支持海洋跨子午线绘图

oce是专门的海洋数据处理包,原生支持跨反子午线的地图绘制:

library(oce)

# 设置绘图参数
par(mar = c(3, 3, 1, 1))
# 绘制底图+轨迹
mapPlot(coordinates = list(longitude = m_track$Lon_daily_new, latitude = m_track$Lat_daily_new),
        projection = "+proj=merc +lon_0=180",  # 以180°为中心投影
        longitudelim = c(172, -172), latitudelim = c(-40, -15),
        bathymetry = TRUE, col = "lightblue")
mapPoints(m_track$Lon_daily_new, m_track$Lat_daily_new, col = m_track$tf, pch = 16, cex = 1.4)
mapLines(m_track$Lon_daily_new, m_track$Lat_daily_new, col = m_track$tf, lwd = 1.2)
# 添加图例
legend("bottomright", legend = unique(m_track$tf), col = unique(m_track$tf), pch = 16, lwd = 1.2,
       title = "Days Elapsed", cex = 0.7)

3. ggspatial+ggplot2:灵活自定义底图

结合ggspatial获取在线底图,配合坐标转换实现跨子午线绘图:

library(ggspatial)
library(sf)
library(ggplot2)

# 将经度转换为0-360范围
m_track$Lon_360 <- ifelse(m_track$Lon_daily_new < 0, m_track$Lon_daily_new + 360, m_track$Lon_daily_new)

ggplot(m_track) +
  # 添加水深底图(可替换为其他类型底图)
  annotation_map_tile(type = "stamen_terrain_bg", zoom = 5) +
  # 绘制轨迹点和路径
  geom_path(aes(x = Lon_360, y = Lat_daily_new, colour = tf), linewidth = 1.2) +
  geom_point(aes(x = Lon_360, y = Lat_daily_new, colour = tf), size = 1.4) +
  # 设置x轴范围为东经172°到西经172°(对应0-360范围的172到188)
  coord_sf(xlim = c(172, 188), ylim = c(-40, -15), expand = FALSE, crs = 4326) +
  # 自定义经度标签格式
  scale_x_continuous(breaks = c(172, 180, 188), labels = c("172°E", "180°", "172°W")) +
  theme_bw() +
  labs(x = "Longitude", y = "Latitude", colour = "Days Elapsed") +
  theme(
    legend.text = element_text(size = 7),
    legend.title = element_text(size = 7),
    legend.justification = c("right","bottom"),
    legend.position = c(.52, .05)
  )

内容的提问来源于stack exchange,提问作者R student

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 03:00:53