我在
ggplot2
中创建了一个动画图,可视化昼夜物种随时间的 GPS 轨迹。为了提高可视化效果,我想叠加一个半透明层,该层会根据白天或夜晚动态变化。我不想使用静态值,而是使用实际的太阳高度。我使用 suncalc
包补充了太阳位置的数据集。下面可以找到带有虚拟数据的可重现示例。谁能帮助我朝正确的方向前进?
library(ggplot2)
library(gganimate)
library(sf)
library(suncalc)
library(ggspatial)
library(gifski)
library(prettymapr)
# sample data
set.seed(123)
gps_data_sf <- data.frame(
IMEI = rep(35664665, 300),
Pick.Time = seq.POSIXt(as.POSIXct("2024-08-13 00:00:00"), by = "15 mins", length.out = 300),
Longitude = runif(300, 2.7, 2.8),
Latitude = runif(300, 51.1, 51.2),
Bird = rep("Bird A", 300)
)
# add sun height
gps_data_sf$sunheight <- mapply(function(lat, lon, time) {
sun_position <- getSunlightPosition(date = time, lat = lat, lon = lon)
return(sun_position$altitude)
}, gps_data_sf$Latitude, gps_data_sf$Longitude, gps_data_sf$Pick.Time)
# Convert to sf
gps_data_sf <- st_as_sf(gps_data_sf, coords = c("Longitude", "Latitude"), crs = 4326)
# animate
animated_plot <- ggplot() +
annotation_map_tile(type = "osm", zoom = 12) +
geom_sf(data = gps_data_sf, aes(geometry = geometry, color = Bird, group = Bird), size = 5, alpha = 0.8) +
labs(
title = "Movement",
subtitle = "Time: {frame_time}",
x = "Longitude",
y = "Latitude"
) +
transition_time(Pick.Time) +
ease_aes('linear')
# Render
animate(animated_plot, nframes = 100, fps = 10, width = 800, height = 600, renderer = gifski_renderer())
使用
geom_rect
以及 scale_fill_gradient
,可以创建您想要实现的外观。
首先,我把数据和分组移到了
ggplot
,这样就可以被geom_rect
继承了。
当用 sf 调用
geom_rect
时,如果你想填充整个图,可以使用 -Inf
到 Inf
。我在这一层任意使用了 0.4 的 alpha。
最后,使用
scale_fill_gradient
创建高低颜色渐变来模拟太阳。 (我用黑色和黄色表示白天和黑夜。)
对
geom_sf
的调用与您的问题中的相同,减去移至 ggplot()
的参数(data
和 group
)。
# animate
animated_plot <- ggplot(gps_data_sf, group = Bird) + # move data and grouping to ggplot
annotation_map_tile(type = "osm", zoom = 12) +
geom_sf(aes(geometry = geometry, color = Bird),
size = 5, alpha = 0.8) +
geom_rect(xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, # add color space
aes(fill = sunheight), alpha = .4) +
scale_fill_gradient(low = "black", high = "yellow") + # specify colors
labs(
title = "Movement", subtitle = "Time: {frame_time}",
x = "Longitude", y = "Latitude") +
transition_time(Pick.Time) + ease_aes('linear')
一些图像,以便您可以看到渐变叠加如何变化(这是凌晨 3 点和上午 10 点)