为包含许多 'layers' 的详细地图优化 Shiny + Leaflet 性能

Optimising Shiny + Leaflet performance for detailed maps with many 'layers'

我想制作一个闪亮的应用程序,其中等值线图的着色基于用户可以 许多 可能的定量变量之一的数值 select从。在简单的情况下,这很简单,但是当我们有 20 多个变量且具有非常详细的形状文件(~2300 个多边形)时,我不确定最佳实践。

变量之间可能完全独立,例如 'Total Population' 或 'Average Temperature',这可能相关也可能不相关,但其中一些变量将具有时间关系,例如 'Total Population' 在 3 个或更多时间点。

我使用的主要 shapefile 之一是 ABS Statistical Area 2。下面我给出了澳大利亚的人口密度(总数 population/area)和悉尼的放大视图,以更好地表达我感兴趣的细节水平。

澳大利亚 悉尼

我已将 shapefile 读入 R 并使用 rmapshaper 包中的 ms_simplify() 函数大大减少了点的 complexity/number。

现在就 Shiny 和传单而言,这就是我一直在做的事情:

对于缺少可重现的示例,我深表歉意。

问题

  1. 如何优化我的代码?我渴望让它更高效 and/or 易于使用。我发现对每一层 selection 使用 hideGroup()'s/showGroup() 比对空白地图使用 addPolygon() 快得多,但这会导致应用程序采取加载时间非常长。

  2. 我可以更改为多边形着色的变量,而无需重新绘制或再次添加这些多边形吗?澄清一下,如果我有 2 个不同的变量要绘制,都使用相同的形状数据,我是否必须执行 2 个不同的 addPolygon() 调用?

  3. 是否有更自动的方法根据所需的调色板(来自 viridis 包?)为每一层的多边形着色。现在我发现为每个变量定义一个新的调色板,相当麻烦,例如:

    palette_layer_n <- colorNumeric(
        palette = "viridis",
        domain = aus_sa2_areas$aus_sa2_areas$var_n
    )
    

附带问题

ABS 网站上的 this map 如何运作?它可以非常详细,但响应速度极快。将网格块细节与 SA2(2310 个多边形)进行比较,示例如下:

由于您还没有得到任何答案,我将 post 基于一个 简单示例 的一些可能对您有帮助的事情。

如果你的是可复制的当然会更容易;我想环顾四周你已经看到有几个相关的问题/请求(关于重新着色多边形),而似乎还没有真正的解决方案已经进入任何版本(传单)。

通过下面的解决方法,您应该能够避免多个 addPolygons 并且可以覆盖任意数量的变量(现在我只是将一个变量硬编码到 modFillCol尽管打电话)。

library(leaflet)
library(maps)
library(viridis)

mapStates = map("state", fill = TRUE, plot = FALSE)

# regarding Question 3 - the way you set the domain it looks equivalent
# to just not setting it up front, i.e. domain = NULL
myPalette <- colorNumeric(
  palette = "viridis",
  domain = NULL
)

mp <- leaflet(data = mapStates) %>%
  addTiles() %>%
  addPolygons(fillColor = topo.colors(10, alpha = NULL), stroke = FALSE)

# utility function to change fill color
modFillCol <- function(x, var_x) {
  cls <- lapply(x$x$calls, function(cl) {
    if (cl$method == "addPolygons") {
      cl$args[[4]]$fillColor <- myPalette(var_x)
    }
    cl
  })
  x$x$calls <- cls
  x
}

# modify fill color depending on the variable, in this simple example
# I just use the number of characters of the state-names
mp %>%
  modFillCol(nchar(mapStates$names))