针对具有许多"层"的详细地图优化Shiny + Leaflet性能

dcl*_*dcl 12 gis r shiny choropleth r-leaflet

我想创建一个Shiny应用程序,其中等值区的着色基于用户可以从中选择的许多可能的定量变量之一的数值.在简单的情况下,这是直截了当的,但是当我们有20多个变量时,我不确定最佳实践,具有非常详细的形状文件(~2300多边形).

变量可能完全相互独立,例如"总人口"或"平均温度"可能相关或不相关,但其中一些变量将具有时间关系,例如3个或更多时间点的"总人口" .

我使用的主要shapefile之一是ABS统计区2.下面我给出澳大利亚的人口密度(总人口/面积)和放大的悉尼视图,以更好地传达我感兴趣的细节水平.

澳大利亚 澳大利亚 悉尼 悉尼

我已将shapefile读入R中,并使用包中的ms_simplify()函数大大降低了复杂性/点数rmapshaper.

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

  • server定义对象之前server.R,我构建了一个包含所有所需"层"的主要地图对象.也就是说,一个传单,有许多addPolygon()调用来定义每个"层"(组)的颜色.

    # Create main map
    primary_map <- leaflet() %>% 
    addProviderTiles(
        providers$OpenStreetMap.BlackAndWhite,
        options = providerTileOptions(opacity = 0.60)
    ) %>% 
    # Layer 0 (blank)
    addPolygons(
        data = aus_sa2_areas,
        group = "blank"
    ) %>% 
    # Layer 1
    addPolygons(
        data = aus_sa2_areas,
        fillColor = ~palette_layer_1(aus_sa2_areas$var_1),
        smoothFactor = 0.5,
        group = "layer_1"
    ) %>% 
    
    Run Code Online (Sandbox Code Playgroud)

    ...

    # Layer N
    addPolygons(
        data = aus_sa2_areas,
        fillColor = ~palette_layer_n(aus_sa2_areas$var_n),
        smoothFactor = 0.5,
        group = "layer_n"
    ) %>% ...
    
    Run Code Online (Sandbox Code Playgroud)
  • 然后使用隐藏第一层的所有条形图,hideGroup()以便初始渲染地图看起来不傻.

    hideGroup("layer_1") %>% 
    hideGroup("layer_2") %>% 
    ...
    hideGroup("layer_n")
    
    Run Code Online (Sandbox Code Playgroud)
  • 在Shiny应用程序中,使用单选按钮(layer_selection),用户可以选择他们想要查看的"图层".我observeEvent(input$layer_selection, {})用来观看单选按钮选项的状态.要更新绘图,我使用leafletProxy()hideGroup()隐藏所有组,然后showGroup()取消隐藏所选图层.

我为缺乏可重复的例子而道歉.

问题

  1. 如何优化我的代码?我渴望使其更高效和/或更易于使用.我发现使用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
    )
    
    Run Code Online (Sandbox Code Playgroud)

边问题

ABS网站上的这张地图如何运作?它可以非常详细,但响应速度极快.将网格块详细信息与SA2(2310多边形)进行比较,示例如下:

ABS网络地图

Rol*_*ASc 6

由于您还没有得到任何答案,我将根据一个简单的示例发布一些可能对您有所帮助的内容

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

通过以下解决方法,您应该能够避免多个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))
Run Code Online (Sandbox Code Playgroud)