【问题标题】:Shiny R dynamic heatmap with ggplot. Scale and speed issues带有 ggplot 的闪亮 R 动态热图。规模和速度问题
【发布时间】:2018-05-01 16:57:31
【问题描述】:

我正在尝试使用一些公共信息来制作加拿大的热图,以获取一些劳工统计数据。使用来自census 的空间文件和来自Statistics Canada 的数据(这些是不需要深入研究的大型 zip 文件)。下面是一个工作示例,说明了我在区域之间的相对变化很小时遇到的两个问题(尽管时期之间可能存在很大的绝对变化,并且绘制时间很慢。要使其正常工作,您需要下载 .zip来自人口普查链接的文件并将文件解压缩到数据文件夹。

library(shiny)
library(maptools)
library(ggplot2)
require(reshape2)
library(tidyr)
library(maptools)
library(ggplot2)
library(RColorBrewer)


ui <- fluidPage(

  titlePanel("heatmap"),

   # Sidebar with a slider input for year of interest
   sidebarLayout(
      sidebarPanel(
        sliderInput("year",h3("Select year or push play button"),
                    min = 2000, max = 2002, step = 1, value = 2000,
                    animate = TRUE)
      ),

      # Output of the map
      mainPanel(
        plotOutput("unemployment")
      )
   )
)

server <- function(input, output) {
  #to get the spacial data: from file in link above
  provinces<-maptools::readShapeSpatial("data/gpr_000a11a_e.shp")

  data.p<- ggplot2::fortify(provinces, region = "PRUID")
  data.p<-data.p[which(data.p$id<60),]

  #dataframe with same structure as statscan csv after processing
   unem <- runif(10,min=0,max=100)
   unem1 <- unem+runif(1,-10,10)
   unem2 <- unem1+runif(1,-10,10)
   unemployment <- c(unem,unem1,unem2)
   #dataframe with same structure as statscan csv after processing
   X <- data.frame("id" = c(10,11,12,13,24,35,46,47,48,59,
   10,11,12,13,24,35,46,47,48,59,
   10,11,12,13,24,35,46,47,48,59),
              "Unemployment" = unemployment,
              "year" = c(rep(2000,10),rep(2001,10),rep(2002,10))
              )


  plot.data<- reactive({
a<- X[which(X$year == input$year),]
    return(merge(data.p,a,by = "id"))
  })

  output$unemployment <- renderPlot({
    ggplot(plot.data(), 
           aes(x = long, y = lat, 
               group = group , fill =Unemployment)) +
      geom_polygon() +
      coord_equal()
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

任何一个问题的帮助将不胜感激

【问题讨论】:

  • 寻求帮助时,您应该包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出。 “似乎对我不起作用”到底是什么意思?
  • 好的,我会想出一个玩具示例并编辑帖子

标签: r ggplot2 shiny r-leaflet


【解决方案1】:

对于这种类型的动画,使用小册子而不是 ggplot 会快得多,因为小册子只允许您重新渲染多边形,而不是整个地图。

我使用另外两个技巧来加速动画:

  1. 我加入了反应之外的数据。在响应式中,它只是一个简单的子集。请注意,加入可以在应用程序之外完成并作为预处理的 .rds 文件读入。

  2. 我使用 rmapshaper 包简化了多边形,以减少传单的绘制时间。同样,这可以在应用程序之外完成,以减少开始时的加载时间。

如果您使用圆形(即每个省份的质心)而不是多边形,动画可能会更加无缝。圆圈大小可能随失业率值而变化。

注意,您需要使用这种方法的小册子、sf、dplyr 和 rmapshaper 包。

library(shiny)
library(dplyr)
library(leaflet)
library(sf)
library(rmapshaper)

ui <- fluidPage(

  titlePanel("heatmap"),

  # Sidebar with a slider input for year of interest
  sidebarLayout(
    sidebarPanel(
      sliderInput("year",h3("Select year or push play button"),
                  min = 2000, max = 2002, step = 1, value = 2000,
                  animate = TRUE)
    ),

    # Output of the map
    mainPanel(
      leafletOutput("unemployment")
    )
  )
)

server <- function(input, output) {
  #to get the spacial data: from file in link above
  data.p <- sf::st_read("input/gpr_000a11a_e.shp") %>% 
    st_transform(4326) %>%
    rmapshaper::ms_simplify()
  data.p$PRUID <- as.character(data.p$PRUID) %>% as.numeric
  data.p <- data.p[which(data.p$PRUID < 60),]

  lng.center <- -99
  lat.center <- 60
  zoom.def <- 3

  #dataframe with same structure as statscan csv after processing
  unem <- runif(10,min=0,max=100)
  unem1 <- unem+runif(1,-10,10)
  unem2 <- unem1+runif(1,-10,10)
  unemployment <- c(unem,unem1,unem2)
  #dataframe with same structure as statscan csv after processing
  X <- data.frame("id" = c(10,11,12,13,24,35,46,47,48,59,
                           10,11,12,13,24,35,46,47,48,59,
                           10,11,12,13,24,35,46,47,48,59),
                  "Unemployment" = unemployment,
                  "year" = c(rep(2000,10),rep(2001,10),rep(2002,10))
  )

  data <- left_join(data.p, X, by = c("PRUID"= "id"))

  output$unemployment <- renderLeaflet({
    leaflet(data = data.p) %>%
      addProviderTiles("OpenStreetMap.Mapnik", options = providerTileOptions(opacity = 1), group = "Open Street Map") %>%
      setView(lng = lng.center, lat = lat.center, zoom = zoom.def) %>%
      addPolygons(group = 'base', 
                  fillColor = 'transparent', 
                  color = 'black',
                  weight = 1.5)  %>%
      addLegend(pal = pal(), values = X$Unemployment, opacity = 0.7, title = NULL,
                position = "topright")
  })

  get_data <- reactive({
    data[which(data$year == input$year),]
  })

  pal <- reactive({
    colorNumeric("viridis", domain = X$Unemployment)
  })

  observe({
    data <- get_data()
    leafletProxy('unemployment', data = data) %>%
      clearGroup('polygons') %>%
      addPolygons(group = 'polygons', 
                  fillColor = ~pal()(Unemployment), 
                  fillOpacity = 0.9,
                  color = 'black',
                  weight = 1.5)
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

【讨论】:

    【解决方案2】:

    我没有发现绘制时间过长,大约 2-3 秒,这对于 2.4mb 的 shapefile 来说似乎是正确的。无论如何,它需要的时间与在我机器上的应用程序中一样长。

    要保持恒定的颜色渐变,您可以在 scale_fill_gradient 中指定限制,尽管您的地图发生了变化,但仍将保持相同的渐变:

    output$unemployment <- renderPlot({
      ggplot(plot.data(), 
           aes(x = long, y = lat, 
               group = group , fill =Unemployment)) +
        geom_polygon() +
        scale_fill_gradient(limits=c(0,100)) +
        coord_equal()
    })
    

    【讨论】:

    • 你知道加快绘制时间的方法吗?当它淡入淡出时,你会失去大部分意义,使变化更难被发现。
    • 我同意 - 较慢的动画使得很难看到过渡。我尝试了一些想法,比如预先绘制大部分情节,然后在选择年份后只添加填充层,但没有什么太大的不同。我的理解是,ggplot 在渲染具有许多层或大量数据的图时并不是非常快。也许你最好的选择是尝试其他更快的绘图例程 - 也许ggvis
    猜你喜欢
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-09
    • 2021-08-21
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多