使用R闪亮集成时间序列图和传单图

Kev*_*vin 8 r dygraphs leaflet shiny

我的数据/结果包含地理编码位置(纬度/经度)和我希望使用R闪亮进行交互的日期/时间戳.我创建了R闪亮的应用程序,其中包含几个传单映射(传单R包),还包含时间序列图(dygraphs R包).我知道如何同步不同的dygraphs(https://rstudio.github.io/dygraphs/gallery-synchronization.html),但不知道如何将它同步到传单地图.我的问题是如何最好地将所有图表链接在一起,所以当我在传单地图上选择一个区域或在dygraph时间序列图上选择一段时间时,其他图表都会更新以仅显示过滤后的数据?

有人认为我有一个传单插件,但不知道如何使用R /闪亮来做到这一点?例如,我看到一些传单插件提供了动画包含日期/时间信息的地图的功能(http://apps.socib.es/Leaflet.TimeDimension/examples/).另一个问题是有没有任何文档/示例显示如何使用R闪亮的传单插件?

我认为可以提取从时间序列图(dygraph)中选择的时间/日期,但不确定是否/如何提取R闪亮的传单地图上显示的区域.我的最后一个问题是,我是否可以提取显示传单地图的区域,因此我可以更新时间序列图.

提前感谢任何有关如何使用R闪亮将传单映射与时间序列图(即dygraph)耦合的建议!

tim*_*lio 11

这可能是一个持续的讨论,而不是一个单一的答案.

幸运的是,你的问题涉及htmlwidgets由RStudio创建的Shiny.他们采取额外的努力,以闪亮的通信整合到两个dygraphsleaflet.对于许多其他人来说情况并非如此htmlwidgets.有关htmlwidgetShiny之外的内部通信的更广泛讨论,我建议遵循此Github问题.

第1部分 - 传单控制图

作为我的第一个例子,我们将leaflet控制dygraphs,所以点击墨西哥的州将把dygraph情节限制在那个状态.我应该赞扬这三个例子.

  1. Kyle Walker的Rpub Mexico Choropleth Leaflet
  2. 传单包含在传单中
  3. 墨西哥的Diego Valle Crime项目

R代码

  # one piece of an answer to this StackOverflow question
  #  http://stackoverflow.com/questions/31814037/integrating-time-series-graphs-and-leaflet-maps-using-r-shiny

  # for this we'll use Kyle Walker's rpubs example
  #   http://rpubs.com/walkerke/leaflet_choropleth
  # combined with data from Diego Valle's crime in Mexico project
  #   https://github.com/diegovalle/mxmortalitydb

  # we'll also build on the shiny example included in leaflet
  #  https://github.com/rstudio/leaflet/blob/master/inst/examples/shiny.R

  library(shiny)
  library(leaflet)
  library(dygraphs)
  library(rgdal)

  # let's build this in advance so we don't download the
  #    data every time
  tmp <- tempdir()
  url <- "http://personal.tcu.edu/kylewalker/data/mexico.zip"
  file <- basename(url)
  download.file(url, file)
  unzip(file, exdir = tmp)
  mexico <- {
    readOGR(dsn = tmp, layer = "mexico", encoding = "UTF-8")
    #delete our files since no longer need
    on.exit({unlink(tmp);unlink(file)})
  }
  pal <- colorQuantile("YlGn", NULL, n = 5)

  leaf_mexico <- leaflet(data = mexico) %>%
    addTiles() %>%
    addPolygons(fillColor = ~pal(gdp08), 
                fillOpacity = 0.8, 
                color = "#BDBDC3", 
                weight = 1,
                layerId = ~id)

  # now let's get our time series data from Diego Valle
  crime_mexico <- jsonlite::fromJSON(
    "https://rawgit.com/diegovalle/crimenmexico.diegovalle.net/master/assets/json/states.json"
  )

  ui <- fluidPage(
    leafletOutput("map1"),
    dygraphOutput("dygraph1",height = 200),
    textOutput("message", container = h3)
  )

  server <- function(input, output, session) {
    v <- reactiveValues(msg = "")

    output$map1 <- renderLeaflet({
      leaf_mexico
    })

    output$dygraph1 <- renderDygraph({
      # start dygraph with all the states
      crime_wide <- reshape(
        crime_mexico$hd[,c("date","rate","state_code"),drop=F],
        v.names="rate",
        idvar = "date",
        timevar="state_code",
        direction="wide"
      )
      colnames(crime_wide) <- c("date",as.character(mexico$state))
      rownames(crime_wide) <- as.Date(crime_wide$date)
      dygraph(
        crime_wide[,-1]
      )
    })

    observeEvent(input$map1_shape_mouseover, {
      v$msg <- paste("Mouse is over shape", input$map1_shape_mouseover$id)
    })
    observeEvent(input$map1_shape_mouseout, {
      v$msg <- ""
    })
    observeEvent(input$map1_shape_click, {
      v$msg <- paste("Clicked shape", input$map1_shape_click$id)
      #  on our click let's update the dygraph to only show
      #    the time series for the clicked
      state_crime_data <- subset(crime_mexico$hd,state_code == input$map1_shape_click$id)
      rownames(state_crime_data) <- as.Date(state_crime_data$date)
      output$dygraph1 <- renderDygraph({
        dygraph(
          xts::as.xts(state_crime_data[,"rate",drop=F]),
          ylab = paste0(
            "homicide rate ",
            as.character(mexico$state[input$map1_shape_click$id])
          )
        )
      })
    })
    observeEvent(input$map1_zoom, {
      v$msg <- paste("Zoom changed to", input$map1_zoom)
    })
    observeEvent(input$map1_bounds, {
      v$msg <- paste("Bounds changed to", paste(input$map1_bounds, collapse = ", "))
    })

    output$message <- renderText(v$msg)
  }

  shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)

第2部分dygraph控制传单+第1部分传单控制图

# one piece of an answer to this StackOverflow question
#  http://stackoverflow.com/questions/31814037/integrating-time-series-graphs-and-leaflet-maps-using-r-shiny

# for this we'll use Kyle Walker's rpubs example
#   http://rpubs.com/walkerke/leaflet_choropleth
# combined with data from Diego Valle's crime in Mexico project
#   https://github.com/diegovalle/mxmortalitydb

# we'll also build on the shiny example included in dygraphs
#  https://github.com/rstudio/leaflet/blob/master/inst/examples/shiny.R

library(shiny)
library(leaflet)
library(dygraphs)
library(dplyr)
library(rgdal)

# let's build this in advance so we don't download the
#    data every time
tmp <- tempdir()
url <- "http://personal.tcu.edu/kylewalker/data/mexico.zip"
file <- basename(url)
download.file(url, file)
unzip(file, exdir = tmp)
mexico <- {
  #delete our files since no longer need
  on.exit({unlink(tmp);unlink(file)})  
  readOGR(dsn = tmp, layer = "mexico", encoding = "UTF-8")
}

# now let's get our time series data from Diego Valle
crime_mexico <- jsonlite::fromJSON(
  "https://rawgit.com/diegovalle/crimenmexico.diegovalle.net/master/assets/json/states.json"
)

# instead of the gdp data, let's use mean homicide_rate
#   for our choropleth
mexico$homicide <- crime_mexico$hd %>%
  group_by( state_code ) %>%
  summarise( homicide = mean(rate) ) %>%
  ungroup() %>%
  select( homicide ) %>%
  unlist


pal <- colorBin(
  palette = RColorBrewer::brewer.pal(n=9,"YlGn")[-(1:2)]
  , domain = c(0,50)
  , bins =7
)

popup <- paste0("<strong>Estado: </strong>", 
                      mexico$name, 
                      "<br><strong>Homicide Rate: </strong>", 
                      round(mexico$homicide,2)
          )

leaf_mexico <- leaflet(data = mexico) %>%
  addTiles() %>%
  addPolygons(fillColor = ~pal(homicide), 
              fillOpacity = 0.8, 
              color = "#BDBDC3", 
              weight = 1,
              layerId = ~id,
              popup = popup
              )


ui <- fluidPage(
  leafletOutput("map1"),
  dygraphOutput("dygraph1",height = 200),
  textOutput("message", container = h3)
)

server <- function(input, output, session) {
  v <- reactiveValues(msg = "")

  output$map1 <- renderLeaflet({
    leaf_mexico
  })

  output$dygraph1 <- renderDygraph({
    # start dygraph with all the states
    crime_wide <- reshape(
      crime_mexico$hd[,c("date","rate","state_code"),drop=F],
      v.names="rate",
      idvar = "date",
      timevar="state_code",
      direction="wide"
    )
    colnames(crime_wide) <- c("date",as.character(mexico$state))
    rownames(crime_wide) <- as.Date(crime_wide$date)
    dygraph( crime_wide[,-1])  %>%
      dyLegend( show = "never" )
  })

  observeEvent(input$dygraph1_date_window, {
    if(!is.null(input$dygraph1_date_window)){
      # get the new mean based on the range selected by dygraph
      mexico$filtered_rate <- crime_mexico$hd %>%
      filter( 
              as.Date(date) >= as.Date(input$dygraph1_date_window[[1]]),
              as.Date(date) <= as.Date(input$dygraph1_date_window[[2]])  
            ) %>%
      group_by( state_code ) %>%
      summarise( homicide = mean(rate) ) %>%
      ungroup() %>%
      select( homicide ) %>%
      unlist

      # leaflet comes with this nice feature leafletProxy
      #  to avoid rebuilding the whole map
      #  let's use it
      leafletProxy( "map1", data = mexico  ) %>%
        removeShape( layerId = ~id ) %>%
        addPolygons( fillColor = ~pal( filtered_rate ), 
                    fillOpacity = 0.8, 
                    color = "#BDBDC3", 
                    weight = 1,
                    layerId = ~id,
                    popup = paste0("<strong>Estado: </strong>", 
                        mexico$name, 
                        "<br><strong>Homicide Rate: </strong>", 
                        round(mexico$filtered_rate,2)
                    )
                    )
    }
  })

  observeEvent(input$map1_shape_click, {
    v$msg <- paste("Clicked shape", input$map1_shape_click$id)
    #  on our click let's update the dygraph to only show
    #    the time series for the clicked
    state_crime_data <- subset(crime_mexico$hd,state_code == input$map1_shape_click$id)
    rownames(state_crime_data) <- as.Date(state_crime_data$date)
    output$dygraph1 <- renderDygraph({
      dygraph(
        xts::as.xts(state_crime_data[,"rate",drop=F]),
        ylab = paste0(
          "homicide rate ",
          as.character(mexico$state[input$map1_shape_click$id])
        )
      )
    })
  })

}

shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)