如何利用R Studio的Leaflet包制作多站点30年气温时间序列动画?
用R的Leaflet制作气温时间序列动画的完整方案
看起来你现在是手动逐个年份生成独立地图,这样肯定没法做成连贯的动画效果。咱们一步步来把数据调整成适合动画的格式,再用Leaflet的扩展工具实现时间线动画。
第一步:数据预处理(核心前提)
你的数据是宽格式(每列对应一个年份,比如X1965),而动画需要长格式(一行对应一个站点+单年份的气温记录)。咱们用tidyr和dplyr来转换:
先安装并加载必要工具包:
# 安装未安装的包 install.packages(c("leaflet", "dplyr", "tidyr", "leaflet.extras")) # 加载包 library(leaflet) library(dplyr) library(tidyr) library(leaflet.extras)
接着读取并转换数据结构:
# 读取你的气温数据 Temp53Yrs_df <- read.csv("C:/Users/Sownal/Documents/53YearsTemp.csv") # 转成长格式:把年份列拆分为"年份"和"气温"两列 tidy_temp <- Temp53Yrs_df %>% # 保留经纬度、站点名称等标识列,将所有以X开头的年份列转成行 pivot_longer(cols = starts_with("X"), names_to = "year", values_to = "avg_temp") %>% # 去掉年份名里的X,转成数值型方便后续排序 mutate(year = as.numeric(gsub("X", "", year)))
转换后的数据每行包含lat、long、year、avg_temp,这是实现动画的基础结构。
第二步:创建带时间线的Leaflet动画地图
我们用leaflet.extras包的addTimeline函数添加时间轴控件,实现年份自动切换的动画效果:
# 定义统一的颜色调色板(用所有年份的气温范围做基准,确保颜色映射一致) col_pal <- colorNumeric(palette = "viridis", domain = tidy_temp$avg_temp, reverse = TRUE) # 构建基础地图+动画控件 animated_map <- leaflet(tidy_temp) %>% addTiles() %>% # 添加默认OpenStreetMap底图 # 按年份分组添加站点标记 addCircleMarkers( lat = ~lat, lng = ~long, color = ~col_pal(avg_temp), radius = 15, # 可根据需求调整,比如用~avg_temp*2让半径随气温变化 fillOpacity = 0.7, label = ~paste("年份:", year, "\n平均气温:", avg_temp), group = ~year # 按年份分组,这是动画切换的核心 ) %>% # 添加统一图例 addLegend(pal = col_pal, values = ~avg_temp, position = "bottomleft", title = "平均气温(°C)") %>% # 添加时间线控件 addTimeline( group = ~year, period = 1000, # 切换间隔,单位毫秒(这里1秒切换一次) autoPlay = TRUE, # 自动播放动画 loop = TRUE, # 循环播放 timelineOpts = timelineOptions( format = "%Y", # 年份显示格式 min = min(tidy_temp$year), max = max(tidy_temp$year) ) ) # 显示动画地图 animated_map
第三步:你之前代码的问题排查
你之前的代码手动重复生成单年份地图,主要问题有两个:
- 数据格式不适合动画:宽格式无法直接实现分组切换
- 缺少动画控件:没有利用Leaflet的分组机制和时间线工具实现自动切换
备选方案:用Shiny做交互式动画(更灵活的控制)
如果需要更丰富的交互(比如手动拖动滑块选年份、筛选站点等),可以用Shiny实现:
library(shiny) ui <- fluidPage( leafletOutput("temp_map"), sliderInput("year_slider", "选择年份:", min = min(tidy_temp$year), max = max(tidy_temp$year), value = min(tidy_temp$year), step = 1, animate = animationOptions(interval = 1000, loop = TRUE)) ) server <- function(input, output) { output$temp_map <- renderLeaflet({ # 筛选当前滑块对应的年份数据 current_data <- tidy_temp %>% filter(year == input$year_slider) leaflet(current_data) %>% addTiles() %>% addCircleMarkers( lat = ~lat, lng = ~long, color = ~col_pal(avg_temp), radius = 15, fillOpacity = 0.7, label = ~paste("平均气温:", avg_temp) ) %>% addLegend(pal = col_pal, values = tidy_temp$avg_temp, position = "bottomleft", title = "平均气温(°C)") }) } shinyApp(ui, server)
这个方案会生成带滑块的网页,既可以手动选年份,也能自动播放动画。
内容的提问来源于stack exchange,提问作者shawn
相关产品推荐
相关产品推荐

