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

如何在gganimate中正确动绘同一日期下的多个R语言船舶点位

太平洋船舶航线动画点位缺失问题解决

问题背景

正在制作太平洋区域船舶航线动画,数据集包含ship(船舶ID)、lat(纬度)、lon(经度)、datetime(时间)字段。静态船舶路径图显示正常,但使用gganimate生成的GIF动画出现部分点位丢失,两者路径存在明显差异:

静态船舶路径图
船舶路径GIF动画

数据集示例

shiplatlondatetime
38291449.22597-124.81412022-02-04
35136454.16689-179.92732022-02-22
............

推测原因

同一datetime下,同一ship的多个经纬度点位仅被显示一个,导致点位缺失。

现有代码

静态图代码

map1 <- ggplot() +
  geom_polygon(data=mapWorld, aes(x=long, y=lat, group=group), 
                              color= "darkolivegreen", 
                              fill="darkolivegreen") +
   geom_path(data = BOATS, aes(x=lon, 
                               y = lat,
                               group = ship id,
                               color = factor(ship)),
                               size = 1.5, show.legend = FALSE) +
  geom_point(data = BOATS, aes(lon, 
                               lat,
                               group = ship,
                               color = factor(ship)), 
                               alpha = 1, size = 2, shape = 21) +
  
 coord_sf(xlim=c(-180, -115), ylim=c(27,62), expand = FALSE) +
 labs(x="Longitude", 
      y="Latitude") +
 scale_colour_brewer(palette = "Dark2") +
 guides(colour = guide_legend(nrow = 3, 
                              byrow = TRUE, 
                              override.aes = list(size=5))) +
 mapTheme
  
map1

动画代码

library(gganimate)
library(gifski)

map1.animation =  map1 + 
                  transition_reveal(along = datetime) + 
                  ease_aes('linear') + 
                  enter_fade() + 
                  exit_fade() 
                
animate(map1.animation, fps = 30,
                        nframes = 360, 
                        width = 1071, 
                        height = 715)


anim_save("Boat Path.gif")

解决方案

问题根源

transition_reveal会对每个分组(ship)的datetime进行去重处理,同一时间点的多个点位被合并显示为一个;另外静态代码中geom_path的group = ship id存在语法问题(字段名带空格易引发错误)。

具体修复步骤

1. 预处理数据集,给同时间同船舶的点位添加唯一标识

通过给同一ship和datetime的记录添加微小时间差,让transition_reveal能识别每个独立点位:

library(dplyr)
# 先统一字段名(如果原字段名是"ship id",先重命名为ship_id避免空格问题)
BOATS <- BOATS %>%
  rename(ship_id = `ship id`) %>% 
  group_by(ship_id, datetime) %>%
  mutate(time_seq = row_number()) %>%
  ungroup() %>%
  # 给同一时间点的点位添加微小时间偏移,确保每个点位都能被过渡显示
  mutate(reveal_time = as.numeric(datetime) + time_seq/1000)

2. 修改静态图和动画代码

修正分组逻辑,使用新的reveal_time作为过渡依据:

# 修正后的静态图代码
map1 <- ggplot() +
  geom_polygon(data=mapWorld, aes(x=long, y=lat, group=group), 
               color= "darkolivegreen", fill="darkolivegreen") +
  geom_path(data = BOATS, aes(x=lon, y = lat, group = ship_id, color = factor(ship_id)),
            size = 1.5, show.legend = FALSE) +
  # 用interaction(ship_id, time_seq)确保每个点位都是独立分组
  geom_point(data = BOATS, aes(lon, lat, group = interaction(ship_id, time_seq), color = factor(ship_id)), 
             alpha = 1, size = 2, shape = 21) +
  coord_sf(xlim=c(-180, -115), ylim=c(27,62), expand = FALSE) +
  labs(x="Longitude", y="Latitude") +
  scale_colour_brewer(palette = "Dark2") +
  guides(colour = guide_legend(nrow = 3, byrow = TRUE, override.aes = list(size=5))) +
  mapTheme

# 修正后的动画代码
map1.animation = map1 + 
  transition_reveal(along = reveal_time) + 
  ease_aes('linear') + 
  enter_fade() + 
  exit_fade() 

animate(map1.animation, fps = 30, nframes = 360, width = 1071, height = 715)
anim_save("Boat Path.gif")

3. 替代方案:使用transition_time保留所有点位

如果不需要路径逐步绘制的效果,改用transition_time配合shadow_mark可以更简单地保留所有历史点位,同时显示当前时间的全部点位:

map1.animation = map1 + 
  transition_time(datetime) + 
  # 保留所有过去的点位,不显示未来点位
  shadow_mark(past = TRUE, future = FALSE) +
  ease_aes('linear')

animate(map1.animation, fps = 30, nframes = 360, width = 1071, height = 715)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 00:40:58