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
相关产品推荐
相关产品推荐

