针对具有多个“图层”的详细地图优化“闪亮+单张”性能

时间:2018-07-31 07:13:47

标签: r shiny gis choropleth r-leaflet

我想制作一个Shiny应用程序,其中,choropleth的颜色基于许多个可能的定量变量之一的数值,用户可以从中选择。在简单的情况下,这很简单,但是我不确定当我们有20多个变量以及非常详细的形状文件(〜2300个多边形)时的最佳做法。

变量可能彼此完全独立,例如“总人口”或“平均温度”,可能无关或无关,但其中一些变量会具有时间关系,例如“总人口”为3或更高。时间点。

ABS Statistical Area 2是我使用的主要shapefile之一。下面,我给出了澳大利亚的人口密度(总人口/区域),并放大了悉尼,以更好地传达我感兴趣的详细程度。

澳大利亚 Australia 悉尼 Sydney

我已经读取了R中的shapefile,并使用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"
    ) %>% 
    

    ...

    # Layer N
    addPolygons(
        data = aus_sa2_areas,
        fillColor = ~palette_layer_n(aus_sa2_areas$var_n),
        smoothFactor = 0.5,
        group = "layer_n"
    ) %>% ...
    
  • 然后使用hideGroup()隐藏第一层的所有栏,以使地图的初始呈现看起来不那么傻。

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

我为缺少可复制的示例表示歉意。

问题

  1. 如何优化代码?我渴望使其性能更高和/或更易于使用。我发现使用hideGroup() / showGroup()进行每个图层选择要比使用addPolygon()进行空白地图绘制要快得多,但这会导致应用花费大量时间加载。

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

  3. 是否有一种更自动的方法,可以根据所需的调色板(从viridis包装中)对每一层的多边形进行合理的着色?现在,我正在为每个变量定义一个新的调色板,这很麻烦,例如:

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

侧问

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

ABS web based map

1 个答案:

答案 0 :(得分:2)

由于您尚未获得任何答案,因此我将基于一个简单的示例发布一些可能对您有所帮助的内容。

如果您的产品具有可复制性,那当然会更容易;我想环顾四周,您已经发现有几个相关的问题/请求(关于为多边形重新着色),而似乎还没有真正的解决方案将其纳入任何版本的传单中。 >

通过以下变通方法,您应该能够避免使用多个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))