如何用R制作雷达降雨时间序列栅格的交互式可视化?
可行方案:制作雷达降雨时间序列交互式绘图
完全可以实现带滚动条/滑块的交互式栅格切换,以下是两种实用方案,解决你之前遇到的工具限制问题:
方案1:Shiny + ggplot2(灵活可控,适合本地/服务器部署)
用Shiny构建带滑块的交互式应用,支持实时切换栅格图层,同时叠加shapefile,样式可高度自定义。
示例代码
library(shiny) library(raster) library(ggplot2) library(sf) # 替换为你的多波段降雨栅格(RasterStack/RasterBrick) r_stack <- stack(replicate(10, raster(matrix(rnorm(10000), 100, 100)))) # 从栅格元数据提取时间标签,这里用模拟名称 names(r_stack) <- paste0("2024-05-01_", sprintf("%02d", 1:10), ":00") # 读取并转换shapefile为sf对象(替换为你的文件路径) shape <- st_read("your_boundary.shp") %>% st_transform(crs = crs(r_stack)) # 确保与栅格坐标系一致 ui <- fluidPage( titlePanel("雷达降雨时间序列"), sidebarLayout( sidebarPanel( sliderInput("time_idx", "选择时间点", min = 1, max = nlayers(r_stack), value = 1, step = 1, # 可选:添加自动播放动画 animate = animationOptions(interval = 800, loop = TRUE)), textOutput("current_time_label") ), mainPanel( plotOutput("rain_plot", height = "600px") ) ) ) server <- function(input, output) { output$current_time_label <- renderText({ paste("当前时间:", names(r_stack)[input$time_idx]) }) output$rain_plot <- renderPlot({ # 提取选中的栅格图层 selected_raster <- r_stack[[input$time_idx]] # 转换为ggplot可用的数据框 raster_df <- as.data.frame(selected_raster, xy = TRUE) colnames(raster_df)[3] <- "rainfall" # 绘制栅格+边界 ggplot() + geom_raster(data = raster_df, aes(x = x, y = y, fill = rainfall)) + geom_sf(data = shape, color = "#2c3e50", fill = NA, linewidth = 0.6) + # 统一颜色比例尺(关键:避免不同图层色阶波动) scale_fill_viridis_c(option = "inferno", limits = c(minValue(r_stack), maxValue(r_stack)), name = "降雨量(mm)", guide = guide_colorbar(title.position = "top")) + coord_sf() + theme_minimal() + theme(plot.title = element_text(hjust = 0.5), legend.position = "bottom") + labs(title = names(r_stack)[input$time_idx]) }) } shinyApp(ui, server)
关键优势
- 完全自定义绘图样式(颜色、字体、布局)
- 支持大栅格数据(可提前降采样优化性能)
- 滑块支持自动播放,适合展示时间序列动态
方案2:Plotly(纯HTML输出,无需服务器)
如果需要生成可嵌入网页的静态交互式文件,用Plotly将所有图层打包成带滑块的HTML,无需依赖Shiny服务器。
示例代码
library(plotly) library(raster) library(sf) # 同方案1的栅格和shapefile准备 r_stack <- stack(replicate(10, raster(matrix(rnorm(10000), 100, 100)))) names(r_stack) <- paste0("2024-05-01_", sprintf("%02d", 1:10), ":00") shape <- st_read("your_boundary.shp") %>% st_transform(crs = crs(r_stack)) # 合并所有时间点的栅格数据为单一数据框 all_raster_data <- lapply(1:nlayers(r_stack), function(i) { df <- as.data.frame(r_stack[[i]], xy = TRUE) colnames(df)[3] <- "rainfall" df$time <- names(r_stack)[i] df }) %>% do.call(rbind, .) # 转换shapefile为Plotly可识别的路径数据 shape_paths <- st_cast(shape, "MULTILINESTRING") %>% st_coordinates() %>% as.data.frame() # 生成Plotly交互式图 p <- ggplot() + geom_raster(data = all_raster_data, aes(x = x, y = y, fill = rainfall)) + geom_path(data = shape_paths, aes(x = X, y = Y, group = L1), color = "#2c3e50") + scale_fill_viridis_c(option = "inferno", limits = c(minValue(r_stack), maxValue(r_stack)), name = "降雨量(mm)") + coord_equal() + theme_minimal() + facet_wrap(~time) # 转换为带滑块的交互式HTML interactive_plot <- ggplotly(p) %>% animation_opts(frame = 800, transition = 0, redraw = FALSE) %>% animation_slider(currentvalue = list(prefix = "时间: ")) %>% layout(legend = list(orientation = "h", y = -0.1)) # 保存为HTML文件 htmlwidgets::saveWidget(interactive_plot, "rainfall_timeseries.html")
注意事项
- 若栅格数据量极大,建议先降采样(用
aggregate(r_stack, fact = 2)),避免HTML文件过大 - 颜色比例尺必须设置统一的
limits,确保不同时间点的降雨量对比一致
关于你之前的工具问题
Leaflet默认更适合地理底图叠加,直接加载多波段栅格会叠加所有图层的像素值,需要用Shiny配合leafletProxy动态替换栅格图层,但上述两种方案更直接满足你的需求。
内容的提问来源于stack exchange,提问作者Maxime auffret
相关产品推荐
相关产品推荐

