优化Shiny + Leaflet性能,用于具有许多“层”的详细地图

16
我想制作一个Shiny应用程序,其中choropleth的着色基于用户可以从中选择的许多可能定量变量之一的数字值。在简单情况下,这很简单,但是当我们有20多个变量时,使用相当详细的形状文件(~ 2300个多边形)时,我不确定最佳实践是什么。
变量可能完全彼此独立,例如“总人口”或“平均温度”,但其中一些将具有时间关系,例如三个或更多时间点上的“总人口”。
我正在使用ABS统计区域2之一的主要形状文件。以下是澳大利亚的人口密度(总人口/面积)以及悉尼的放大视图,以更好地传达我感兴趣的详细程度。
澳大利亚 Australia 悉尼 Sydney 我已经将形状文件读入R,并使用rmapshaper包中的ms_simplify()函数大大减少了复杂性/点数。

就Shiny和leaflet而言,我一直在做以下内容:

  • Before the server object is defined in server.R, I build a primary map object with all the desired 'layers'. That is, a leaflet with numerous addPolygon() calls to define the colouring of each 'layer' (group).

    # 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"
    ) %>% ...
    
  • All bar the first layer is then hidden using hideGroup() so that the initial rendering of the map doesn't look silly.

    hideGroup("layer_1") %>% 
    hideGroup("layer_2") %>% 
    ...
    hideGroup("layer_n")
    
  • In the Shiny app, using radio buttons (layer_selection), the user can select the 'layer' they'd like to see. I use observeEvent(input$layer_selection, {}) to watch the status of the radio button options. To update the plot, I use leafletProxy() and hideGroup() to hide all the groups and then showGroup() to unhide the selected layer.

我很抱歉没有提供可重现的示例。
问题:
  1. How can I optimise my code? I am eager to make it more performant and/or easy to work with. I've found using hideGroup()'s/showGroup() for each layer selection is far faster than using addPolygon() to a blank map, but this causes the app to take a very significant amount of time to load.

  2. Can I change the variable I am colouring the polygons by, without redrawing or adding those polygons again? To clarify, if I have 2 different variables to plot, both using the same shape data, do I have to do 2 distinct addPolygon() calls?

  3. Is there a more automatic way to sensibly colour the polygons for each layer according to a desired palette (from the viridis package?). Right now I'm finding defining a new palette for each variable, rather cumbersome, eg:

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

附加问题

ABS网站上的这个地图是如何工作的?它可以非常详细,同时响应速度也非常快。将Mesh Block的细节与SA2(2310个多边形)进行比较,例如下面的例子:

ABS web based map

1个回答

6
由于您还没有得到任何答案,我会根据一个简单的例子给出一些可能对您有所帮助的东西。
当然,如果您的问题可以重现,那么解决起来会更容易。我猜想从您周围的情况来看,您已经发现了几个相关的问题/请求(关于重新着色多边形),但是似乎在任何版本(leaflet)中都没有真正的解决方案。
通过以下解决方法,您应该能够避免多个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))

有人知道在Shiny和leafletProxy中如何实现这个吗? - Rex Parsons
1
跟进我上面的评论,使用leafletProxy更新fillColor的解决方案在这里 https://github.com/rstudio/leaflet/issues/496#issuecomment-650122985 - Rex Parsons

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接