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

求助:使用R的tiler包为Leaflet仪表盘创建栅格瓦片失败

问题与解决方案

需求说明

制作flexdashboard仪表盘时,希望通过Leaflet加载本地栅格瓦片替代多边形图层以提升渲染速度。使用R的tiler包将多边形数据先栅格化再生成多缩放级别的瓦片,每组瓦片对应不同的SID79分组,但当前代码运行失败,期望效果为将下图中的多边形替换为瓦片图层:
多边形版本的期望效果

原错误代码

---
title: "try"
date: "`r Sys.Date()`"
output:
  flexdashboard::flex_dashboard:
    orientation: rows 
    vertical_layout: fill
runtime: shiny
---
  
```{r setup, include = FALSE}
knitr::opts_chunk$set(echo=FALSE)
library(flexdashboard)
library(shiny)
library(tidyverse)
library(sf)
library(leaflet)
library(stars)
library(tiler)

pdf(NULL)


nc <- st_read(system.file("shape/nc.shp", package="sf")) %>% st_transform(4326)
subset <- nc %>% filter(SID74 <=5)
    
  # map
  splitField <- "SID79"
years <-  unique(subset[[splitField]])
subset$SID74 <- as.character(subset$SID74)

for (i in 1:length(years)) {
  tmp <- subset[subset[[splitField]] == years[i], ]
  assign(paste0("year", i), tmp)
}
Map

Row

Map

colour6 <- tibble(
    numbers = c("0", "1", "2", "3", "4","5"),
    Color = c('#FFFF33',  '#00CC99', '#006633' , '#99CC99', 
           '#6699CC','#CC9900'))
  
  m1 <- leaflet() %>% 
    setView(lng = -79.5, lat = 36,zoom =7) %>% 
    addTiles(group = "OSM (default)")
  
  for (i in 1:length(years)) {
      dat <- get(paste0("year",i))
       dat_col <- merge( x =dat, y =colour6, by.x ="SID74", by.y="numbers")
       
       ras <- st_rasterize(dat_col[,"numbers"], dx= 100, dy = 100)
       ras4326 <- st_warp(ras, crs = st_crs(4326))
       
       # create subfolders in existing path
       dir.create(file.path("./", i), showWarnings = FALSE)
       
        tile_dir <- file.path(paste0("./",i))
        tiles <- tile(ras4326, tile_dir, "0-3", col = colour6$Color)

        m1 <- m1 %>% addTiles(tiles,
                   group = paste0(i),
                   options = tileOptions(opacity = 0.8))
  }

  m1 <- m1 %>%   addLayersControl(
      baseGroups = c("OSM"),
      options = layersControlOptions(collapsed = FALSE),
      overlayGroups  =  unique(years))  %>%
    addLegend(colors = colour6$Color, labels = colour6$numbers)

renderLeaflet({ 
  m1
})

## 问题分析
1. **栅格分辨率不合理**:`st_rasterize`中`dx=100, dy=100`对应经纬度CRS(4326)下的100度,分辨率过大导致栅格无有效数据
2. **瓦片路径错误**:`addTiles`需要的是瓦片的访问路径,`tiler::tile`返回的是本地目录,需转换为相对URL格式
3. **栅格化字段错误**:栅格化时应使用颜色对应的数值字段,而非合并后的`numbers`字段
4. **变量管理低效**:用`assign`生成多个变量不如用列表存储分组数据更简洁可靠

## 修正后的完整代码
```yaml
---
title: "Tile-based Leaflet Dashboard"
date: "`r Sys.Date()`"
output:
  flexdashboard::flex_dashboard:
    orientation: rows 
    vertical_layout: fill
runtime: shiny
---
  
```{r setup, include = FALSE}
knitr::opts_chunk$set(echo=FALSE)
library(flexdashboard)
library(shiny)
library(tidyverse)
library(sf)
library(leaflet)
library(stars)
library(tiler)

# 避免PDF设备冲突
pdf(NULL)

# 加载并预处理数据
nc <- st_read(system.file("shape/nc.shp", package="sf")) %>% st_transform(4326)
subset <- nc %>% filter(SID74 <=5)
splitField <- "SID79"
years <- unique(subset[[splitField]])
subset$SID74 <- as.character(subset$SID74)

# 用列表存储分组数据,替代assign
year_list <- split(subset, subset[[splitField]])

# 颜色映射表
colour6 <- tibble(
  numbers = c("0", "1", "2", "3", "4","5"),
  Color = c('#FFFF33',  '#00CC99', '#006633' , '#99CC99', '#6699CC','#CC9900')
)
Map

Row

Map

renderLeaflet({
  m <- leaflet() %>% 
    setView(lng = -79.5, lat = 36, zoom =7) %>% 
    addTiles(group = "OSM (default)")
  
  # 遍历每个年份分组生成瓦片并添加图层
  for (i in seq_along(year_list)) {
    dat <- year_list[[i]]
    current_year <- names(year_list)[i]
    
    # 合并颜色映射
    dat_col <- merge(dat, colour6, by.x ="SID74", by.y="numbers")
    
    # 栅格化:使用合理的经纬度分辨率(0.01度,约1公里)
    # 基于SID74的数值栅格化,后续用颜色映射匹配
    ras <- st_rasterize(dat_col["SID74"], dx = 0.01, dy = 0.01)
    
    # 创建瓦片存储目录
    tile_dir <- file.path("tiles", current_year)
    dir.create(tile_dir, recursive = TRUE, showWarnings = FALSE)
    
    # 生成瓦片:指定颜色映射,缩放级别设为7-10(适配初始视图)
    tile(ras, 
         tile_dir, 
         zoom = "7-10", 
         col = colour6$Color,
         breaks = as.integer(colour6$numbers))
    
    # 本地瓦片的URL路径格式:用相对路径指向瓦片目录
    tile_url <- file.path(".", tile_dir, "{z}/{x}/{y}.png")
    
    # 添加瓦片图层
    m <- m %>% addTiles(urlTemplate = tile_url,
                        group = current_year,
                        options = tileOptions(opacity = 0.8, tms = FALSE))
  }
  
  # 添加图层控制和图例
  m %>% 
    addLayersControl(
      baseGroups = c("OSM (default)"),
      overlayGroups = names(year_list),
      options = layersControlOptions(collapsed = FALSE)
    ) %>%
    addLegend(colors = colour6$Color, labels = colour6$numbers)
})
## 关键修正点
1. **栅格分辨率调整**:将`dx`和`dy`设为`0.01`(经纬度下的0.01度,适配地图缩放级别)
2. **瓦片路径处理**:生成相对URL格式的瓦片路径,确保Leaflet能正确加载本地瓦片
3. **颜色映射匹配**:在`tile`函数中通过`breaks`参数将数值与颜色对应
4. **数据结构优化**:用`split`生成列表存储分组数据,替代`assign`提升代码可读性
5. **缩放级别适配**:将瓦片缩放级别设为`7-10`,匹配初始地图视图的缩放范围

内容的提问来源于stack exchange,提问作者jaykay
相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 22:58:13