闪亮的R动态热图与ggplot。规模和速度问题

时间:2018-05-01 16:57:32

标签: r ggplot2 shiny r-leaflet

我正在尝试使用一些公共信息来制作加拿大的热图来进行一些劳动力统计。使用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)

非常感谢任何有关这两个问题的帮助

2 个答案:

答案 0 :(得分:2)

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

我使用其他两个技巧来加速动画:

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

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

  3. 如果使用圆(即每个省的质心)而不是多边形,动画可能会更加无缝。圈数可能因失业率而异。

    注意,这种方法需要传单,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)
    

    enter image description here

答案 1 :(得分:0)

我没有发现绘图时间在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()
})