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

ggplot2中geom_circle动画出现非预期插值圆问题求助

问题描述

我使用R语言的gifski包制作GIF动画:以底部固定红点为圆心绘制圆,圆的半径随移动蓝点的距离变化。其中circle_df.rds仅包含13个时间点的圆数据,gps.rds包含约700个时间点的蓝点数据。我需要仅在动画帧时间与circle_df中的时间点完全匹配时才显示对应圆,但当前动画全程显示插值后的圆,比如11:30:41和11:31:14之间本不该显示圆,却出现了插值生成的圆。

解决方案

问题根源是transition_time()会对所有图层的数据自动进行时间插值,包括圆的图层。要实现仅指定时间点显示圆,需通过以下步骤修正:

  • 提取gps中的所有时间帧,与circle_df做全连接,为非目标时间点的圆半径设为0
  • 在geom_circle的映射中添加条件判断,仅当当前时间属于circle_df的时间集合时,使用真实半径绘制圆,否则半径设为0(等同于不显示)
修改后的可复现代码
## Google maps API
register_google(key="YOURKEY", write=TRUE)

## 读取数据
gps <- readRDS("gps.rds")
sensor <- readRDS("sensor.rds")
circle_df <- readRDS("circle_df.rds")

## 补全所有时间帧的圆数据:非目标时间点半径设为0
full_time_df <- data.frame(time = unique(gps$time))
circle_full <- merge(full_time_df, circle_df, by = "time", all.x = TRUE)
# 填充缺失值:非匹配时间点半径为0,信号强度设为最小值
circle_full$distance_deg <- ifelse(is.na(circle_full$distance_deg), 0, circle_full$distance_deg)
circle_full$signal <- ifelse(is.na(circle_full$signal), -100, circle_full$signal)
# 补全传感器经纬度(确保每个时间点都有圆心坐标)
circle_full <- merge(circle_full, sensor[, c("lon", "lat")], by = c("lon", "lat"), all.x = TRUE)

## 获取卫星底图
cor <- c(mean(gps$lon), mean(gps$lat))
map <- ggmap(get_googlemap(center=cor, zoom=18, maptype="satellite"))

## 构建绘图对象
p <- map +
  geom_point(data=gps, aes(x=lon, y=lat),
             color="blue", size=2, shape=10) +
  geom_point(data=sensor, aes(x=lon, y=lat),
             color="red", fill="white", size=3.4, shape=21) +
  geom_text(data=sensor, aes(x=lon, y=lat, label=ID),
            color="red", fontface="bold", size=2.4, vjust=0.24) +
  ## 仅匹配时间点显示圆
  geom_circle(data=circle_full, aes(x0=lon, y0=lat,
                                  color=signal, 
                                  r=ifelse(time %in% circle_df$time, as.numeric(distance_deg), 0)),
              fill=NA, alpha=0.6, linewidth=0.8) +
  scale_color_gradient(low="dodgerblue", high="red",
                       name=expression("Signal Intensity\n(-100 to 0)"),
                       limits=c(-100,0),
                       guide = guide_colorbar(title.theme=element_text(color="white", size=10),
                                              label.theme = element_text(color = "white", size=10),
                                              barwidth=1, barheight = 5, nbin = 10)) +
  theme(axis.title.x=element_blank(),
        axis.text.x = element_blank(),
        axis.title.y=element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        rect = element_blank(),
        legend.position=c(0.9,0.14),
        plot.margin = unit(c(0, 0, 0, 0), "cm")) +
  transition_time(time) +
  ggtitle('Time:, {frame_time}',
          subtitle = 'Frame {frame} of {nframes}')

## 生成动画
frame <- as.integer((max(gps$time) - min(gps$time)) * 60)
anime <- animate(p, nframes=frame, fps=round(frame/20))

## 保存并预览
anim_save("test.gif", anime) ; anime

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 00:35:33